]> git.saurik.com Git - wxWidgets.git/blobdiff - src/os2/radiobox.cpp
Added various #includes for non-precompiled headers.
[wxWidgets.git] / src / os2 / radiobox.cpp
index da582d0e52ef7fcb9755e3b355a3df8dda5785be..70a9a050e400b5b13c485d3009e0a67d6c1542c9 100644 (file)
 /////////////////////////////////////////////////////////////////////////////
 // Name:        radiobox.cpp
 // Purpose:     wxRadioBox
-// Author:      AUTHOR
+// Author:      David Webster
 // Modified by:
-// Created:     ??/??/98
+// Created:     10/12/99
 // RCS-ID:      $Id$
-// Copyright:   (c) AUTHOR
-// Licence:    wxWindows licence
+// Copyright:   (c) David Webster
+// Licence:     wxWindows licence
 /////////////////////////////////////////////////////////////////////////////
 
-#ifdef __GNUG__
-#pragma implementation "radiobox.h"
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifndef WX_PRECOMP
+    #include <stdio.h>
+    #include "wx/setup.h"
+    #include "wx/wxchar.h"
+    #include "wx/string.h"
+    #include "wx/bitmap.h"
+    #include "wx/brush.h"
+    #include "wx/radiobox.h"
 #endif
 
-#include "wx/radiobox.h"
+#include "wx/os2/private.h"
 
-#if !USE_SHARED_LIBRARY
 IMPLEMENT_DYNAMIC_CLASS(wxRadioBox, wxControl)
-#endif
+
+// ---------------------------------------------------------------------------
+// private functions
+// ---------------------------------------------------------------------------
+
+// wnd proc for radio buttons
+MRESULT EXPENTRY wxRadioBtnWndProc( HWND hWnd
+                                   ,UINT uMessage
+                                   ,MPARAM wParam
+                                   ,MPARAM lParam
+                                  );
+
+// ---------------------------------------------------------------------------
+// global vars
+// ---------------------------------------------------------------------------
+
+// the pointer to standard radio button wnd proc
+static WXFARPROC                    fnWndProcRadioBtn = NULL;
+
+// ===========================================================================
+// implementation
+// ===========================================================================
+
+// ---------------------------------------------------------------------------
+// wxRadioBox
+// ---------------------------------------------------------------------------
 
 // Radio box item
 wxRadioBox::wxRadioBox()
 {
-    m_selectedButton = -1;
-    m_noItems = 0;
-    m_noRowsOrCols = 0;
-    m_majorDim = 0 ;
-}
+    m_nSelectedButton = -1;
+    m_nNoItems = 0;
+    m_nNoRowsOrCols = 0;
+    m_ahRadioButtons = NULL;
+    m_nMajorDim = 0;
+    m_pnRadioWidth = NULL;
+    m_pnRadioHeight = NULL;
+} // end of wxRadioBox::wxRadioBox
 
-bool wxRadioBox::Create(wxWindow *parent, wxWindowID id, const wxString& title,
-             const wxPoint& pos, const wxSize& size,
-             int n, const wxString choices[],
-             int majorDim, long style,
-             const wxValidator& val, const wxString& name)
+wxRadioBox::~wxRadioBox()
 {
-    m_selectedButton = -1;
-    m_noItems = n;
+    m_isBeingDeleted = TRUE;
 
-    SetName(name);
-    SetValidator(val);
+    if (m_ahRadioButtons)
+    {
+        int                         i;
+        for (i = 0; i < m_nNoItems; i++)
+            ::WinDestroyWindow((HWND)m_ahRadioButtons[i]);
+        delete[] m_ahRadioButtons;
+    }
+    if (m_pnRadioWidth)
+        delete[] m_pnRadioWidth;
+    if (m_pnRadioHeight)
+        delete[] m_pnRadioHeight;
+} // end of wxRadioBox::~wxRadioBox
 
-    parent->AddChild(this);
+void wxRadioBox::AdjustButtons(
+  int                               nX
+, int                               nY
+, int                               nWidth
+, int                               nHeight
+, int                               nSizeFlags
+)
+{
+    wxSize                          vMaxSize;
+    int                             nXOffset = nX;
+    int                             nYOffset = nY + nHeight;
+    int                             nCx1;
+    int                             nCy1;
+    int                             nStartX;
+    int                             nStartY;
+    int                             nMaxWidth;
+    int                             nMaxHeight;
+    int                             nTotWidth;
+    int                             nTotHeight;
 
-    m_windowStyle = (long&)style;
+    wxGetCharSize( m_hWnd
+                  ,&nCx1
+                  ,&nCy1
+                  ,&GetFont()
+                 );
+    vMaxSize   = GetMaxButtonSize();
+    nMaxWidth  = vMaxSize.x;
+    nMaxHeight = vMaxSize.y;
 
-    if (id == -1)
-        m_windowId = NewControlId();
-    else
-        m_windowId = id;
+    nXOffset += nCx1;
+    nYOffset -= (nMaxHeight + ((3*nCy1)/2));
 
-    m_noRowsOrCols = majorDim;
+    nStartX = nXOffset;
+    nStartY = nYOffset;
 
-    if (majorDim==0)
-        m_majorDim = n ;
-    else
-        m_majorDim = majorDim ;
+    for (int i = 0; i < m_nNoItems; i++)
+    {
+        //
+        // The last button in the row may be wider than the other ones as the
+        // radiobox may be wider than the sum of the button widths (as it
+        // happens, for example, when the radiobox label is very long)
+        //
+        bool                        bIsLastInTheRow;
+
+        if (m_windowStyle & wxRA_SPECIFY_COLS)
+        {
+            //
+            // Item is the last in its row if it is a multiple of the number of
+            // columns or if it is just the last item
+            //
+            int                     n = i + 1;
+
+            bIsLastInTheRow = ((n % m_nMajorDim) == 0) || (n == m_nNoItems);
+        }
+        else // winRA_SPECIFY_ROWS
+        {
+            //
+            // Item is the last in the row if it is in the last columns
+            //
+            bIsLastInTheRow = i >= (m_nNoItems/m_nMajorDim) * m_nMajorDim;
+        }
+
+        //
+        // Is this the start of new row/column?
+        //
+        if (i && (i % m_nMajorDim == 0))
+        {
+            if (m_windowStyle & wxRA_SPECIFY_ROWS)
+            {
+
+                //
+                // Start of new column
+                //
+                nYOffset = nStartY;
+                nXOffset += nMaxWidth + nCx1;
+            }
+            else // start of new row
+            {
+                nXOffset = nStartX;
+                nYOffset -= nMaxHeight;
+                if (m_pnRadioWidth[0] > 0L)
+                    nYOffset -= nCy1/2;
+            }
+        }
+
+        int                         nWidthBtn;
 
+        if (bIsLastInTheRow)
+        {
+            //
+            // Make the button go to the end of radio box
+            //
+            nWidthBtn = nStartX + nWidth - nXOffset - (2 * nCx1);
+            if (nWidthBtn < nMaxWidth)
+                nWidthBtn = nMaxWidth;
+        }
+        else
+        {
+            //
+            // Normal button, always of the same size
+            //
+            nWidthBtn = nMaxWidth;
+        }
+
+        //
+        // Make all buttons of the same, maximal size - like this they
+        // cover the radiobox entirely and the radiobox tooltips are always
+        // shown (otherwise they are not when the mouse pointer is in the
+        // radiobox part not beYInt32ing to any radiobutton)
+        //
+        ::WinSetWindowPos( (HWND)m_ahRadioButtons[i]
+                          ,HWND_TOP
+                          ,(LONG)nXOffset
+                          ,(LONG)nYOffset
+                          ,(LONG)nWidthBtn
+                          ,(LONG)nMaxHeight
+                          ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
+                         );
+        //
+        // Where do we put the next button?
+        //
+        if (m_windowStyle & wxRA_SPECIFY_ROWS)
+        {
+            //
+            // Below this one
+            //
+            nYOffset -= nMaxHeight;
+            if (m_pnRadioWidth[0] > 0)
+                nYOffset -= nCy1/2;
+        }
+        else
+        {
+            //
+            // To the right of this one
+            //
+            nXOffset += nWidthBtn + nCx1;
+        }
+    }
+} // end of wxRadioBox::AdjustButtons
+
+void wxRadioBox::Command (
+  wxCommandEvent&                   rEvent
+)
+{
+    SetSelection (rEvent.GetInt());
+    ProcessCommand(rEvent);
+} // end of wxRadioBox::Command
+
+bool wxRadioBox::ContainsHWND(
+  WXHWND                            hWnd
+) const
+{
+    size_t                          nCount = GetCount();
+    size_t                          i;
 
-    // TODO create radiobox
+    for (i = 0; i < nCount; i++)
+    {
+        if (GetRadioButtons()[i] == hWnd)
+            return TRUE;
+    }
     return FALSE;
-}
+} // end of wxRadioBox::ContainsHWND
 
+bool wxRadioBox::Create(
+  wxWindow*                         pParent
+, wxWindowID                        vId
+, const wxString&                   rsTitle
+, const wxPoint&                    rPos
+, const wxSize&                     rSize
+, int                               nNum
+, const wxString                    asChoices[]
+, int                               nMajorDim
+, long                              lStyle
+#if wxUSE_VALIDATORS
+, const wxValidator&                rVal
+#endif
+, const wxString&                   rsName
+)
+{
+    //
+    // System fonts are too big in OS/2 and they are blue
+    // We want smaller fonts and black by default.
+    //
+    wxFont&                         rFont = *wxSMALL_FONT;
+    wxColour                        vColour;
+    LONG                            lColor;
 
-wxRadioBox::~wxRadioBox()
+    vColour.Set(wxString("BLACK"));
+    lColor = (LONG)vColour.GetPixel();
+    m_nSelectedButton = -1;
+    m_nNoItems        = nNum;
+
+    m_nMajorDim     = nMajorDim == 0 ? nNum : nMajorDim;
+    m_nNoRowsOrCols = nMajorDim;
+
+    //
+    // Common initialization
+    //
+    if (!OS2CreateControl( pParent
+                          ,vId
+                          ,rPos
+                          ,rSize
+                          ,lStyle
+#if wxUSE_VALIDATORS
+                          ,rVal
+#endif
+                          ,rsName
+                         ))
+
+
+
+
+    if (!OS2CreateControl( "STATIC"
+#if RADIOBTN_PARENT_IS_RADIOBOX
+                          ,SS_GROUPBOX | WS_GROUP | WS_CLIPCHILDREN
+#else
+                          ,SS_GROUPBOX | WS_GROUP | WS_CLIPSIBLINGS
+#endif
+                          ,rPos
+                          ,rSize
+                          ,rsTitle
+                         ))
+
+#if RADIOBTN_PARENT_IS_RADIOBOX
+    HWND                            hWndParent = GetHwnd();
+#else
+    HWND                            hWndParent = GetHwndOf(pParent);
+#endif
+    HFONT                           hFont;
+
+    //
+    // Some radio boxes test consecutive id.
+    //
+    (void)NewControlId();
+    m_ahRadioButtons = new WXHWND[nNum];
+    m_pnRadioWidth   = new int[nNum];
+    m_pnRadioHeight  = new int[nNum];
+
+    if (rFont.Ok())
+    {
+        hFont = rFont.GetResourceHandle();
+    }
+
+    for (int i = 0; i < nNum; i++)
+    {
+        m_pnRadioWidth[i] = m_pnRadioHeight[i] = -1;
+
+        long                        lStyleBtn = BS_AUTORADIOBUTTON | WS_TABSTOP | WS_VISIBLE;
+        int                         nNewId = NewControlId();
+
+        if (i == 0 && lStyle == 0)
+            lStyleBtn |= WS_GROUP;
+
+        HWND                        hWndBtn = (WXHWND)::WinCreateWindow ( GetHwndOf(pParent)
+                                                                         ,WC_BUTTON
+                                                                         ,asChoices[i]
+                                                                         ,lStyleBtn
+                                                                         ,0, 0, 0, 0
+                                                                         ,GetWinHwnd(pParent)
+                                                                         ,HWND_TOP
+                                                                         ,(HMENU)nNewId
+                                                                         ,NULL
+                                                                         ,NULL
+                                                                        );
+        lColor = (LONG)vColour.GetPixel();
+        ::WinSetPresParam( hWndBtn
+                          ,PP_FOREGROUNDCOLOR
+                          ,sizeof(LONG)
+                          ,(PVOID)&lColor
+                         );
+        lColor = (LONG)m_backgroundColour.GetPixel();
+
+        ::WinSetPresParam( hWndBtn
+                          ,PP_BACKGROUNDCOLOR
+                          ,sizeof(LONG)
+                          ,(PVOID)&lColor
+                         );
+        if (!hWndBtn)
+        {
+            return FALSE;
+        }
+        m_ahRadioButtons[i] = (WXHWND)hWndBtn;
+        SubclassRadioButton((WXHWND)hWndBtn);
+        wxOS2SetFont( hWndBtn
+                     ,rFont
+                    );
+        ::WinSetWindowULong(hWndBtn, QWL_USER, (ULONG)this);
+        m_aSubControls.Add(nNewId);
+    }
+
+    //
+    // Create a dummy radio control to end the group.
+    //
+    (void)::WinCreateWindow ( GetHwndOf(pParent)
+                             ,WC_BUTTON
+                             ,""
+                             ,WS_GROUP | BS_AUTORADIOBUTTON
+                             ,0, 0, 0, 0
+                             ,GetWinHwnd(pParent)
+                             ,HWND_TOP
+                             ,(HMENU)NewControlId()
+                             ,NULL
+                             ,NULL
+                            );
+     SetFont(*wxSMALL_FONT);
+    lColor = (LONG)vColour.GetPixel();
+    ::WinSetPresParam( m_hWnd
+                      ,PP_FOREGROUNDCOLOR
+                      ,sizeof(LONG)
+                      ,(PVOID)&lColor
+                     );
+    lColor = (LONG)m_backgroundColour.GetPixel();
+
+    ::WinSetPresParam( m_hWnd
+                      ,PP_BACKGROUNDCOLOR
+                      ,sizeof(LONG)
+                      ,(PVOID)&lColor
+                     );
+    SetSelection(0);
+    SetSize( rPos.x
+            ,rPos.y
+            ,rSize.x
+            ,rSize.y
+           );
+    return TRUE;
+} // end of wxRadioBox::Create
+
+wxSize wxRadioBox::DoGetBestSize() const
 {
-    // TODO
-}
+    return (GetTotalButtonSize(GetMaxButtonSize()));
+} // end of WinGuiBase_CRadioBox::DoGetBestSize
 
-wxString wxRadioBox::GetLabel(int item) const
+void wxRadioBox::DoSetSize(
+  int                               nX
+, int                               nY
+, int                               nWidth
+, int                               nHeight
+, int                               nSizeFlags
+)
 {
-    // TODO
-    return wxString("");
-}
+    int                             nCurrentX;
+    int                             nCurrentY;
+    int                             nWidthOld;
+    int                             nHeightOld;
+    int                             nXx = nX;
+    int                             nYy = nY;
+#if RADIOBTN_PARENT_IS_RADIOBOX
+    int                             nXOffset = 0;
+    int                             nYOffset = 0;
+#else
+    int                             nXOffset = nXx;
+    int                             nYOffset = nYy;
+#endif
+    int                             nCx1;
+    int                             nCy1;
+    wxSize                          vMaxSize = GetMaxButtonSize();
+    int                             nMaxWidth;
+    int                             nMaxHeight;
+    wxSize                          vTotSize;
+    int                             nTotWidth;
+    int                             nTotHeight;
+    int                             nStartX;
+    int                             nStartY;
+
+    m_nSizeFlags = nSizeFlags;
+    GetPosition( &nCurrentX
+                ,&nCurrentY
+               );
+    GetSize( &nWidthOld
+            ,&nHeightOld
+           );
+
+    if (nX == -1 && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+        nXx = nCurrentX;
+    if (nY == -1 && !(nSizeFlags & wxSIZE_ALLOW_MINUS_ONE))
+        nYy = nCurrentY;
+
+
+    wxGetCharSize( m_hWnd
+                  ,&nCx1
+                  ,&nCy1
+                  ,&GetFont()
+                 );
+
+    //
+    // Attempt to have a look coherent with other platforms: We compute the
+    // biggest toggle dim, then we align all items according this value.
+    //
+    vMaxSize   = GetMaxButtonSize();
+    nMaxWidth  = vMaxSize.x;
+    nMaxHeight = vMaxSize.y;
+
+    vTotSize   = GetTotalButtonSize(vMaxSize);
+    nTotWidth  = vTotSize.x;
+    nTotHeight = vTotSize.y;
+
+    //
+    // Only change our width/height if asked for
+    //
+    if (nWidth == -1)
+    {
+        if (nSizeFlags & wxSIZE_AUTO_WIDTH )
+            nWidth = nTotWidth;
+        else
+            nWidth = nWidthOld;
+    }
+
+    if (nHeight == -1)
+    {
+        if (nSizeFlags & wxSIZE_AUTO_HEIGHT)
+            nHeight = nTotHeight;
+        else
+            nHeight = nHeightOld;
+    }
+
+    wxWindowOS2*                    pParent = (wxWindowOS2*)GetParent();
+
+    if (pParent)
+    {
+        int                         nOS2Height = GetOS2ParentHeight(pParent);
+
+        nYy = nOS2Height - (nYy + nHeight);
+        nYOffset = nYy + nHeight;
+    }
+    else
+    {
+        RECTL                       vRect;
+
+        ::WinQueryWindowRect(HWND_DESKTOP, &vRect);
+        nYy = vRect.yTop - (nYy + nHeight);
+    }
+    ::WinSetWindowPos( GetHwnd()
+                      ,HWND_TOP
+                      ,(LONG)nXx
+                      ,(LONG)nYy
+                      ,(LONG)nWidth
+                      ,(LONG)nHeight
+                      ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
+                     );
+
+    //
+    // Now position all the buttons: the current button will be put at
+    // wxPoint(x_offset, y_offset) and the new row/column will start at
+    // startX/startY. The size of all buttons will be the same wxSize(maxWidth,
+    // maxHeight) except for the buttons in the last column which should extend
+    // to the right border of radiobox and thus can be wider than this.
+    //
+    // Also, remember that wxRA_SPECIFY_COLS means that we arrange buttons in
+    // left to right order and m_majorDim is the number of columns while
+    // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
+    // m_majorDim is the number of rows.
+    //
+    nXOffset += nCx1;
+    nYOffset -= (nMaxHeight + ((3*nCy1)/2));
 
-void wxRadioBox::SetLabel(int item, const wxString& label)
+    nStartX = nXOffset;
+    nStartY = nYOffset;
+
+    for (int i = 0; i < m_nNoItems; i++)
+    {
+        //
+        // The last button in the row may be wider than the other ones as the
+        // radiobox may be wider than the sum of the button widths (as it
+        // happens, for example, when the radiobox label is very long)
+        //
+        bool                        bIsLastInTheRow;
+
+        if (m_windowStyle & wxRA_SPECIFY_COLS)
+        {
+            //
+            // Item is the last in its row if it is a multiple of the number of
+            // columns or if it is just the last item
+            //
+            int                  n = i + 1;
+
+            bIsLastInTheRow = ((n % m_nMajorDim) == 0) || (n == m_nNoItems);
+        }
+        else // winRA_SPECIFY_ROWS
+        {
+            //
+            // Item is the last in the row if it is in the last columns
+            //
+            bIsLastInTheRow = i >= (m_nNoItems/m_nMajorDim) * m_nMajorDim;
+        }
+
+        //
+        // Is this the start of new row/column?
+        //
+        if (i && (i % m_nMajorDim == 0))
+        {
+            if (m_windowStyle & wxRA_SPECIFY_ROWS)
+            {
+
+                //
+                // Start of new column
+                //
+                nYOffset = nStartY;
+                nXOffset += nMaxWidth + nCx1;
+            }
+            else // start of new row
+            {
+                nXOffset = nStartX;
+                nYOffset -= nMaxHeight;
+                if (m_pnRadioWidth[0] > 0L)
+                    nYOffset -= nCy1/2;
+            }
+        }
+
+        int                      nWidthBtn;
+
+        if (bIsLastInTheRow)
+        {
+            //
+            // Make the button go to the end of radio box
+            //
+            nWidthBtn = nStartX + nWidth - nXOffset - (2 * nCx1);
+            if (nWidthBtn < nMaxWidth)
+                nWidthBtn = nMaxWidth;
+        }
+        else
+        {
+            //
+            // Normal button, always of the same size
+            //
+            nWidthBtn = nMaxWidth;
+        }
+
+        //
+        // Make all buttons of the same, maximal size - like this they
+        // cover the radiobox entirely and the radiobox tooltips are always
+        // shown (otherwise they are not when the mouse pointer is in the
+        // radiobox part not beinting to any radiobutton)
+        //
+        ::WinSetWindowPos( (HWND)m_ahRadioButtons[i]
+                          ,HWND_TOP
+                          ,(LONG)nXOffset
+                          ,(LONG)nYOffset
+                          ,(LONG)nWidthBtn
+                          ,(LONG)nMaxHeight
+                          ,SWP_ZORDER | SWP_SIZE | SWP_MOVE | SWP_SHOW
+                         );
+        //
+        // Where do we put the next button?
+        //
+        if (m_windowStyle & wxRA_SPECIFY_ROWS)
+        {
+            //
+            // Below this one
+            //
+            nYOffset -= nMaxHeight;
+            if (m_pnRadioWidth[0] > 0)
+                nYOffset -= nCy1/2;
+        }
+        else
+        {
+            //
+            // To the right of this one
+            //
+            nXOffset += nWidthBtn + nCx1;
+        }
+    }
+} // end of wxRadioBox::DoSetSize
+
+void wxRadioBox::Enable(
+  int                               nItem
+, bool                              bEnable
+)
 {
-    // TODO
-}
+    wxCHECK_RET( nItem >= 0 && nItem < m_nNoItems,
+                 wxT("invalid item in wxRadioBox::Enable()") );
+
+    ::WinEnableWindow((HWND) m_ahRadioButtons[nItem], bEnable);
+} // end of wxRadioBox::Enable
 
-int wxRadioBox::FindString(const wxString& s) const
+bool wxRadioBox::Enable(
+  bool                              bEnable
+)
 {
-    // TODO
-    return -1;
-}
+    if ( !wxControl::Enable(bEnable) )
+        return FALSE;
+    for (int i = 0; i < m_nNoItems; i++)
+        ::WinEnableWindow((HWND)m_ahRadioButtons[i], bEnable);
+    return TRUE;
+} // end of wxRadioBox::Enable
 
-void wxRadioBox::SetSelection(int n)
+int wxRadioBox::FindString(
+  const wxString&                   rsStr
+) const
 {
-    if ((n < 0) || (n >= m_noItems))
-        return;
-    // TODO
+    for (int i = 0; i < m_nNoItems; i++)
+    {
+        if (rsStr == wxGetWindowText(m_ahRadioButtons[i]) )
+            return i;
+    }
+    return wxNOT_FOUND;
+} // end of wxRadioBox::FindString
+
+int wxRadioBox::GetColumnCount() const
+{
+    return GetNumHor();
+} // end of wxRadioBox::GetColumnCount
+
+int wxRadioBox::GetCount() const
+{
+    return m_nNoItems;
+} // end of wxRadioBox::GetCount
 
-    m_selectedButton = n;
-}
+wxString wxRadioBox::GetLabel(
+  int                               nItem
+) const
+{
+    wxCHECK_MSG(nItem >= 0 && nItem < m_nNoItems, wxT(""), wxT("invalid radiobox index") );
+
+    return wxGetWindowText(m_ahRadioButtons[nItem]);
+} // end of wxRadioBox::GetLabel
+
+wxSize wxRadioBox::GetMaxButtonSize() const
+{
+    int                             nWidthMax = 0;
+    int                             nHeightMax = 0;
+
+    for (int i = 0 ; i < m_nNoItems; i++)
+    {
+        int                         nWidth;
+        int                         nHeight;
+
+        if (m_pnRadioWidth[i] < 0L)
+        {
+            GetTextExtent( wxGetWindowText(m_ahRadioButtons[i])
+                          ,&nWidth
+                          ,&nHeight
+                         );
+
+            //
+            // Adjust the size to take into account the radio box itself
+            // FIXME this is totally bogus!
+            //
+            nWidth  += RADIO_SIZE;
+            nHeight *= 3;
+            nHeight /= 2;
+        }
+        else
+        {
+            nWidth  = m_pnRadioWidth[i];
+            nHeight = m_pnRadioHeight[i];
+        }
+        if (nWidthMax < nWidth )
+            nWidthMax = nWidth;
+        if (nHeightMax < nHeight )
+            nHeightMax = nHeight;
+    }
+    return(wxSize( nWidthMax
+                  ,nHeightMax
+                 )
+          );
+} // end of wxRadioBox::GetMaxButtonSize
+
+int wxRadioBox::GetNumHor() const
+{
+    if ( m_windowStyle & wxRA_SPECIFY_ROWS )
+    {
+        return (m_nNoItems + m_nMajorDim - 1)/m_nMajorDim;
+    }
+    else
+    {
+        return m_nMajorDim;
+    }
+} // end of wxRadioBox::GetNumHor
+
+int wxRadioBox::GetNumVer() const
+{
+    if ( m_windowStyle & wxRA_SPECIFY_ROWS )
+    {
+        return m_nMajorDim;
+    }
+    else
+    {
+        return (m_nNoItems + m_nMajorDim - 1)/m_nMajorDim;
+    }
+} // end of wxRadioBox::GetNumVer
+
+void wxRadioBox::GetPosition(
+  int*                              pnX
+, int*                              pnY
+) const
+{
+    wxWindowOS2*                    pParent = GetParent();
+    RECT                            vRect = { -1, -1, -1, -1 };;
+    POINTL                          vPoint;
+    int                             i;
+
+    for (i = 0; i < m_nNoItems; i++)
+        wxFindMaxSize( m_ahRadioButtons[i]
+                      ,&vRect
+                     );
+    if (m_hWnd)
+        wxFindMaxSize( m_hWnd
+                      ,&vRect
+                     );
+
+    //
+    // Since we now have the absolute screen coords, if there's a parent we
+    // must subtract its top left corner
+    //
+    vPoint.x = vRect.xLeft;
+    vPoint.y = vRect.yTop;
+    if (pParent)
+    {
+        SWP                             vSwp;
+
+        ::WinQueryWindowPos((HWND)pParent->GetHWND(), &vSwp);
+        vPoint.x = vSwp.x;
+        vPoint.y = vSwp.y;
+    }
+
+    //
+    // We may be faking the client origin. So a window that's really at (0, 30)
+    // may appear (to wxWin apps) to be at (0, 0).
+    //
+    if (GetParent())
+    {
+        wxPoint                     vPt(GetParent()->GetClientAreaOrigin());
+
+        vPoint.x = vPt.x;
+        vPoint.y = vPt.y;
+    }
+    *pnX = vPoint.x;
+    *pnX = vPoint.y;
+} // end of wxRadioBox::GetPosition
+
+int wxRadioBox::GetRowCount() const
+{
+    return GetNumVer();
+} // end of wxRadioBox::GetRowCount
 
 // Get single selection, for single choice list items
 int wxRadioBox::GetSelection() const
 {
-    return m_selectedButton;
-}
+    return m_nSelectedButton;
+} // end of wxRadioBox::GetSelection
+
+void wxRadioBox::GetSize(
+  int*                              pnWidth
+, int*                              pnHeight
+) const
+{
+    RECT                            vRect;
+    int                             i;
+
+    vRect.xLeft   = -1;
+    vRect.xRight  = -1;
+    vRect.yTop    = -1;
+    vRect.yBottom = -1;
+
+    if (m_hWnd)
+        wxFindMaxSize( m_hWnd
+                      ,&vRect
+                     );
+
+    for (i = 0; i < m_nNoItems; i++)
+        wxFindMaxSize( m_ahRadioButtons[i]
+                      ,&vRect
+                     );
+
+    *pnWidth  = vRect.xRight - vRect.xLeft;
+    *pnHeight = vRect.yBottom - vRect.yTop;
+} // end of wxRadioBox::GetSize
 
 // Find string for position
-wxString wxRadioBox::GetString(int n) const
+wxString wxRadioBox::GetString(
+  int                               nNum
+) const
 {
-    // TODO
-    return wxString("");
-}
+    return wxGetWindowText(m_ahRadioButtons[nNum]);
+} // end of wxRadioBox::GetString
 
-void wxRadioBox::SetSize(int x, int y, int width, int height, int sizeFlags)
+// For single selection items only
+wxString wxRadioBox::GetStringSelection() const
 {
-    // TODO
-}
+    wxString                        sResult;
+    int                             nSel = GetSelection();
+
+    if (nSel > -1)
+        sResult = GetString(nSel);
+    return sResult;
+} // end of wxRadioBox::GetStringSelection
 
-void wxRadioBox::GetSize(int *width, int *height) const
+wxSize wxRadioBox::GetTotalButtonSize(
+  const wxSize&                     rSizeBtn
+) const
 {
-    // TODO
-}
+    int                             nCx1;
+    int                             nCy1;
+    int                             nExtraHeight;
+    int                             nHeight;
+    int                             nWidth;
+    int                             nWidthLabel;
+
+    wxGetCharSize( m_hWnd
+                  ,&nCx1
+                  ,&nCy1
+                  ,(wxFont*)&GetFont()
+                 );
+    nExtraHeight = nCy1;
 
-void wxRadioBox::GetPosition(int *x, int *y) const
+    nHeight = GetNumVer() * rSizeBtn.y + (2 * nCy1);
+    nWidth  = GetNumHor() * (rSizeBtn.x + nCx1) + nCx1;
+
+    //
+    // And also wide enough for its label
+    //
+    GetTextExtent( GetTitle()
+                  ,&nWidthLabel
+                  ,NULL
+                 );
+    nWidthLabel += RADIO_SIZE;
+    if (nWidthLabel > nWidth)
+        nWidth = nWidthLabel;
+
+    return(wxSize( nWidth
+                  ,nHeight
+                 )
+          );
+} // end of wxRadioBox::GetTotalButtonSize
+
+WXHBRUSH wxRadioBox::OnCtlColor(
+  WXHDC                             hwinDC
+, WXHWND                            hWnd
+, WXUINT                            uCtlColor
+, WXUINT                            uMessage
+, WXWPARAM                          wParam
+, WXLPARAM                          lParam
+)
 {
-    // TODO
-}
+    HPS                             hPS = (HPS)hwinDC; // pass in a PS handle in OS/2
+
+    if (GetParent()->GetTransparentBackground())
+        ::GpiSetBackMix(hPS, BM_LEAVEALONE);
+    else
+        ::GpiSetBackMix(hPS, BM_OVERPAINT);
+
+    wxColour                        vColBack = GetBackgroundColour();
 
-wxString wxRadioBox::GetLabel() const
+    ::GpiSetBackColor(hPS, vColBack.GetPixel());
+    ::GpiSetColor(hPS, vColBack.GetPixel());
+
+
+    wxBrush*                        pBrush = wxTheBrushList->FindOrCreateBrush( vColBack
+                                                                               ,wxSOLID
+                                                                              );
+    return ((WXHBRUSH)pBrush->GetResourceHandle());
+} // end of wxRadioBox::OnCtlColor
+
+bool wxRadioBox::OS2Command(
+  WXUINT                            uCmd
+, WXWORD                            wId
+)
 {
-    // TODO
-    return wxString("");
-}
+    int                             nSelectedButton = -1;
+
+    if (uCmd == BN_CLICKED)
+    {
+        if (wId == GetId())
+            return TRUE;
+
 
-void wxRadioBox::SetLabel(const wxString& label)
+        for (int i = 0; i < m_nNoItems; i++)
+        {
+            if (wId == wxGetWindowId(m_ahRadioButtons[i]))
+            {
+                nSelectedButton = i;
+                break;
+            }
+        }
+        if (nSelectedButton == -1)
+        {
+            //
+            // Just ignore it - due to a hack with WM_NCHITTEST handling in our
+            // wnd proc, we can receive dummy click messages when we click near
+            // the radiobox edge (this is ugly but Julian wouldn't let me get
+            // rid of this...)
+            return FALSE;
+        }
+        if (nSelectedButton != m_nSelectedButton)
+        {
+            m_nSelectedButton = nSelectedButton;
+            SendNotificationEvent();
+        }
+        return TRUE;
+    }
+    else
+        return FALSE;
+} // end of wxRadioBox::OS2Command
+
+void wxRadioBox::SendNotificationEvent()
 {
-    // TODO
-}
+    wxCommandEvent                  vEvent( wxEVT_COMMAND_RADIOBOX_SELECTED
+                                           ,m_windowId
+                                          );
+
+    vEvent.SetInt( m_nSelectedButton );
+    vEvent.SetString( GetString(m_nSelectedButton) );
+    vEvent.SetEventObject(this);
+    ProcessCommand(vEvent);
+} // end of wxRadioBox::SendNotificationEvent
 
 void wxRadioBox::SetFocus()
 {
-    // TODO
-}
+    if (m_nNoItems > 0)
+    {
+        if (m_nSelectedButton == -1)
+            ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[0]);
+        else
+            ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[m_nSelectedButton]);
+    }
+} // end of wxRadioBox::SetFocus
 
-bool wxRadioBox::Show(bool show)
+bool wxRadioBox::SetFont(
+  const wxFont&                     rFont
+)
 {
-    // TODO
-    return FALSE;
-}
+    if (!wxControl::SetFont(rFont))
+    {
+        //
+        // Nothing to do
+        //
+        return FALSE;
+    }
+    //
+    // Also set the font of our radio buttons
+    //
+    WXHFONT                         hFont = wxFont(rFont).GetResourceHandle();
 
-// Enable a specific button
-void wxRadioBox::Enable(int item, bool enable)
-{
-    // TODO
-}
+    for (int n = 0; n < (int)m_nNoItems; n++)
+    {
+        HWND                        hWndBtn = (HWND)m_ahRadioButtons[n];
+
+        wxOS2SetFont( hWndBtn
+                     ,rFont
+                    );
+        ::WinInvalidateRect(hWndBtn, NULL, FALSE);
+    }
+    return TRUE;
+} // end of wxRadioBox::SetFont
 
-// Enable all controls
-void wxRadioBox::Enable(bool enable)
+void wxRadioBox::SetSelection(
+  int                               nNum
+)
 {
-    wxControl::Enable(enable);
+    wxCHECK_RET( (nNum >= 0) && (nNum < m_nNoItems), wxT("invalid radiobox index") );
 
-    // TODO
-}
+    if (m_nSelectedButton >= 0 && m_nSelectedButton < m_nNoItems)
+        ::WinSendMsg((HWND)m_ahRadioButtons[m_nSelectedButton], BM_SETCHECK, (MPARAM)0, (MPARAM)0);
 
-// Show a specific button
-void wxRadioBox::Show(int item, bool show)
-{
-    // TODO
-}
+    ::WinSendMsg((HWND)m_ahRadioButtons[nNum], BM_SETCHECK, (MPARAM)1, (MPARAM)0);
+    ::WinSetFocus(HWND_DESKTOP, (HWND)m_ahRadioButtons[nNum]);
+    m_nSelectedButton = nNum;
+} // end of wxRadioBox::SetSelection
 
-// For single selection items only
-wxString wxRadioBox::GetStringSelection () const
+void wxRadioBox::SetString(
+  int                               nItem
+, const wxString&                   rsLabel
+)
 {
-    int sel = GetSelection ();
-    if (sel > -1)
-        return this->GetString (sel);
-    else
-        return wxString("");
-}
+    wxCHECK_RET( nItem >= 0 && nItem < m_nNoItems, wxT("invalid radiobox index") );
 
-bool wxRadioBox::SetStringSelection (const wxString& s)
+    m_pnRadioWidth[nItem] = m_pnRadioHeight[nItem] = -1;
+    ::WinSetWindowText((HWND)m_ahRadioButtons[nItem], rsLabel.c_str());
+} // end of wxRadioBox::SetString
+
+bool wxRadioBox::SetStringSelection(
+  const wxString&                   rsStr
+)
 {
-    int sel = FindString (s);
-    if (sel > -1)
+    int                             nSel = FindString(rsStr);
+
+    if (nSel > -1)
     {
-        SetSelection (sel);
+        SetSelection(nSel);
         return TRUE;
     }
     else
         return FALSE;
-}
+} // end of wxRadioBox::SetStringSelection
 
-void wxRadioBox::Command (wxCommandEvent & event)
+bool wxRadioBox::Show(
+  bool                              bShow
+)
 {
-    SetSelection (event.m_commandInt);
-    ProcessCommand (event);
-}
+    int                             nCmdShow = 0;
+
+    if (!wxControl::Show(bShow))
+        return FALSE;
+
+    for (int i = 0; i < m_nNoItems; i++)
+    {
+        ::WinShowWindow((HWND)m_ahRadioButtons[i], (BOOL)bShow);
+    }
+    return TRUE;
+} // end of wxRadioBox::Show
+
+// Show a specific button
+void wxRadioBox::Show(
+  int                               nItem
+, bool                              bShow
+)
+{
+    wxCHECK_RET( nItem >= 0 && nItem < m_nNoItems,
+                 wxT("invalid item in wxRadioBox::Show()") );
+
+    ::WinShowWindow((HWND)m_ahRadioButtons[nItem], bShow);
+} // end of wxRadioBox::Show
+
+void wxRadioBox::SubclassRadioButton(
+  WXHWND                            hWndBtn
+)
+{
+    HWND                            hwndBtn = (HWND)hWndBtn;
+
+    fnWndProcRadioBtn = (WXFARPROC)::WinSubclassWindow(hWndBtn, (PFNWP)wxRadioBtnWndProc);
+} // end of wxRadioBox::SubclassRadioButton
+
+MRESULT wxRadioBox::WindowProc(
+  WXUINT                            uMsg
+, WXWPARAM                          wParam
+, WXLPARAM                          lParam
+)
+{
+    return (wxControl::OS2WindowProc( uMsg
+                                     ,wParam
+                                     ,lParam
+                                    ));
+} // end of wxRadioBox::WindowProc
+
+// ---------------------------------------------------------------------------
+// window proc for radio buttons
+// ---------------------------------------------------------------------------
+
+MRESULT wxRadioBtnWndProc(
+  HWND                              hWnd
+, UINT                              uMessage
+, MPARAM                            wParam
+, MPARAM                            lParam
+)
+{
+    switch (uMessage)
+    {
+        case WM_CHAR:
+            {
+                USHORT                  uKeyFlags = SHORT1FROMMP((MPARAM)wParam);
+
+                if (!(uKeyFlags & KC_KEYUP)) // Key Down event
+                {
+                    if (uKeyFlags & KC_VIRTUALKEY)
+                    {
+                        wxRadioBox*             pRadiobox = (wxRadioBox *)::WinQueryWindowULong( hWnd
+                                                                                                ,QWL_USER
+                                                                                               );
+                        USHORT                  uVk = SHORT2FROMMP((MPARAM)lParam);
+                        bool                    bProcessed = TRUE;
+                        wxDirection             eDir;
+
+                        switch(uVk)
+                        {
+                            case VK_LEFT:
+                                eDir = wxDOWN;
+                                break;
+
+                            case VK_RIGHT:
+                                eDir = wxDOWN;
+                                break;
+
+                            case VK_DOWN:
+                                eDir = wxDOWN;
+                                break;
+
+                            case VK_UP:
+                                eDir = wxUP;
+                                break;
+
+                            default:
+                                bProcessed = FALSE;
+
+                                //
+                                // Just to suppress the compiler warning
+                                //
+                                eDir = wxALL;
+                        }
+
+                        if (bProcessed)
+                        {
+                            int             nSelOld = pRadiobox->GetSelection();
+                            int             nSelNew = pRadiobox->GetNextItem( nSelOld
+                                                                             ,eDir
+                                                                             ,pRadiobox->GetWindowStyleFlag()
+                                                                            );
+
+                            if (nSelNew != nSelOld)
+                            {
+                                pRadiobox->SetSelection(nSelNew);
+
+                                //
+                                // Emulate the button click
+                                //
+                                pRadiobox->SendNotificationEvent();
+                                return 0;
+                            }
+                        }
+                    }
+                }
+            }
+            break;
+    }
 
+    return fnWndProcRadioBtn( hWnd
+                             ,(ULONG)uMessage
+                             ,(MPARAM)wParam
+                             ,(MPARAM)lParam
+                            );
+} // end of wxRadioBtnWndProc