vkdoom_m/libraries/ZWidget/src/widgets/tabwidget/tabwidget.cpp
Magnus Norddahl 762ce6f14c Add a tab widget
2024-01-10 17:08:50 +01:00

308 lines
5.5 KiB
C++

#include "widgets/tabwidget/tabwidget.h"
#include "widgets/textlabel/textlabel.h"
#include "widgets/imagebox/imagebox.h"
#include <algorithm>
TabWidget::TabWidget(Widget* parent) : Widget(parent)
{
Bar = new TabBar(this);
PageStack = new TabWidgetStack(this);
Bar->OnCurrentChanged = [=]() { OnBarCurrentChanged(); };
}
int TabWidget::AddTab(Widget* page, const std::string& label)
{
return AddTab(page, nullptr, label);
}
int TabWidget::AddTab(Widget* page, const std::shared_ptr<Image>& icon, const std::string& label)
{
int pageIndex = Bar->AddTab(label);
page->SetParent(PageStack);
page->SetVisible(false);
Pages.push_back(page);
if (Pages.size() == 1)
{
PageStack->SetCurrentWidget(page);
}
return pageIndex;
}
int TabWidget::GetCurrentIndex() const
{
return Bar->GetCurrentIndex();
}
Widget* TabWidget::GetCurrentWidget() const
{
return Pages[Bar->GetCurrentIndex()];
}
void TabWidget::SetCurrentIndex(int pageIndex)
{
if (Bar->GetCurrentIndex() != pageIndex)
{
Bar->SetCurrentIndex(pageIndex);
PageStack->SetCurrentWidget(Pages[pageIndex]);
}
}
void TabWidget::SetCurrentWidget(Widget* pageWidget)
{
int pageIndex = GetPageIndex(pageWidget);
if (pageIndex != -1)
SetCurrentIndex(pageIndex);
}
int TabWidget::GetPageIndex(Widget* pageWidget) const
{
for (size_t i = 0; i < Pages.size(); i++)
{
if (Pages[i] == pageWidget)
return i;
}
return -1;
}
void TabWidget::OnBarCurrentChanged()
{
int pageIndex = Bar->GetCurrentIndex();
PageStack->SetCurrentWidget(Pages[pageIndex]);
if (OnCurrentChanged)
OnCurrentChanged();
}
void TabWidget::OnPaintFrame(Canvas* canvas)
{
}
void TabWidget::OnGeometryChanged()
{
double w = GetWidth();
double h = GetHeight();
double barHeight = Bar->GetPreferredHeight();
Bar->SetFrameGeometry(Rect::xywh(0.0, 0.0, w, barHeight));
PageStack->SetFrameGeometry(Rect::xywh(0.0, barHeight, w, std::max(h - barHeight, 0.0)));
}
/////////////////////////////////////////////////////////////////////////////
TabBar::TabBar(Widget* parent) : Widget(parent)
{
}
int TabBar::AddTab(const std::string& label)
{
return AddTab(nullptr, label);
}
int TabBar::AddTab(const std::shared_ptr<Image>& icon, const std::string& label)
{
TabBarTab* tab = new TabBarTab(this);
tab->SetIcon(icon);
tab->SetText(label);
int pageIndex = Tabs.size();
Tabs.push_back(tab);
if (CurrentIndex == -1)
SetCurrentIndex(pageIndex);
OnGeometryChanged();
return pageIndex;
}
int TabBar::GetCurrentIndex() const
{
return CurrentIndex;
}
void TabBar::SetCurrentIndex(int pageIndex)
{
if (CurrentIndex != pageIndex)
{
if (CurrentIndex != -1)
Tabs[CurrentIndex]->SetCurrent(false);
CurrentIndex = pageIndex;
if (CurrentIndex != -1)
Tabs[CurrentIndex]->SetCurrent(true);
}
}
void TabBar::OnTabClicked(TabBarTab* tab)
{
int pageIndex = GetTabIndex(tab);
if (CurrentIndex != pageIndex)
{
SetCurrentIndex(pageIndex);
if (OnCurrentChanged)
OnCurrentChanged();
}
}
int TabBar::GetTabIndex(TabBarTab* tab)
{
for (size_t i = 0; i < Tabs.size(); i++)
{
if (Tabs[i] == tab)
return i;
}
return -1;
}
void TabBar::OnPaintFrame(Canvas* canvas)
{
}
void TabBar::OnGeometryChanged()
{
double w = GetWidth();
double h = GetHeight();
double x = 0.0;
for (TabBarTab* tab : Tabs)
{
double tabWidth = tab->GetPreferredWidth();
tab->SetFrameGeometry(Rect::xywh(x, 0.0, tabWidth, h));
x += tabWidth;
}
}
/////////////////////////////////////////////////////////////////////////////
TabBarTab::TabBarTab(Widget* parent) : Widget(parent)
{
}
void TabBarTab::SetText(const std::string& text)
{
if (!text.empty())
{
if (!Label)
{
Label = new TextLabel(this);
OnGeometryChanged();
}
Label->SetText(text);
}
else
{
delete Label;
Label = nullptr;
OnGeometryChanged();
}
}
void TabBarTab::SetIcon(const std::shared_ptr<Image>& image)
{
if (image)
{
if (!Icon)
{
Icon = new ImageBox(this);
OnGeometryChanged();
}
Icon->SetImage(image);
}
else
{
delete Icon;
Icon = nullptr;
OnGeometryChanged();
}
}
void TabBarTab::SetCurrent(bool value)
{
if (IsCurrent != value)
{
IsCurrent = value;
Update();
}
}
double TabBarTab::GetPreferredWidth() const
{
double x = Icon ? 32.0 + 5.0 : 0.0;
if (Label) x += Label->GetPreferredWidth();
return x;
}
void TabBarTab::OnPaintFrame(Canvas* canvas)
{
}
void TabBarTab::OnGeometryChanged()
{
double x = 0.0;
double w = GetWidth();
double h = GetHeight();
if (Icon)
{
Icon->SetFrameGeometry(Rect::xywh(x, (h - 32.0) * 0.5, 32.0, 32.0));
x = 32.0 + 5.0;
}
if (Label)
{
Label->SetFrameGeometry(Rect::xywh(x, 0.0, std::max(w - x, 0.0), h));
}
}
void TabBarTab::OnMouseMove(const Point& pos)
{
if (!hot)
{
hot = true;
Update();
}
}
void TabBarTab::OnMouseDown(const Point& pos, int key)
{
mouseDown = true;
Update();
}
void TabBarTab::OnMouseUp(const Point& pos, int key)
{
if (mouseDown)
{
mouseDown = false;
Repaint();
if (OnClick)
OnClick();
}
}
void TabBarTab::OnMouseLeave()
{
hot = false;
mouseDown = false;
Update();
}
/////////////////////////////////////////////////////////////////////////////
TabWidgetStack::TabWidgetStack(Widget* parent) : Widget(parent)
{
}
void TabWidgetStack::SetCurrentWidget(Widget* widget)
{
if (widget != CurrentWidget)
{
if (CurrentWidget)
CurrentWidget->SetVisible(false);
CurrentWidget = widget;
if (CurrentWidget)
CurrentWidget->SetVisible(true);
}
}
void TabWidgetStack::OnPaintFrame(Canvas* canvas)
{
}
void TabWidgetStack::OnGeometryChanged()
{
if (CurrentWidget)
CurrentWidget->SetFrameGeometry(Rect::xywh(0.0, 0.0, GetWidth(), GetHeight()));
}