]> git.saurik.com Git - wxWidgets.git/blobdiff - src/ribbon/toolbar.cpp
Use CFSocket instead of CFFileDescriptor in wxCFEventLoopSource.
[wxWidgets.git] / src / ribbon / toolbar.cpp
index 945204f269feb58fd2c62f179c1d8ac9fb9ca43f..55a6c152ae814781b4afab240f915f13130f1fed 100644 (file)
     #pragma hdrstop
 #endif
 
-#include "wx/ribbon/toolbar.h"
-
 #if wxUSE_RIBBON
 
+#include "wx/ribbon/toolbar.h"
 #include "wx/ribbon/art.h"
 #include "wx/ribbon/bar.h"
 #include "wx/dcbuffer.h"
@@ -45,7 +44,7 @@ public:
     long state;
 };
 
-WX_DEFINE_ARRAY(wxRibbonToolBarToolBase*, wxArrayRibbonToolBarToolBase);
+WX_DEFINE_ARRAY_PTR(wxRibbonToolBarToolBase*, wxArrayRibbonToolBarToolBase);
 
 class wxRibbonToolBarToolGroup
 {
@@ -58,8 +57,8 @@ public:
     wxSize size;
 };
 
-wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_CLICKED, wxRibbonToolBarEvent);
-wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED, wxRibbonToolBarEvent);
+wxDEFINE_EVENT(wxEVT_RIBBONTOOLBAR_CLICKED, wxRibbonToolBarEvent);
+wxDEFINE_EVENT(wxEVT_RIBBONTOOLBAR_DROPDOWN_CLICKED, wxRibbonToolBarEvent);
 
 IMPLEMENT_DYNAMIC_CLASS(wxRibbonToolBarEvent, wxCommandEvent)
 IMPLEMENT_CLASS(wxRibbonToolBar, wxRibbonControl)
@@ -162,6 +161,15 @@ wxRibbonToolBarToolBase* wxRibbonToolBar::AddHybridTool(
         wxRIBBON_BUTTON_HYBRID, NULL);
 }
 
+wxRibbonToolBarToolBase* wxRibbonToolBar::AddToggleTool(
+        int tool_id,
+        const wxBitmap& bitmap,
+        const wxString& help_string)
+{
+    return AddTool(tool_id, bitmap, wxNullBitmap, help_string,
+        wxRIBBON_BUTTON_TOGGLE, NULL);
+}
+
 wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
             int tool_id,
             const wxBitmap& bitmap,
@@ -169,9 +177,74 @@ wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
             const wxString& help_string,
             wxRibbonButtonKind kind,
             wxObject* client_data)
+{
+    return InsertTool(GetToolCount(), tool_id, bitmap, bitmap_disabled,
+        help_string, kind, client_data);
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::AddSeparator()
+{
+    if(m_groups.Last()->tools.IsEmpty())
+        return NULL;
+
+    AppendGroup();
+    return &m_groups.Last()->dummy_tool;
+}
+
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::InsertTool(
+                size_t pos,
+                int tool_id,
+                const wxBitmap& bitmap,
+                const wxString& help_string,
+                wxRibbonButtonKind kind)
+{
+    return InsertTool(pos, tool_id, bitmap, wxNullBitmap, help_string, kind,
+        NULL);
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::InsertDropdownTool(
+            size_t pos,
+            int tool_id,
+            const wxBitmap& bitmap,
+            const wxString& help_string)
+{
+    return InsertTool(pos, tool_id, bitmap, wxNullBitmap, help_string,
+        wxRIBBON_BUTTON_DROPDOWN, NULL);
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::InsertHybridTool(
+            size_t pos,
+            int tool_id,
+            const wxBitmap& bitmap,
+            const wxString& help_string)
+{
+    return InsertTool(pos, tool_id, bitmap, wxNullBitmap, help_string,
+        wxRIBBON_BUTTON_HYBRID, NULL);
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::InsertToggleTool(
+        size_t pos,
+        int tool_id,
+        const wxBitmap& bitmap,
+        const wxString& help_string)
+{
+    return InsertTool(pos, tool_id, bitmap, wxNullBitmap, help_string,
+        wxRIBBON_BUTTON_TOGGLE, NULL);
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::InsertTool(
+            size_t pos,
+            int tool_id,
+            const wxBitmap& bitmap,
+            const wxBitmap& bitmap_disabled,
+            const wxString& help_string,
+            wxRibbonButtonKind kind,
+            wxObject* client_data)
 {
     wxASSERT(bitmap.IsOk());
 
+    // Create the wxRibbonToolBarToolBase with parameters
     wxRibbonToolBarToolBase* tool = new wxRibbonToolBarToolBase;
     tool->id = tool_id;
     tool->bitmap = bitmap;
@@ -189,19 +262,257 @@ wxRibbonToolBarToolBase* wxRibbonToolBar::AddTool(
     tool->size = wxSize(0, 0);
     tool->state = 0;
 
-    m_groups.Last()->tools.Add(tool);
-    return tool;
+    // Find the position where insert tool
+    size_t group_count = m_groups.GetCount();
+    size_t g;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        if(pos <= tool_count)
+        {
+            group->tools.Insert(tool, pos);
+            return tool;
+        }
+        pos -= tool_count + 1;
+    }
+    wxFAIL_MSG("Tool position out of toolbar bounds.");
+    return NULL;
 }
 
-wxRibbonToolBarToolBase* wxRibbonToolBar::AddSeparator()
+wxRibbonToolBarToolBase* wxRibbonToolBar::InsertSeparator(size_t pos)
 {
+    size_t group_count = m_groups.GetCount();
+    size_t g;
+    for(g = 0; g < group_count; ++g)
+    {
+        if(pos==0) // Prepend group
+            return &InsertGroup(g)->dummy_tool;
+        if(pos==group_count) // Append group
+            return &InsertGroup(g+1)->dummy_tool;
+
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        if(pos < tool_count)
+        {
+            wxRibbonToolBarToolGroup* new_group = InsertGroup(g+1);
+
+            for(size_t t = pos; t < tool_count; t++)
+                new_group->tools.Add(group->tools[t]);
+            group->tools.RemoveAt(pos, tool_count-pos);
+
+            return &group->dummy_tool;
+        }
+        pos -= tool_count + 1;
+    }
+    // Add an empty group at the end of the bar.
     if(m_groups.Last()->tools.IsEmpty())
         return NULL;
-
     AppendGroup();
     return &m_groups.Last()->dummy_tool;
 }
 
+wxRibbonToolBarToolGroup* wxRibbonToolBar::InsertGroup(size_t pos)
+{
+    wxRibbonToolBarToolGroup* group = new wxRibbonToolBarToolGroup;
+    group->position = wxPoint(0, 0);
+    group->size = wxSize(0, 0);
+    m_groups.Insert(group, pos);
+    return group;
+}
+
+void wxRibbonToolBar::ClearTools()
+{
+    size_t count = m_groups.GetCount();
+    size_t i, t;
+    for(i = 0; i < count; ++i)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(i);
+        size_t tool_count = group->tools.GetCount();
+        for(t = 0; t < tool_count; ++t)
+        {
+            wxRibbonToolBarToolBase* tool = group->tools.Item(t);
+            delete tool;
+        }
+        delete group;
+    }
+    m_groups.Clear();
+}
+
+bool wxRibbonToolBar::DeleteTool(int tool_id)
+{
+    size_t group_count = m_groups.GetCount();
+    size_t g, t;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        for(t = 0; t < tool_count; ++t)
+        {
+            wxRibbonToolBarToolBase* tool = group->tools.Item(t);
+            if(tool->id == tool_id)
+            {
+                group->tools.RemoveAt(t);
+                delete tool;
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+bool wxRibbonToolBar::DeleteToolByPos(size_t pos)
+{
+    size_t group_count = m_groups.GetCount();
+    size_t g, t;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        if(pos<tool_count)
+        {
+            // Remove tool
+            wxRibbonToolBarToolBase* tool = group->tools.Item(pos);
+            group->tools.RemoveAt(pos);
+            delete tool;
+            return true;
+        }
+        else if(pos==tool_count)
+        {
+            // Remove separator
+            if(g < group_count - 1)
+            {
+                wxRibbonToolBarToolGroup* next_group = m_groups.Item(g+1);
+                for(t = 0; t < next_group->tools.GetCount(); ++t)
+                    group->tools.Add(next_group->tools[t]);
+                m_groups.RemoveAt(g+1);
+                delete next_group;
+            }
+            return true;
+        }
+    }
+    return false;
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::FindById(int tool_id)const
+{
+    size_t group_count = m_groups.GetCount();
+    size_t g, t;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        for(t = 0; t < tool_count; ++t)
+        {
+            wxRibbonToolBarToolBase* tool = group->tools.Item(t);
+            if(tool->id == tool_id)
+            {
+                return tool;
+            }
+        }
+    }
+    return NULL;
+}
+
+wxRibbonToolBarToolBase* wxRibbonToolBar::GetToolByPos(size_t pos)const
+{
+    size_t group_count = m_groups.GetCount();
+    size_t g;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        if(pos<tool_count)
+        {
+            return group->tools[pos];
+        }
+        else if(pos==tool_count)
+        {
+            return NULL;
+        }
+    }
+    return NULL;
+}
+
+size_t wxRibbonToolBar::GetToolCount() const
+{
+    size_t count = 0;
+    for(size_t g = 0; g < m_groups.GetCount(); ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        count += group->tools.GetCount();
+    }
+    // There is a splitter in front of every group except for the first
+    // If only one group, no separator.
+    if(m_groups.GetCount()>1)
+        count += m_groups.GetCount() - 1;
+    return count;
+}
+
+int wxRibbonToolBar::GetToolId(const wxRibbonToolBarToolBase* tool)const
+{
+    wxCHECK_MSG(tool != NULL , wxNOT_FOUND, "The tool pointer must not be NULL");
+    return tool->id;
+}
+
+wxObject* wxRibbonToolBar::GetToolClientData(int tool_id)const
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_MSG(tool != NULL , NULL, "Invalid tool id");
+    return tool->client_data;
+}
+
+bool wxRibbonToolBar::GetToolEnabled(int tool_id)const
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_MSG(tool != NULL , false, "Invalid tool id");
+    return (tool->state & wxRIBBON_TOOLBAR_TOOL_DISABLED) == 0;
+}
+
+wxString wxRibbonToolBar::GetToolHelpString(int tool_id)const
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_MSG(tool != NULL , wxEmptyString, "Invalid tool id");
+    return tool->help_string;
+}
+
+wxRibbonButtonKind wxRibbonToolBar::GetToolKind(int tool_id)const
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_MSG(tool != NULL , wxRIBBON_BUTTON_NORMAL, "Invalid tool id");
+    return tool->kind;
+}
+
+int wxRibbonToolBar::GetToolPos(int tool_id)const
+{
+    size_t group_count = m_groups.GetCount();
+    size_t g, t;
+    int pos = 0;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        for(t = 0; t < tool_count; ++t)
+        {
+            wxRibbonToolBarToolBase* tool = group->tools.Item(t);
+            if(tool->id == tool_id)
+            {
+                return pos;
+            }
+            ++pos;
+        }
+        ++pos; // Increment pos for group separator.
+    }
+    return wxNOT_FOUND;
+}
+
+bool wxRibbonToolBar::GetToolState(int tool_id)const
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_MSG(tool != NULL , false, "Invalid tool id");
+    return (tool->state & wxRIBBON_TOOLBAR_TOOL_TOGGLED) != 0;
+}
+
 wxBitmap wxRibbonToolBar::MakeDisabledBitmap(const wxBitmap& original)
 {
     wxImage img(original.ConvertToImage());
@@ -221,6 +532,78 @@ bool wxRibbonToolBar::IsSizingContinuous() const
     return false;
 }
 
+void wxRibbonToolBar::SetToolClientData(int tool_id, wxObject* clientData)
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_RET(tool != NULL , "Invalid tool id");
+    tool->client_data = clientData;
+}
+
+void wxRibbonToolBar::SetToolDisabledBitmap(int tool_id, const wxBitmap &bitmap)
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_RET(tool != NULL , "Invalid tool id");
+    tool->bitmap_disabled = bitmap;
+}
+
+void wxRibbonToolBar::SetToolHelpString(int tool_id, const wxString& helpString)
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_RET(tool != NULL , "Invalid tool id");
+    tool->help_string = helpString;
+}
+
+void wxRibbonToolBar::SetToolNormalBitmap(int tool_id, const wxBitmap &bitmap)
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_RET(tool != NULL , "Invalid tool id");
+    tool->bitmap = bitmap;
+}
+
+void wxRibbonToolBar::EnableTool(int tool_id, bool enable)
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_RET(tool != NULL , "Invalid tool id");
+    if(enable)
+    {
+        if(tool->state & wxRIBBON_TOOLBAR_TOOL_DISABLED)
+        {
+            tool->state &= ~wxRIBBON_TOOLBAR_TOOL_DISABLED;
+            Refresh();
+        }
+    }
+    else
+    {
+        if((tool->state & wxRIBBON_TOOLBAR_TOOL_DISABLED)==0)
+        {
+            tool->state |= wxRIBBON_TOOLBAR_TOOL_DISABLED;
+            Refresh();
+        }
+    }
+}
+
+void wxRibbonToolBar::ToggleTool(int tool_id, bool checked)
+{
+    wxRibbonToolBarToolBase* tool = FindById(tool_id);
+    wxCHECK_RET(tool != NULL , "Invalid tool id");
+    if(checked)
+    {
+        if((tool->state & wxRIBBON_TOOLBAR_TOOL_TOGGLED) == 0)
+        {
+            tool->state |= wxRIBBON_TOOLBAR_TOOL_TOGGLED;
+            Refresh();
+        }
+    }
+    else
+    {
+        if(tool->state & wxRIBBON_TOOLBAR_TOOL_TOGGLED)
+        {
+            tool->state &= ~wxRIBBON_TOOLBAR_TOOL_TOGGLED;
+            Refresh();
+        }
+    }
+}
+
 static int GetSizeInOrientation(wxSize size, wxOrientation orientation)
 {
     switch(orientation)
@@ -364,7 +747,6 @@ bool wxRibbonToolBar::Realize()
             tool->size = m_art->GetToolSize(temp_dc, this,
                 tool->bitmap.GetSize(), tool->kind, t == 0,
                 t == (tool_count - 1), &tool->dropdown);
-            tool->state = tool->state & ~wxRIBBON_TOOLBAR_TOOL_DISABLED;
             if(t == 0)
                 tool->state |= wxRIBBON_TOOLBAR_TOOL_FIRST;
             if(t == tool_count - 1)
@@ -399,7 +781,21 @@ bool wxRibbonToolBar::Realize()
     wxSize* row_sizes = new wxSize[m_nrows_max];
     wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
         wxVERTICAL : wxHORIZONTAL;
+
     SetMinSize(wxSize(0, 0));
+    wxSize minSize(INT_MAX, INT_MAX);
+
+    // See if we're sizing flexibly (i.e. wrapping), and set min size differently
+    bool sizingFlexibly = false;
+    wxRibbonPanel* panel = wxDynamicCast(GetParent(), wxRibbonPanel);
+    if (panel && (panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE))
+        sizingFlexibly = true;
+
+    // Without this, there will be redundant horizontal space because SetMinSize will
+    // use the smallest possible height (and therefore largest width).
+    if (sizingFlexibly)
+        major_axis = wxHORIZONTAL;
+
     for(nrows = m_nrows_min; nrows <= m_nrows_max; ++nrows)
     {
         for(r = 0; r < nrows; ++r)
@@ -427,13 +823,31 @@ bool wxRibbonToolBar::Realize()
             size.IncBy(0, row_sizes[r].y);
         }
         m_sizes[nrows - m_nrows_min] = size;
+
         if(GetSizeInOrientation(size, major_axis) < smallest_area)
         {
-            SetMinSize(size);
             smallest_area = GetSizeInOrientation(size, major_axis);
+            SetMinSize(size);
+        }
+
+        if (sizingFlexibly)
+        {
+            if (size.x < minSize.x)
+                minSize.x = size.x;
+            if (size.y < minSize.y)
+                minSize.y = size.y;
         }
     }
 
+    if (sizingFlexibly)
+    {
+        // Give it the min size in either direction regardless of row,
+        // so that we're able to vary the size of the panel according to
+        // the space the toolbar takes up.
+        SetMinSize(minSize);
+    }
+    delete[] row_sizes;
+
     // Position the groups
     wxSizeEvent dummy_event(GetSize());
     OnSize(dummy_event);
@@ -451,6 +865,20 @@ void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
     int row_count = m_nrows_max;
     wxOrientation major_axis = m_art->GetFlags() & wxRIBBON_BAR_FLOW_VERTICAL ?
         wxVERTICAL : wxHORIZONTAL;
+
+    // See if we're sizing flexibly, and set min size differently
+    bool sizingFlexibly = false;
+    wxRibbonPanel* panel = wxDynamicCast(GetParent(), wxRibbonPanel);
+    if (panel && (panel->GetFlags() & wxRIBBON_PANEL_FLEXIBLE))
+        sizingFlexibly = true;
+
+    // Without this, there will be redundant horizontal space because SetMinSize will
+    // use the smallest possible height (and therefore largest width).
+    if (sizingFlexibly)
+        major_axis = wxHORIZONTAL;
+
+    wxSize bestSize = m_sizes[0];
+
     if(m_nrows_max != m_nrows_min)
     {
         int area = 0;
@@ -461,6 +889,7 @@ void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
             {
                 area = GetSizeInOrientation(m_sizes[i], major_axis);
                 row_count = m_nrows_min + i;
+                bestSize = m_sizes[i];
             }
         }
     }
@@ -512,6 +941,37 @@ void wxRibbonToolBar::OnSize(wxSizeEvent& evt)
     delete[] row_sizes;
 }
 
+// Finds the best width and height given the parents' width and height
+wxSize wxRibbonToolBar::GetBestSizeForParentSize(const wxSize& parentSize) const
+{
+    if (!m_sizes)
+        return GetMinSize();
+
+    // Choose row count with largest possible area
+    wxSize size = parentSize;
+
+    // A toolbar should maximize its width whether vertical or horizontal, so
+    // force the major axis to be horizontal. Without this, there will be
+    // redundant horizontal space.
+    wxOrientation major_axis = wxHORIZONTAL;
+    wxSize bestSize = m_sizes[0];
+
+    if(m_nrows_max != m_nrows_min)
+    {
+        int area = 0;
+        for(int i = 0; i <= m_nrows_max - m_nrows_min; ++i)
+        {
+            if(m_sizes[i].x <= size.x && m_sizes[i].y <= size.y &&
+                GetSizeInOrientation(m_sizes[i], major_axis) > area)
+            {
+                area = GetSizeInOrientation(m_sizes[i], major_axis);
+                bestSize = m_sizes[i];
+            }
+        }
+    }
+    return bestSize;
+}
+
 wxSize wxRibbonToolBar::DoGetBestSize() const
 {
     return GetMinSize();
@@ -544,8 +1004,12 @@ void wxRibbonToolBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
             {
                 wxRibbonToolBarToolBase* tool = group->tools.Item(t);
                 wxRect rect(group->position + tool->position, tool->size);
-                m_art->DrawTool(dc, this, rect, tool->bitmap, tool->kind,
-                    tool->state);
+                if(tool->state & wxRIBBON_TOOLBAR_TOOL_DISABLED)
+                    m_art->DrawTool(dc, this, rect, tool->bitmap_disabled,
+                        tool->kind, tool->state);
+                else
+                    m_art->DrawTool(dc, this, rect, tool->bitmap, tool->kind,
+                        tool->state);
             }
         }
     }
@@ -581,6 +1045,22 @@ void wxRibbonToolBar::OnMouseMove(wxMouseEvent& evt)
         }
     }
 
+#if wxUSE_TOOLTIPS
+    if(new_hover)
+    {
+        SetToolTip(new_hover->help_string);
+    }
+    else if(GetToolTip())
+    {
+        UnsetToolTip();
+    }
+#endif
+
+    if(new_hover && new_hover->state & wxRIBBON_TOOLBAR_TOOL_DISABLED)
+    {
+        new_hover = NULL; // A disabled tool can not be hilighted
+    }
+
     if(new_hover != m_hover_tool)
     {
         if(m_hover_tool)
@@ -596,7 +1076,7 @@ void wxRibbonToolBar::OnMouseMove(wxMouseEvent& evt)
                 what = wxRIBBON_TOOLBAR_TOOL_DROPDOWN_HOVERED;
 
             new_hover->state |= what;
-            
+
             if(new_hover == m_active_tool)
             {
                 new_hover->state &= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
@@ -653,17 +1133,32 @@ void wxRibbonToolBar::OnMouseUp(wxMouseEvent& WXUNUSED(evt))
     {
         if(m_active_tool->state & wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK)
         {
-            wxEventType evt_type = wxEVT_COMMAND_RIBBONTOOL_CLICKED;
+            wxEventType evt_type = wxEVT_RIBBONTOOLBAR_CLICKED;
             if(m_active_tool->state & wxRIBBON_TOOLBAR_TOOL_DROPDOWN_ACTIVE)
-                evt_type = wxEVT_COMMAND_RIBBONTOOL_DROPDOWN_CLICKED;
+                evt_type = wxEVT_RIBBONTOOLBAR_DROPDOWN_CLICKED;
             wxRibbonToolBarEvent notification(evt_type, m_active_tool->id);
+            if(m_active_tool->kind == wxRIBBON_BUTTON_TOGGLE)
+            {
+                m_active_tool->state ^=
+                    wxRIBBON_BUTTONBAR_BUTTON_TOGGLED;
+                notification.SetInt(m_active_tool->state &
+                    wxRIBBON_BUTTONBAR_BUTTON_TOGGLED);
+            }
             notification.SetEventObject(this);
             notification.SetBar(this);
             ProcessEvent(notification);
+
+            wxStaticCast(m_parent, wxRibbonPanel)->HideIfExpanded();
+        }
+
+        // Notice that m_active_tool could have been reset by the event handler
+        // above so we need to test it again.
+        if (m_active_tool)
+        {
+            m_active_tool->state &= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
+            m_active_tool = NULL;
+            Refresh(false);
         }
-        m_active_tool->state &= ~wxRIBBON_TOOLBAR_TOOL_ACTIVE_MASK;
-        m_active_tool = NULL;
-        Refresh(false);
     }
 }
 
@@ -675,6 +1170,39 @@ void wxRibbonToolBar::OnMouseEnter(wxMouseEvent& evt)
     }
 }
 
+void wxRibbonToolBar::UpdateWindowUI(long flags)
+{
+    wxWindowBase::UpdateWindowUI(flags);
+
+    // don't waste time updating state of tools in a hidden toolbar
+    if ( !IsShown() )
+        return;
+
+    size_t group_count = m_groups.GetCount();
+    size_t g, t;
+    for(g = 0; g < group_count; ++g)
+    {
+        wxRibbonToolBarToolGroup* group = m_groups.Item(g);
+        size_t tool_count = group->tools.GetCount();
+        for(t = 0; t < tool_count; ++t)
+        {
+            wxRibbonToolBarToolBase* tool = group->tools.Item(t);
+            int id = tool->id;
+
+            wxUpdateUIEvent event(id);
+            event.SetEventObject(this);
+
+            if ( ProcessWindowEvent(event) )
+            {
+                if ( event.GetSetEnabled() )
+                    EnableTool(id, event.GetEnabled());
+                if ( event.GetSetChecked() )
+                    ToggleTool(id, event.GetChecked());
+            }
+        }
+    }
+}
+
 bool wxRibbonToolBarEvent::PopupMenu(wxMenu* menu)
 {
     wxPoint pos = wxDefaultPosition;