Skip to content

Instantly share code, notes, and snippets.

@vadz
Created March 16, 2024 17:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vadz/2fba5f0f48cbea44477096f3990fe0d9 to your computer and use it in GitHub Desktop.
Save vadz/2fba5f0f48cbea44477096f3990fe0d9 to your computer and use it in GitHub Desktop.
Example of using custom tab art with wxAUI
#include <wx/app.h>
#include <wx/dc.h>
#include <wx/frame.h>
#include <wx/panel.h>
#include <wx/sizer.h>
#include <wx/textctrl.h>
#include <wx/aui/aui.h>
class TestDockArt : public wxAuiDefaultDockArt {
public:
void DrawCaption(wxDC& dc,
wxWindow* window,
const wxString& text,
const wxRect& rect,
wxAuiPaneInfo& pane)
{
dc.SetBrush(*wxBLUE);
dc.DrawRectangle(rect);
dc.SetTextForeground(*wxYELLOW);
dc.DrawText(text, rect.x + window->FromDIP(5), rect.y);
}
};
class TestTabArt : public wxAuiGenericTabArt
{
public:
wxAuiTabArt* Clone() override
{
return new TestTabArt{*this};
}
void
DrawBackground(wxDC& dc,
wxWindow* WXUNUSED(wnd),
const wxRect& rect) override
{
dc.SetBrush(*wxBLACK_BRUSH);
dc.DrawRectangle(rect);
}
void
DrawTab(wxDC& dc,
wxWindow* wnd,
const wxAuiNotebookPage& pane,
const wxRect& inRect,
int closeButtonState,
wxRect* outTabRect,
wxRect* WXUNUSED(outButtonRect),
int* xExtent) override
{
const wxSize tabSize = GetTabSize(dc, wnd, pane.caption, pane.bitmap,
pane.active, closeButtonState,
xExtent);
*outTabRect = wxRect(inRect.GetPosition(), tabSize);
// To draw a semi-rounded (on top only) rectangle, make it much higher
// than necessary, so that the bottom round corners are chopped off.
wxRect rect = *outTabRect;
rect.height *= 2;
dc.SetBrush(pane.active ? *wxBLUE_BRUSH : *wxTRANSPARENT_BRUSH);
dc.DrawRoundedRectangle(rect, wnd->FromDIP(8));
rect.height /= 2;
// Use some horizontal padding.
rect.Deflate(wnd->FromDIP(5), 0);
// Draw the bitmap, if any.
if ( pane.bitmap.IsOk() )
{
const auto& bitmap = pane.bitmap.GetBitmapFor(wnd);
dc.DrawBitmap(bitmap,
rect.x,
rect.y + (rect.height - bitmap.GetLogicalHeight()) / 2,
true /* use mask */);
rect.Deflate(bitmap.GetLogicalWidth() + wnd->FromDIP(5), 0);
}
// Draw the text.
dc.SetTextForeground(*wxWHITE);
dc.SetFont(pane.active ? m_selectedFont : m_normalFont);
dc.DrawLabel(pane.caption, rect, wxALIGN_CENTER_VERTICAL);
// Finally, draw the close button.
if ( closeButtonState != wxAUI_BUTTON_STATE_HIDDEN )
{
const wxBitmapBundle bb(pane.active ? m_activeCloseBmp
: m_disabledCloseBmp);
const wxBitmap bitmap = bb.GetBitmapFor(wnd);
rect.x = inRect.x + tabSize.x - bitmap.GetLogicalWidth() - wnd->FromDIP(5);
rect.width = bitmap.GetLogicalWidth();
// TODO: account for button state.
dc.DrawBitmap(bitmap,
rect.x,
rect.y + (rect.height - bitmap.GetLogicalHeight()) / 2,
true /* use mask */);
}
}
wxSize
GetTabSize(wxDC& dc,
wxWindow* wnd,
const wxString& caption,
const wxBitmapBundle& bitmap,
bool WXUNUSED(active),
int closeButtonState,
int* xExtent) override
{
dc.SetFont(m_measuringFont);
wxSize size = dc.GetTextExtent(caption);
// Account for the close button.
if ( closeButtonState != wxAUI_BUTTON_STATE_HIDDEN )
{
size.x += m_activeCloseBmp.GetBitmapFor(wnd).GetLogicalWidth();
size.x += wnd->FromDIP(10);
}
// Account for the bitmap, if any.
if ( bitmap.IsOk() )
{
const wxSize bitmapSize = bitmap.GetPreferredLogicalSizeFor(wnd);
size.x += bitmapSize.x;
size.x += wnd->FromDIP(10);
if ( bitmapSize.y > size.y )
size.y = bitmapSize.y;
}
// Add some padding.
size += wnd->FromDIP(wxSize(20, 8));
*xExtent = size.x;
return size;
}
};
class TestPanel : public wxPanel {
public:
explicit TestPanel(wxWindow* parent) : wxPanel(parent, wxID_ANY) {
m_manager.SetManagedWindow(this);
m_manager.SetArtProvider(new TestDockArt);
auto nb = new wxAuiNotebook(this);
nb->AddPage(new wxTextCtrl(nb, wxID_ANY, "Welcome to the first page"), "First");
nb->AddPage(new wxTextCtrl(nb, wxID_ANY, "And another one"), "Second");
nb->AddPage(new wxTextCtrl(nb, wxID_ANY, "Last page, promised"), "Last");
nb->SetArtProvider(new TestTabArt);
m_manager.AddPane(nb, wxAuiPaneInfo().CenterPane().PaneBorder(false));
m_manager.AddPane(new wxTextCtrl(this, wxID_ANY, "Left pane"), wxAuiPaneInfo().Left().Layer(1).MinSize(FromDIP(wxSize(200, 100))).Caption("Left pane").CloseButton());
m_manager.AddPane(new wxTextCtrl(this, wxID_ANY, "Bottom pane"), wxAuiPaneInfo().Bottom().Layer(2).MinSize(FromDIP(wxSize(200, 100))).Caption("Bottom pane").MaximizeButton());
m_manager.Update();
}
private:
wxAuiManager m_manager;
};
class TestApp : public wxApp {
public:
bool OnInit() override {
auto f = new wxFrame(nullptr, wxID_ANY, "Window containing AUI panel");
auto t = new wxTextCtrl(f, wxID_ANY, "Just a text", wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);
auto p = new TestPanel(f);
auto s = new wxBoxSizer(wxHORIZONTAL);
s->Add(t, wxSizerFlags().Expand());
s->Add(p, wxSizerFlags(1).Expand());
f->SetSizer(s);
f->SetClientSize(f->FromDIP(wxSize(800, 600)));
f->Show();
return true;
}
};
wxIMPLEMENT_APP(TestApp);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment