]> git.saurik.com Git - wxWidgets.git/blobdiff - src/univ/toolbar.cpp
Merge in from trunk r64802 - r68625
[wxWidgets.git] / src / univ / toolbar.cpp
index a6d53027834ae887af453e34206e5310f41c037a..da03781e9c06d6d37a9341225c66bdce9fc7dd03 100644 (file)
 
 #include "wx/univ/renderer.h"
 
+// ----------------------------------------------------------------------------
+// wxStdToolbarInputHandler: translates SPACE and ENTER keys and the left mouse
+// click into button press/release actions
+// ----------------------------------------------------------------------------
+
+class WXDLLEXPORT wxStdToolbarInputHandler : public wxStdInputHandler
+{
+public:
+    wxStdToolbarInputHandler(wxInputHandler *inphand);
+
+    virtual bool HandleKey(wxInputConsumer *consumer,
+                           const wxKeyEvent& event,
+                           bool pressed);
+    virtual bool HandleMouse(wxInputConsumer *consumer,
+                             const wxMouseEvent& event);
+    virtual bool HandleMouseMove(wxInputConsumer *consumer, const wxMouseEvent& event);
+    virtual bool HandleFocus(wxInputConsumer *consumer, const wxFocusEvent& event);
+    virtual bool HandleActivation(wxInputConsumer *consumer, bool activated);
+
+private:
+    wxWindow            *m_winCapture;
+    wxToolBarToolBase   *m_toolCapture;
+    wxToolBarToolBase   *m_toolLast;
+};
+
 // ----------------------------------------------------------------------------
 // constants
 // ----------------------------------------------------------------------------
@@ -79,8 +104,8 @@ public:
         m_underMouse = false;
     }
 
-    wxToolBarTool(wxToolBar *tbar, wxControl *control)
-        : wxToolBarToolBase(tbar, control)
+    wxToolBarTool(wxToolBar *tbar, wxControl *control, const wxString& label)
+        : wxToolBarToolBase(tbar, control, label)
     {
         // no position yet
         m_x =
@@ -165,9 +190,11 @@ bool wxToolBar::Create(wxWindow *parent,
         return false;
     }
 
+    FixupStyle();
+
     CreateInputHandler(wxINP_HANDLER_TOOLBAR);
 
-    SetBestSize(size);
+    SetInitialSize(size);
 
     return true;
 }
@@ -233,7 +260,7 @@ void wxToolBar::SetToolShortHelp(int id, const wxString& help)
 {
     wxToolBarToolBase *tool = FindById(id);
 
-    wxCHECK_RET( tool, _T("SetToolShortHelp: no such tool") );
+    wxCHECK_RET( tool, wxT("SetToolShortHelp: no such tool") );
 
     tool->SetShortHelp(help);
 }
@@ -263,59 +290,15 @@ bool wxToolBar::DoDeleteTool(size_t WXUNUSED(pos),
 
 void wxToolBar::DoEnableTool(wxToolBarToolBase *tool, bool enable)
 {
+#if wxUSE_IMAGE
     // created disabled-state bitmap on demand
-    if ( !enable && !tool->GetDisabledBitmap().Ok() )
+    if ( !enable && !tool->GetDisabledBitmap().IsOk() )
     {
-        wxImage image( tool->GetNormalBitmap().ConvertToImage() );
-
-        // TODO: don't hardcode 180
-        unsigned char bg_red = 180;
-        unsigned char bg_green = 180;
-        unsigned char bg_blue = 180;
-
-        unsigned char mask_red = image.GetMaskRed();
-        unsigned char mask_green = image.GetMaskGreen();
-        unsigned char mask_blue = image.GetMaskBlue();
-
-        bool has_mask = image.HasMask();
+        wxImage image(tool->GetNormalBitmap().ConvertToImage());
 
-        int x,y;
-        for (y = 0; y < image.GetHeight(); y++)
-        {
-            for (x = 0; x < image.GetWidth(); x++)
-            {
-                unsigned char red = image.GetRed(x,y);
-                unsigned char green = image.GetGreen(x,y);
-                unsigned char blue = image.GetBlue(x,y);
-                if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
-                {
-                    red = (unsigned char)((((wxInt32) red  - bg_red) >> 1) + bg_red);
-                    green = (unsigned char)((((wxInt32) green  - bg_green) >> 1) + bg_green);
-                    blue = (unsigned char)((((wxInt32) blue  - bg_blue) >> 1) + bg_blue);
-                    image.SetRGB( x, y, red, green, blue );
-                }
-            }
-        }
-
-        for (y = 0; y < image.GetHeight(); y++)
-        {
-            for (x = y % 2; x < image.GetWidth(); x += 2)
-            {
-                unsigned char red = image.GetRed(x,y);
-                unsigned char green = image.GetGreen(x,y);
-                unsigned char blue = image.GetBlue(x,y);
-                if (!has_mask || red != mask_red || green != mask_green || blue != mask_blue)
-                {
-                    red = (unsigned char)((((wxInt32) red  - bg_red) >> 1) + bg_red);
-                    green = (unsigned char)((((wxInt32) green  - bg_green) >> 1) + bg_green);
-                    blue = (unsigned char)((((wxInt32) blue  - bg_blue) >> 1) + bg_blue);
-                    image.SetRGB( x, y, red, green, blue );
-                }
-            }
-        }
-
-        tool->SetDisabledBitmap(image);
+        tool->SetDisabledBitmap(image.ConvertToGreyscale());
     }
+#endif // wxUSE_IMAGE
 
     RefreshTool(tool);
 }
@@ -345,9 +328,10 @@ wxToolBarToolBase *wxToolBar::CreateTool(int id,
                              clientData, shortHelp, longHelp);
 }
 
-wxToolBarToolBase *wxToolBar::CreateTool(wxControl *control)
+wxToolBarToolBase *
+wxToolBar::CreateTool(wxControl *control, const wxString& label)
 {
-    return new wxToolBarTool(this, control);
+    return new wxToolBarTool(this, control, label);
 }
 
 // ----------------------------------------------------------------------------
@@ -360,7 +344,7 @@ wxRect wxToolBar::GetToolRect(wxToolBarToolBase *toolBase) const
 
     wxRect rect;
 
-    wxCHECK_MSG( tool, rect, _T("GetToolRect: NULL tool") );
+    wxCHECK_MSG( tool, rect, wxT("GetToolRect: NULL tool") );
 
     // ensure that we always have the valid tool position
     if ( m_needsLayout )
@@ -440,7 +424,30 @@ bool wxToolBar::Realize()
     m_needsLayout = true;
     DoLayout();
 
-    SetBestSize(wxDefaultSize);
+    // the first item in the radio group is checked by default to be consistent
+    // with wxGTK and the menu radio items
+    int radioGroupCount = 0;
+
+    for ( wxToolBarToolsList::compatibility_iterator node = m_tools.GetFirst();
+          node;
+          node = node->GetNext() )
+    {
+        wxToolBarTool *tool = (wxToolBarTool*) node->GetData();
+
+        if ( !tool->IsButton() || tool->GetKind() != wxITEM_RADIO )
+        {
+            radioGroupCount = 0;
+            continue;
+        }
+
+        bool toggle = !radioGroupCount++;
+        if ( tool->Toggle(toggle) )
+        {
+            DoToggleTool(tool, toggle);
+        }
+    }
+
+    SetInitialSize(wxDefaultSize);
 
     return true;
 }
@@ -456,7 +463,7 @@ void wxToolBar::SetWindowStyleFlag( long style )
 
 void wxToolBar::DoLayout()
 {
-    wxASSERT_MSG( m_needsLayout, _T("why are we called?") );
+    wxASSERT_MSG( m_needsLayout, wxT("why are we called?") );
 
     m_needsLayout = false;
 
@@ -580,13 +587,7 @@ void wxToolBar::DoSetSize(int x, int y, int width, int height, int sizeFlags)
     // otherwise the toolbar can be shown incorrectly
     if ( old_width != width || old_height != height )
     {
-        // But before we send the size event check it
-        // we have a frame that is not being deleted.
-        wxFrame *frame = wxDynamicCast(GetParent(), wxFrame);
-        if ( frame && !frame->IsBeingDeleted() )
-        {
-            frame->SendSizeEvent();
-        }
+        SendSizeEventToParent();
     }
 }
 
@@ -603,7 +604,7 @@ void wxToolBar::GetRectLimits(const wxRect& rect,
                               wxCoord *start,
                               wxCoord *end) const
 {
-    wxCHECK_RET( start && end, _T("NULL pointer in GetRectLimits") );
+    wxCHECK_RET( start && end, wxT("NULL pointer in GetRectLimits") );
 
     if ( IsVertical() )
     {
@@ -690,26 +691,26 @@ void wxToolBar::DoDraw(wxControlRenderer *renderer)
         {
             label = tool->GetLabel();
             bitmap = tool->GetBitmap();
+
+            if ( !bitmap.IsOk() )
+            {
+                // it's better not to draw anything than to assert inside
+                // drawing code as this results in an almost guaranteed crash
+                // as we're likely to be called by a paint event handler and so
+                // the assert is going to be triggered again and again and ...
+                continue;
+            }
         }
         //else: leave both the label and the bitmap invalid to draw a separator
 
         if ( !tool->IsControl() )
         {
-            int tbStyle = 0;
-            if(HasFlag(wxTB_TEXT))
-            {
+            int tbStyle = HasFlag(wxTB_VERTICAL) ? wxTB_VERTICAL : wxTB_HORIZONTAL;
+            if ( HasFlag(wxTB_TEXT) )
                 tbStyle |= wxTB_TEXT;
-            }
 
-            if(HasFlag(wxTB_VERTICAL))
-            {
-                tbStyle |= wxTB_VERTICAL;
-            }
-            else
-            {
-                tbStyle |= wxTB_HORIZONTAL;
-            }
-            rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags, tool->GetStyle(), tbStyle);
+            rend->DrawToolBarButton(dc, label, bitmap, rectTool, flags,
+                                    tool->GetStyle(), tbStyle);
         }
         else // control
         {
@@ -737,25 +738,13 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
 
         PerformAction( wxACTION_BUTTON_CLICK, numArg );
 
-        // Write by Danny Raynor to change state again.
-        // Check button still pressed or not
-        if ( tool->CanBeToggled() && tool->IsToggled() )
-        {
-            tool->Toggle(false);
-        }
-
-        if( tool->IsInverted() )
-        {
-            PerformAction( wxACTION_TOOLBAR_RELEASE, numArg );
-        }
-
         // Set mouse leave toolbar button range (If still in the range,
         // toolbar button would get focus again
         PerformAction( wxACTION_TOOLBAR_LEAVE, numArg );
     }
     else if ( action == wxACTION_TOOLBAR_PRESS )
     {
-        wxLogTrace(_T("toolbar"), _T("Button '%s' pressed."), tool->GetShortHelp().c_str());
+        wxLogTrace(wxT("toolbar"), wxT("Button '%s' pressed."), tool->GetShortHelp().c_str());
 
         tool->Invert();
 
@@ -763,11 +752,14 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
     }
     else if ( action == wxACTION_TOOLBAR_RELEASE )
     {
-        wxLogTrace(_T("toolbar"), _T("Button '%s' released."), tool->GetShortHelp().c_str());
+        wxLogTrace(wxT("toolbar"), wxT("Button '%s' released."), tool->GetShortHelp().c_str());
 
-        wxASSERT_MSG( tool->IsInverted(), _T("release unpressed button?") );
+        wxASSERT_MSG( tool->IsInverted(), wxT("release unpressed button?") );
 
-        tool->Invert();
+        if(tool->IsInverted())
+        {
+            tool->Invert();
+        }
 
         RefreshTool( tool );
     }
@@ -776,7 +768,15 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
         bool isToggled;
         if ( tool->CanBeToggled() )
         {
-            tool->Toggle();
+            if ( tool->IsButton() && tool->GetKind() == wxITEM_RADIO )
+            {
+                UnToggleRadioGroup(tool);
+                tool->Toggle(true);
+            }
+            else
+            {
+                tool->Toggle();
+            }
 
             RefreshTool( tool );
 
@@ -790,7 +790,7 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
     }
     else if ( action == wxACTION_TOOLBAR_ENTER )
     {
-        wxCHECK_MSG( tool, false, _T("no tool to enter?") );
+        wxCHECK_MSG( tool, false, wxT("no tool to enter?") );
 
         if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
         {
@@ -802,7 +802,7 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
     }
     else if ( action == wxACTION_TOOLBAR_LEAVE )
     {
-        wxCHECK_MSG( tool, false, _T("no tool to leave?") );
+        wxCHECK_MSG( tool, false, wxT("no tool to leave?") );
 
         if ( HasFlag(wxTB_FLAT) && tool->IsEnabled() )
         {
@@ -818,6 +818,14 @@ bool wxToolBar::PerformAction(const wxControlAction& action,
     return true;
 }
 
+/* static */
+wxInputHandler *wxToolBar::GetStdInputHandler(wxInputHandler *handlerDef)
+{
+    static wxStdToolbarInputHandler s_handler(handlerDef);
+
+    return &s_handler;
+}
+
 // ============================================================================
 // wxStdToolbarInputHandler implementation
 // ============================================================================