]> git.saurik.com Git - wxWidgets.git/blobdiff - src/ribbon/bar.cpp
Don't ignore invalid files entered into wxFileDirPickerCtrlBase.
[wxWidgets.git] / src / ribbon / bar.cpp
index e922cecc0e850f11083814fe4766de851937db7d..e64b381778e028d1ce94e29e5e44fe3860594bf1 100644 (file)
@@ -20,6 +20,7 @@
 #include "wx/ribbon/bar.h"
 #include "wx/ribbon/art.h"
 #include "wx/dcbuffer.h"
+#include "wx/app.h"
 
 #ifndef WX_PRECOMP
 #endif
@@ -39,6 +40,7 @@ wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONBAR_TAB_MIDDLE_UP, wxRibbonBarEvent);
 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_DOWN, wxRibbonBarEvent);
 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONBAR_TAB_RIGHT_UP, wxRibbonBarEvent);
 wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONBAR_TAB_LEFT_DCLICK, wxRibbonBarEvent);
+wxDEFINE_EVENT(wxEVT_COMMAND_RIBBONBAR_TOGGLED, wxRibbonBarEvent);
 
 IMPLEMENT_CLASS(wxRibbonBar, wxRibbonControl)
 IMPLEMENT_DYNAMIC_CLASS(wxRibbonBarEvent, wxNotifyEvent)
@@ -65,6 +67,8 @@ void wxRibbonBar::AddPage(wxRibbonPage *page)
     info.page = page;
     info.active = false;
     info.hovered = false;
+    info.highlight = false;
+    info.shown = true;
     // info.rect not set (intentional)
 
     wxClientDC dcTemp(this);
@@ -109,7 +113,7 @@ bool wxRibbonBar::DismissExpandedPanel()
     return m_pages.Item(m_current_page).page->DismissExpandedPanel();
 }
 
-void wxRibbonBar::ShowPanels(const bool show)
+void wxRibbonBar::ShowPanels(bool show)
 {
     m_arePanelsShown = show;
     SetMinSize(wxSize(GetSize().GetWidth(), DoGetBestSize().GetHeight()));
@@ -140,6 +144,8 @@ bool wxRibbonBar::Realize()
     for(i = 0; i < numtabs; ++i)
     {
         wxRibbonPageTabInfo& info = m_pages.Item(i);
+        if (!info.shown)
+            continue;
         RepositionPage(info.page);
         if(!info.page->Realize())
         {
@@ -239,6 +245,7 @@ void wxRibbonBar::OnMouseMove(wxMouseEvent& evt)
     {
         RefreshTabBar();
     }
+    HitTestToggleButton(evt.GetPosition());
 }
 
 void wxRibbonBar::OnMouseLeave(wxMouseEvent& WXUNUSED(evt))
@@ -266,6 +273,12 @@ void wxRibbonBar::OnMouseLeave(wxMouseEvent& WXUNUSED(evt))
     {
         RefreshTabBar();
     }
+    if(m_toggle_button_hovered)
+    {
+        m_bar_hovered = false;
+        m_toggle_button_hovered = false;
+        Refresh(false);
+    }
 }
 
 wxRibbonPage* wxRibbonBar::GetPage(int n)
@@ -275,6 +288,100 @@ wxRibbonPage* wxRibbonBar::GetPage(int n)
     return m_pages.Item(n).page;
 }
 
+size_t wxRibbonBar::GetPageCount() const
+{
+    return m_pages.GetCount();
+}
+
+bool wxRibbonBar::IsPageShown(size_t page) const
+{
+    if (page >= m_pages.GetCount())
+        return false;
+    return m_pages.Item(page).shown;
+}
+
+void wxRibbonBar::ShowPage(size_t page, bool show)
+{
+    if(page >= m_pages.GetCount())
+        return;
+    m_pages.Item(page).shown = show;
+}
+
+bool wxRibbonBar::IsPageHighlighted(size_t page) const
+{
+    if (page >= m_pages.GetCount())
+        return false;
+    return m_pages.Item(page).highlight;
+}
+
+void wxRibbonBar::AddPageHighlight(size_t page, bool highlight)
+{
+    if(page >= m_pages.GetCount())
+        return;
+    m_pages.Item(page).highlight = highlight;
+}
+
+void wxRibbonBar::DeletePage(size_t n)
+{
+    if(n < m_pages.GetCount())
+    {
+        wxRibbonPage *page = m_pages.Item(n).page;
+
+        // Schedule page object for destruction and not destroying directly
+        // as this function can be called in an event handler and page functions
+        // can be called afeter removing.
+        // Like in wxRibbonButtonBar::OnMouseUp
+        if(!wxTheApp->IsScheduledForDestruction(page))
+        {
+            wxTheApp->ScheduleForDestruction(page);
+        }
+
+        m_pages.RemoveAt(n);
+
+        if(m_current_page == static_cast<int>(n))
+        {
+            m_current_page = -1;
+
+            if(m_pages.GetCount() > 0)
+            {
+                if(n >= m_pages.GetCount())
+                {
+                    SetActivePage(m_pages.GetCount() - 1);
+                }
+                else
+                {
+                    SetActivePage(n - 1);
+                }
+            }
+        }
+        else if(m_current_page > static_cast<int>(n))
+        {
+            m_current_page--;
+        }
+    }
+}
+
+void wxRibbonBar::ClearPages()
+{
+    size_t i;
+    for(i=0; i<m_pages.GetCount(); i++)
+    {
+        wxRibbonPage *page = m_pages.Item(i).page;
+        // Schedule page object for destruction and not destroying directly
+        // as this function can be called in an event handler and page functions
+        // can be called afeter removing.
+        // Like in wxRibbonButtonBar::OnMouseUp
+        if(!wxTheApp->IsScheduledForDestruction(page))
+        {
+            wxTheApp->ScheduleForDestruction(page);
+        }
+    }
+    m_pages.Empty();
+    Realize();
+    m_current_page = -1;
+    Refresh();
+}
+
 bool wxRibbonBar::SetActivePage(size_t page)
 {
     if(m_current_page == (int)page)
@@ -294,6 +401,7 @@ bool wxRibbonBar::SetActivePage(size_t page)
     }
     m_current_page = (int)page;
     m_pages.Item(page).active = true;
+    m_pages.Item(page).shown = true;
     {
         wxRibbonPage* wnd = m_pages.Item(page).page;
         RepositionPage(wnd);
@@ -319,6 +427,20 @@ bool wxRibbonBar::SetActivePage(wxRibbonPage* page)
     return false;
 }
 
+int wxRibbonBar::GetPageNumber(wxRibbonPage* page) const
+{
+    size_t numpages = m_pages.GetCount();
+    for(size_t i = 0; i < numpages; ++i)
+    {
+        if(m_pages.Item(i).page == page)
+        {
+            return i;
+        }
+    }
+    return wxNOT_FOUND;
+}
+
+
 int wxRibbonBar::GetActivePage() const
 {
     return m_current_page;
@@ -356,6 +478,8 @@ void wxRibbonBar::RecalculateTabSizes()
         for(i = 0; i < numtabs; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             info.rect.x = x;
             info.rect.y = y;
             info.rect.width = info.ideal_width;
@@ -373,6 +497,8 @@ void wxRibbonBar::RecalculateTabSizes()
         for(i = 0; i < numtabs; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             info.rect.x = x;
             info.rect.y = y;
             info.rect.width = info.minimum_width;
@@ -409,6 +535,8 @@ void wxRibbonBar::RecalculateTabSizes()
         for(i = 0; i < numtabs; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             info.rect.x -= m_tab_scroll_amount;
         }
     }
@@ -430,6 +558,8 @@ void wxRibbonBar::RecalculateTabSizes()
         for(i = 0; i < numtabs; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             if(info.small_must_have_separator_width < smallest_tab_width)
             {
                 smallest_tab_width = info.small_must_have_separator_width;
@@ -445,6 +575,8 @@ void wxRibbonBar::RecalculateTabSizes()
             for(i = 0; i < numtabs; ++i)
             {
                 wxRibbonPageTabInfo& info = m_pages.Item(i);
+                if (!info.shown)
+                    continue;
                 int delta = info.ideal_width - info.small_must_have_separator_width;
                 info.rect.x = x;
                 info.rect.y = y;
@@ -463,6 +595,8 @@ void wxRibbonBar::RecalculateTabSizes()
             for(i = 0; i < numtabs; ++i)
             {
                 wxRibbonPageTabInfo& info = m_pages.Item(i);
+                if (!info.shown)
+                    continue;
                 if(info.minimum_width < smallest_tab_width)
                 {
                     total_small_width += smallest_tab_width;
@@ -479,6 +613,8 @@ void wxRibbonBar::RecalculateTabSizes()
                 for(i = 0; i < numtabs; ++i)
                 {
                     // Sneaky obj array trickery to not copy the tab descriptors
+                    if (!m_pages.Item(i).shown)
+                        continue;
                     sorted_pages.Add(&m_pages.Item(i));
                 }
                 sorted_pages.Sort(OrderPageTabInfoBySmallWidthAsc);
@@ -486,6 +622,8 @@ void wxRibbonBar::RecalculateTabSizes()
                 for(i = 0; i < numtabs; ++i)
                 {
                     wxRibbonPageTabInfo& info = sorted_pages.Item(i);
+                    if (!info.shown)
+                        continue;
                     if(info.small_must_have_separator_width * (int)(numtabs - i) <= width)
                     {
                         info.rect.width = info.small_must_have_separator_width;;
@@ -499,6 +637,8 @@ void wxRibbonBar::RecalculateTabSizes()
                 for(i = 0; i < numtabs; ++i)
                 {
                     wxRibbonPageTabInfo& info = m_pages.Item(i);
+                    if (!info.shown)
+                        continue;
                     info.rect.x = x;
                     info.rect.y = y;
                     info.rect.height = m_tab_height;
@@ -516,6 +656,8 @@ void wxRibbonBar::RecalculateTabSizes()
                 for(i = 0; i < numtabs; ++i)
                 {
                     wxRibbonPageTabInfo& info = m_pages.Item(i);
+                    if (!info.shown)
+                        continue;
                     int delta = smallest_tab_width - info.minimum_width;
                     info.rect.x = x;
                     info.rect.y = y;
@@ -601,6 +743,9 @@ void wxRibbonBar::CommonInit(long style)
         SetArtProvider(new wxRibbonDefaultArtProvider);
     }
     SetBackgroundStyle(wxBG_STYLE_CUSTOM);
+
+    m_toggle_button_hovered = false;
+    m_bar_hovered = false;
 }
 
 void wxRibbonBar::SetArtProvider(wxRibbonArtProvider* art)
@@ -638,6 +783,8 @@ void wxRibbonBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
 
     DoEraseBackground(dc);
 
+    m_toggle_button_rect = m_art->GetBarToggleButtonArea(dc, this, GetSize());
+
     size_t numtabs = m_pages.GetCount();
     double sep_visibility = 0.0;
     bool draw_sep = false;
@@ -651,6 +798,8 @@ void wxRibbonBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
     for(i = 0; i < numtabs; ++i)
     {
         wxRibbonPageTabInfo& info = m_pages.Item(i);
+        if (!info.shown)
+            continue;
 
         dc.DestroyClippingRegion();
         if(m_tab_scroll_buttons_shown)
@@ -683,6 +832,8 @@ void wxRibbonBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
         for(i = 0; i < numtabs - 1; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             rect.x = info.rect.x + info.rect.width;
 
             if(m_tab_scroll_buttons_shown && !tabs_rect.Intersects(rect))
@@ -707,6 +858,9 @@ void wxRibbonBar::OnPaint(wxPaintEvent& WXUNUSED(evt))
             m_art->DrawScrollButton(dc, this, m_tab_scroll_right_button_rect, wxRIBBON_SCROLL_BTN_RIGHT | m_tab_scroll_right_button_state | wxRIBBON_SCROLL_BTN_FOR_TABS);
         }
     }
+    wxRect rect(GetClientSize().GetWidth() - 30, 6, 12, 12);
+    if ( m_flags & wxRIBBON_BAR_SHOW_TOGGLE_BUTTON  )
+        m_art->DrawToggleButton(dc, this, rect, ArePanelsShown());
 }
 
 void wxRibbonBar::OnEraseBackground(wxEraseEvent& WXUNUSED(evt))
@@ -755,6 +909,8 @@ wxRibbonPageTabInfo* wxRibbonBar::HitTestTabs(wxPoint position, int* index)
         for(i = 0; i < numtabs; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             if(info.rect.Contains(position))
             {
                 if(index != NULL)
@@ -802,6 +958,23 @@ void wxRibbonBar::OnMouseLeftDown(wxMouseEvent& evt)
             RefreshTabBar();
         }
     }
+
+    wxPoint position = evt.GetPosition();
+
+    if(position.x >= 0 && position.y >= 0)
+    {
+        wxSize size = GetSize();
+        if(position.x < size.GetWidth() && position.y < size.GetHeight())
+        {
+            if(m_toggle_button_rect.Contains(position))
+            {
+                ShowPanels(!ArePanelsShown());
+                wxRibbonBarEvent event(wxEVT_COMMAND_RIBBONBAR_TOGGLED, GetId());
+                event.SetEventObject(this);
+                ProcessWindowEvent(event);
+            }
+        }
+    }
 }
 
 void wxRibbonBar::OnMouseLeftUp(wxMouseEvent& WXUNUSED(evt))
@@ -852,6 +1025,8 @@ void wxRibbonBar::ScrollTabBar(int amount)
     for(i = 0; i < numtabs; ++i)
     {
         wxRibbonPageTabInfo& info = m_pages.Item(i);
+        if (!info.shown)
+            continue;
         info.rect.SetX(info.rect.GetX() - amount);
     }
     if(show_right != (m_tab_scroll_right_button_rect.GetWidth() != 0) ||
@@ -942,6 +1117,8 @@ void wxRibbonBar::RecalculateMinSize()
         for(i = 1; i < numtabs; ++i)
         {
             wxRibbonPageTabInfo& info = m_pages.Item(i);
+            if (!info.shown)
+                continue;
             wxSize page_min = info.page->GetMinSize();
 
             min_size.x = wxMax(min_size.x, page_min.x);
@@ -981,4 +1158,29 @@ wxSize wxRibbonBar::DoGetBestSize() const
     return best;
 }
 
+void wxRibbonBar::HitTestToggleButton(wxPoint position)
+{
+    bool hovered = false, toggle_button_hovered = false;
+    if(position.x >= 0 && position.y >= 0)
+    {
+        wxSize size = GetSize();
+        if(position.x < size.GetWidth() && position.y < size.GetHeight())
+        {
+            hovered = true;
+        }
+    }
+    if(hovered)
+    {
+        toggle_button_hovered = (m_flags & wxRIBBON_BAR_SHOW_TOGGLE_BUTTON) &&
+                                    m_toggle_button_rect.Contains(position);
+
+        if(hovered != m_bar_hovered || toggle_button_hovered != m_toggle_button_hovered)
+        {
+            m_bar_hovered = hovered;
+            m_toggle_button_hovered = toggle_button_hovered;
+            Refresh(false);
+        }
+    }
+}
+
 #endif // wxUSE_RIBBON