]> git.saurik.com Git - wxWidgets.git/blobdiff - src/msw/radiobox.cpp
Use the data scheme to load resources in the WebKitGTK+ implementation, rather than...
[wxWidgets.git] / src / msw / radiobox.cpp
index cdf514108516ca6659673b6f31121f45cfe9c54b..de869045c1114c5a63bb391dd69d3a23f7da0d90 100644 (file)
@@ -29,6 +29,7 @@
 #include "wx/radiobox.h"
 
 #ifndef WX_PRECOMP
+    #include "wx/hashmap.h"
     #include "wx/bitmap.h"
     #include "wx/brush.h"
     #include "wx/settings.h"
@@ -74,10 +75,7 @@ wxBEGIN_FLAGS( wxRadioBoxStyle )
     wxFLAGS_MEMBER(wxHSCROLL)
 
     wxFLAGS_MEMBER(wxRA_SPECIFY_COLS)
-    wxFLAGS_MEMBER(wxRA_HORIZONTAL)
     wxFLAGS_MEMBER(wxRA_SPECIFY_ROWS)
-    wxFLAGS_MEMBER(wxRA_VERTICAL)
-
 wxEND_FLAGS( wxRadioBoxStyle )
 
 IMPLEMENT_DYNAMIC_CLASS_XTI(wxRadioBox, wxControl,"wx/radiobox.h")
@@ -113,13 +111,34 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hWnd,
 // global vars
 // ---------------------------------------------------------------------------
 
+namespace
+{
+
 // the pointer to standard radio button wnd proc
-static WXFARPROC s_wndprocRadioBtn = (WXFARPROC)NULL;
+WXFARPROC s_wndprocRadioBtn = (WXFARPROC)NULL;
+
+// Hash allowing to find wxRadioBox containing the given radio button by its
+// HWND. This is used by (subclassed) radio button window proc to find the
+// radio box it belongs to.
+WX_DECLARE_HASH_MAP(HWND, wxRadioBox *,
+                    wxPointerHash, wxPointerEqual,
+                    RadioBoxFromButton);
+
+RadioBoxFromButton gs_boxFromButton;
+
+} // anonymous namespace
 
 // ===========================================================================
 // implementation
 // ===========================================================================
 
+/* static */
+wxRadioBox* wxRadioBox::GetFromRadioButtonHWND(WXHWND hwnd)
+{
+    const RadioBoxFromButton::const_iterator it = gs_boxFromButton.find(hwnd);
+    return it == gs_boxFromButton.end() ? NULL : it->second;
+}
+
 // ---------------------------------------------------------------------------
 // wxRadioBox creation
 // ---------------------------------------------------------------------------
@@ -183,7 +202,7 @@ bool wxRadioBox::Create(wxWindow *parent,
 
         wxWindowIDRef subid = NewControlId();
 
-        HWND hwndBtn = ::CreateWindow(_T("BUTTON"),
+        HWND hwndBtn = ::CreateWindow(wxT("BUTTON"),
                                       choices[i].wx_str(),
                                       styleBtn,
                                       0, 0, 0, 0,   // will be set in SetSize()
@@ -211,7 +230,7 @@ bool wxRadioBox::Create(wxWindow *parent,
     // Create a dummy radio control to end the group.
     m_dummyId = NewControlId();
 
-    m_dummyHwnd = (WXHWND)::CreateWindow(_T("BUTTON"),
+    m_dummyHwnd = (WXHWND)::CreateWindow(wxT("BUTTON"),
                          wxEmptyString,
                          WS_GROUP | BS_AUTORADIOBUTTON | WS_CHILD,
                          0, 0, 0, 0, GetHwndOf(parent),
@@ -256,9 +275,23 @@ wxRadioBox::~wxRadioBox()
 {
     SendDestroyEvent();
 
+    // Unsubclass all the radio buttons and remove their soon-to-be-invalid
+    // HWNDs from the global map. Notice that we need to unsubclass because
+    // otherwise we'd need the entries in gs_boxFromButton for the buttons
+    // being deleted to handle the messages generated during their destruction.
+    for ( size_t item = 0; item < m_radioButtons->GetCount(); item++ )
+    {
+        HWND hwnd = m_radioButtons->Get(item);
+
+        wxSetWindowProc(hwnd, reinterpret_cast<WNDPROC>(s_wndprocRadioBtn));
+        gs_boxFromButton.erase(hwnd);
+    }
+
     delete m_radioButtons;
+
     if ( m_dummyHwnd )
         DestroyWindow((HWND)m_dummyHwnd);
+
     delete[] m_radioWidth;
     delete[] m_radioHeight;
 }
@@ -273,7 +306,8 @@ void wxRadioBox::SubclassRadioButton(WXHWND hWndBtn)
         s_wndprocRadioBtn = (WXFARPROC)wxGetWindowProc(hwndBtn);
 
     wxSetWindowProc(hwndBtn, wxRadioBtnWndProc);
-    wxSetWindowUserData(hwndBtn, this);
+
+    gs_boxFromButton[hwndBtn] = this;
 }
 
 // ----------------------------------------------------------------------------
@@ -406,7 +440,7 @@ bool wxRadioBox::Enable(unsigned int item, bool enable)
     wxCHECK_MSG( IsValid(item), false,
                  wxT("invalid item in wxRadioBox::Enable()") );
 
-    BOOL ret = ::EnableWindow((*m_radioButtons)[item], enable);
+    BOOL ret = MSWEnableHWND((*m_radioButtons)[item], enable);
 
     return (ret == 0) != enable;
 }
@@ -462,7 +496,9 @@ void wxRadioBox::DoSetItemToolTip(unsigned int item, wxToolTip *tooltip)
     if ( tooltip != NULL )
         tooltip->Add(hwndRbtn);
     else // unset the tooltip
-        wxToolTip::Remove(hwndRbtn);
+        wxToolTip::Remove(hwndRbtn, 0, wxRect(0,0,0,0));
+        // the second parameter can be zero since it's ignored by Remove()
+        // as we pass a rect for which wxRect::IsEmpty()==true...
 }
 
 #endif // wxUSE_TOOLTIPS
@@ -565,57 +601,34 @@ wxSize wxRadioBox::DoGetBestSize() const
     return best;
 }
 
-// Restored old code.
 void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
 {
-    int currentX, currentY;
-    GetPosition(&currentX, &currentY);
-    int widthOld, heightOld;
-    GetSize(&widthOld, &heightOld);
+    if ( (width == wxDefaultCoord && (sizeFlags & wxSIZE_AUTO_WIDTH)) ||
+            (height == wxDefaultCoord && (sizeFlags & wxSIZE_AUTO_HEIGHT)) )
+    {
+        // Attempt to have a look coherent with other platforms: We compute the
+        // biggest toggle dim, then we align all items according this value.
+        const wxSize totSize = GetTotalButtonSize(GetMaxButtonSize());
 
-    int xx = x;
-    int yy = y;
+        // only change our width/height if asked for
+        if ( width == wxDefaultCoord && (sizeFlags & wxSIZE_AUTO_WIDTH) )
+            width = totSize.x;
 
-    if (x == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
-        xx = currentX;
-    if (y == wxDefaultCoord && !(sizeFlags & wxSIZE_ALLOW_MINUS_ONE))
-        yy = currentY;
+        if ( height == wxDefaultCoord && (sizeFlags & wxSIZE_AUTO_HEIGHT) )
+            height = totSize.y;
+    }
 
-    int y_offset = yy;
-    int x_offset = xx;
+    wxStaticBox::DoSetSize(x, y, width, height);
+}
 
-    int cx1, cy1;
-    wxGetCharSize(m_hWnd, &cx1, &cy1, GetFont());
+void wxRadioBox::DoMoveWindow(int x, int y, int width, int height)
+{
+    wxStaticBox::DoMoveWindow(x, y, width, height);
 
-    // Attempt to have a look coherent with other platforms: We compute the
-    // biggest toggle dim, then we align all items according this value.
     wxSize maxSize = GetMaxButtonSize();
     int maxWidth = maxSize.x,
         maxHeight = maxSize.y;
 
-    wxSize totSize = GetTotalButtonSize(maxSize);
-    int totWidth = totSize.x,
-        totHeight = totSize.y;
-
-    // only change our width/height if asked for
-    if ( width == wxDefaultCoord )
-    {
-        if ( sizeFlags & wxSIZE_AUTO_WIDTH )
-            width = totWidth;
-        else
-            width = widthOld;
-    }
-
-    if ( height == wxDefaultCoord )
-    {
-        if ( sizeFlags & wxSIZE_AUTO_HEIGHT )
-            height = totHeight;
-        else
-            height = heightOld;
-    }
-
-    DoMoveWindow(xx, yy, width, height);
-
     // 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,
@@ -627,8 +640,11 @@ void wxRadioBox::DoSetSize(int x, int y, int width, int height, int sizeFlags)
     // wxRA_SPECIFY_ROWS means that the buttons are arranged top to bottom and
     // GetMajorDim() is the number of rows.
 
-    x_offset += cx1;
-    y_offset += cy1;
+    int cx1, cy1;
+    wxGetCharSize(m_hWnd, &cx1, &cy1, GetFont());
+
+    int x_offset = x + cx1;
+    int y_offset = y + cy1;
 
     // Add extra space under the label, if it exists.
     if (!wxControl::GetLabel().empty())
@@ -766,6 +782,10 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
                                            WPARAM wParam,
                                            LPARAM lParam)
 {
+
+    wxRadioBox * const radiobox = wxRadioBox::GetFromRadioButtonHWND(hwnd);
+    wxCHECK_MSG( radiobox, 0, wxT("Should have the associated radio box") );
+
     switch ( message )
     {
         case WM_GETDLGCODE:
@@ -781,10 +801,6 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
 
         case WM_KEYDOWN:
             {
-                wxRadioBox *radiobox = (wxRadioBox *)wxGetWindowUserData(hwnd);
-
-                wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
-
                 bool processed = true;
 
                 wxDirection dir;
@@ -840,10 +856,6 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
         case WM_SETFOCUS:
         case WM_KILLFOCUS:
             {
-                wxRadioBox *radiobox = (wxRadioBox *)wxGetWindowUserData(hwnd);
-
-                wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
-
                 // if we don't do this, no focus events are generated for the
                 // radiobox and, besides, we need to notify the parent about
                 // the focus change, otherwise the focus handling logic in
@@ -858,10 +870,6 @@ LRESULT APIENTRY _EXPORT wxRadioBtnWndProc(HWND hwnd,
 #ifndef __WXWINCE__
         case WM_HELP:
             {
-                wxRadioBox *radiobox = (wxRadioBox *)wxGetWindowUserData(hwnd);
-
-                wxCHECK_MSG( radiobox, 0, wxT("radio button without radio box?") );
-
                 bool processed = false;
 
                 wxEvtHandler * const handler = radiobox->GetEventHandler();