wxAuiNotebook, changing the close button bitmap?

152 views
Skip to first unread message

Tony Kennedy

unread,
Nov 22, 2023, 6:45:01 AM11/22/23
to wx-users
Hi all,

I've got a wxAuiNotebook, and I'd like to change the close button bitmap so it's a trashcan rather than the "X".

Is there a simple way to do this? I've been experimenting with SetArtProvider and a class derived from wxAuiDefaultTabArt where I set the member bitmaps to the one I want, but nothing seems to work for me.

Thanks in advance,

Tony.

PS. This is just to try and avoid any user confusion, the "X" for close is fine, but in my app, "close" in this case means delete something.

PB

unread,
Nov 22, 2023, 1:59:40 PM11/22/23
to wx-users
Hi,

Disclaimer: I know little about wxAUI, just took a look at the sources, and I am Windows only.

Replacing close button bitmaps in wxAuiSimpleTabArt is very simple but more complicated with wxAuiDefaultTabArt. wxAuiDefaultTabArt differs between platforms, e.g., it actually is wxAuiMSWTabArt on Windows which uses native theme API to draw the button.

Anyway, I tried if using a custom art for the tab works, writing a proof-of-concept code using a help bitmap as the close button (same for active and disabled), borrowing the draw methods from the generic tab art when needed, not caring about how it looks:
wx-auintb-art.png

#include <wx/wx.h>
#include <wx/artprov.h>
#include <wx/aui/auibook.h>

class MyAuiSimpleTabArt : public wxAuiSimpleTabArt
{
public:
    MyAuiSimpleTabArt(const wxBitmapBundle& activeCloseBmp, const wxBitmapBundle& disabledCloseBmp)
    {
        m_activeCloseBmp = activeCloseBmp;
        m_disabledCloseBmp = disabledCloseBmp;
    }

    wxAuiTabArt* Clone()
    {
        return new MyAuiSimpleTabArt(*this);
    }
};

class MyAuiDefaultTabArt : public wxAuiDefaultTabArt
{
public:
    MyAuiDefaultTabArt(const wxBitmapBundle& activeCloseBmp, const wxBitmapBundle& disabledCloseBmp)
    {
        m_activeCloseBmp = activeCloseBmp;
        m_disabledCloseBmp = disabledCloseBmp;
    }

    // This draws the "Close active tab" button on the far right
    void DrawButton(wxDC& dc, wxWindow* wnd, const wxRect& in_rect, int bitmap_id, int button_state, int orientation, wxRect* out_rect) override
    {
        // for testing, use generic version
        wxAuiGenericTabArt::DrawButton(dc, wnd, in_rect, bitmap_id, button_state, orientation, out_rect);
    }

    void DrawTab(wxDC& dc, wxWindow* wnd, const wxAuiNotebookPage& page, const wxRect& in_rect, int close_button_state, wxRect* out_tab_rect, wxRect* out_button_rect, int* x_extent) override
    {
        // for testing, use generic version
        wxAuiGenericTabArt::DrawTab(dc, wnd, page, in_rect, close_button_state, out_tab_rect, out_button_rect, x_extent);
    }

    wxAuiTabArt* Clone()
    {
        return new MyAuiDefaultTabArt(*this);
    }
};

class MyFrame : public wxFrame
{
public:
    MyFrame(wxWindow* parent = nullptr) : wxFrame(parent, wxID_ANY, "Test")
    {
        const wxBitmapBundle activeClose = wxArtProvider::GetBitmapBundle(wxART_HELP, wxART_OTHER, wxSize(16,16));
        const wxBitmapBundle disabledClose = activeClose;

        wxBoxSizer* mainSizer = new wxBoxSizer(wxVERTICAL);

        mainSizer->Add(AddNotebook(new MyAuiSimpleTabArt(activeClose, disabledClose)), wxSizerFlags(1).Expand());
        mainSizer->Add(AddNotebook(new MyAuiDefaultTabArt(activeClose, disabledClose)), wxSizerFlags(1).Expand());
        SetSizer(mainSizer);
    }
private:
    wxAuiNotebook* AddNotebook(wxAuiTabArt* tabArt)
    {
        wxAuiNotebook* notebook = new wxAuiNotebook(this, wxID_ANY, wxDefaultPosition, wxDefaultSize, wxAUI_NB_CLOSE_BUTTON | wxAUI_NB_CLOSE_ON_ALL_TABS | wxAUI_NB_DEFAULT_STYLE);

        notebook->SetArtProvider(tabArt);
        for ( size_t i = 0; i < 10; ++i )
            notebook->AddPage(new wxPanel(notebook), wxString::Format("Page %zu", i), false);
        return notebook;
    }
};

class MyApp : public wxApp
{
    bool OnInit() override
    {
        (new MyFrame())->Show();
        return true;
    }
}; wxIMPLEMENT_APP(MyApp);

To conclude, customizing the tab art seems possible but may require some effort to look good and work properly on all the platforms.

Regards,
PB

Tony Kennedy

unread,
Nov 23, 2023, 2:55:11 AM11/23/23
to wx-users
Thank you for this. I tried something similar, but only had code for DrawButton which never got called.

All the best,

Tony.

Tony Kennedy

unread,
Nov 23, 2023, 4:33:59 AM11/23/23
to wx-users
Thanks again for this, it is almost perfect for my needs.

Do you know how to make the tabs slightly wider? When I activate a tab, the font is bold (which is good), but then the text is truncated slightly. What I mean is, if the tab has the label "company,product", when I select it, I get "company,prod...". I'd prefer to keep all the text.

Tony.

Tony Kennedy

unread,
Nov 23, 2023, 6:22:04 AM11/23/23
to wx-users
PS. I tried a few things like modifying the out_tab_rect, out_button_rect and x_extent in DrawTab, but nothing seemed to do what I needed.

Tony.

PB

unread,
Nov 23, 2023, 3:23:18 PM11/23/23
to wx-users
Hi,

regarding the truncated caption for the active tab. You did not provide any information on which platform are you using or what exactly do you do code and flag-wise (e.g., do you use fixed-width tabs), nor provided minimal but complete code showing what you do, similar to one I posted above.

Anyway, the wxAuiTabArt API provides two virtual methods to measure the tab width. The default implementation seems to use the bold variant of the font as the measure font. If the truncated text can be reproduced in the original tabart (I could not) , it is the tabart issue. If it cannot, it is a bug in your code you need to find and fix. I am afraid I cannot be of any further help here.

Regards,
PB
Message has been deleted

Tony Kennedy

unread,
Nov 24, 2023, 2:21:19 AM11/24/23
to wx-users
Sorry, I should have provided more details. Developing on Windows (but also release on the Mac) and variable width tabs. As with most things, it's tricky for me to unpick the code I've got so as to provide an example.

I'll have a go at setting the measuring font to be the bold version when a tab is selected. But now I know about GetTabSize, that does the job as well.

Thanks again so much for your help. You've got me to the point where it's all working well now (and looking great too).

Tony. 
Reply all
Reply to author
Forward
0 new messages