Search code examples
c++wxwidgets

Can I use custom color for a specific wx[Aui]Notebook tab


I'm triying to color each tab on wxWidgets with a different color, like when you tag an Excel Sheet, is there a way to do that in the C++ version of wxWidgets, with or without AUI?


Solution

  • I don't think there is anything that will let you do this out of the box; but with an Aui notebook, you can write a custom tab art to color the tabs as you see fit. Here's a hideous example that I just threw together to demonstrate one way to do this:

    // For compilers that support precompilation, includes "wx/wx.h".
    #include "wx/wxprec.h"
    
    #ifdef __BORLANDC__
        #pragma hdrstop
    #endif
    
    // for all others, include the necessary headers (this file is usually all you
    // need because it includes almost all "standard" wxWidgets headers)
    #ifndef WX_PRECOMP
        #include "wx/wx.h"
    #endif
    
    #include <wx/aui/auibook.h>
    #include <map>
    
    class MyTabArt:public wxAuiGenericTabArt
    {
    public:
        MyTabArt():wxAuiGenericTabArt(){}
    
        wxAuiTabArt* Clone()
        {
            return new MyTabArt(*this);
        }
    
        void AddTabColor(wxWindow* w, const wxColor& c)
        {
            m_tabColors[w] = c;
        }
    
        virtual void DrawTab(wxDC& dc, wxWindow* wnd, const wxAuiNotebookPage& page,
                             const wxRect& rect, int closeButtonState,
                             wxRect* outTabRect, wxRect* outButtonRect,
                             int* xExtent) wxOVERRIDE
        {
            wxSize tabSize = GetTabSize(dc, wnd, page.caption, page.bitmap,
                                        page.active, closeButtonState, xExtent);
    
            wxCoord tabHeight = m_tabCtrlHeight;
            wxCoord tabWidth = tabSize.x;
            wxCoord tabX = rect.x;
            wxCoord tabY = rect.y + rect.height - tabHeight;
    
            wxRect tabRect(tabX, tabY, tabWidth, tabHeight);
    
            wxDCClipper clipper(dc, tabRect);
    
            auto it = m_tabColors.find(page.window);
    
            if ( it != m_tabColors.end() )
            {
                wxDCBrushChanger bchanger(dc, it->second);
                wxDCPenChanger pchanger(dc, it->second);
                dc.DrawRectangle(tabRect);
            }
            else
            {
                wxDCBrushChanger bchanger(dc, *wxGREEN);
                wxDCPenChanger pchanger(dc, *wxGREEN);
                dc.DrawRectangle(tabRect);
            }
    
            dc.DrawText(page.caption,tabRect.x,tabRect.y);
    
            *outTabRect = tabRect;
        }
    
    private:
        std::map<wxWindow*,wxColor> m_tabColors;
    };
    
    class MyFrame: public wxFrame
    {
        public:
            MyFrame();
    
        private:
    };
    
    MyFrame::MyFrame()
            :wxFrame(NULL, wxID_ANY, "AUI Tab", wxDefaultPosition, wxSize(600, 400))
    {
        wxAuiNotebook * auiNotebook =
            new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, 0 );
        wxPanel* panel1 = new wxPanel( auiNotebook, wxID_ANY );
        wxPanel* panel2 = new wxPanel( auiNotebook, wxID_ANY );
        auiNotebook->AddPage(panel1, "Page 1");
        auiNotebook->AddPage(panel2, "Page 2");
    
        MyTabArt* art = new MyTabArt();
        art->AddTabColor(panel1, *wxRED);
        art->AddTabColor(panel2, *wxBLUE);
    
        auiNotebook->SetArtProvider(art);
    }
    
    class MyApp : public wxApp
    {
        public:
            virtual bool OnInit()
            {
                ::wxInitAllImageHandlers();
                MyFrame* frame = new MyFrame();
                frame->Show();
                return true;
            }
    };
    
    wxIMPLEMENT_APP(MyApp);
    

    On windows, this monstrosity looks like this:

    enter image description here

    You can look at the source wxWidgets source for the other tab arts to see an example of how to make this prettier.