Start UI over from scratch and add demo window

This commit is contained in:
Luke Street
2026-04-28 16:20:45 -06:00
parent f7b880c5ea
commit d899706208
35 changed files with 434 additions and 3745 deletions
+232 -427
View File
@@ -1,464 +1,269 @@
#include "window.hpp"
#include "element.hpp"
#include "focus_border.hpp"
#include "theme.hpp"
#include <RmlUi/Core.h>
#include <RmlUi/Core/PropertyDictionary.h>
#include <RmlUi/Core/StyleSheetSpecification.h>
#include <algorithm>
#include "aurora/rmlui.hpp"
namespace dusk::ui {
namespace {
WindowTab::WindowTab(Rml::Element* parent, std::string_view id, std::string_view label,
std::function<void()> selectedCallback)
: m_selectedCallback(std::move(selectedCallback)) {
using namespace theme;
m_element = append(parent, "button", id,
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::Position, Rml::Style::Position::Relative},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center},
{Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::Height, rml_percent(100.0f)},
{Rml::PropertyId::PaddingLeft, rml_dp(20.0f)},
{Rml::PropertyId::PaddingRight, rml_dp(20.0f)},
{Rml::PropertyId::BackgroundColor, rml_color(Transparent)},
{Rml::PropertyId::BorderTopWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderRightWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderBottomWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderLeftWidth, rml_px(0.0f)},
{Rml::PropertyId::Cursor, rml_string("pointer")},
{Rml::PropertyId::TabIndex, Rml::Style::TabIndex::Auto},
{Rml::PropertyId::NavUp, Rml::Style::Nav::Auto},
{Rml::PropertyId::NavDown, Rml::Style::Nav::Auto},
{Rml::PropertyId::NavLeft, Rml::Style::Nav::Auto},
{Rml::PropertyId::NavRight, Rml::Style::Nav::Auto},
{Rml::PropertyId::FontFamily, rml_string("Inter")},
});
add_focus_border(m_element, BorderRadiusSmall);
m_label = append(m_element, "span", {},
{
{Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None},
{Rml::PropertyId::FontSize, rml_dp(20.0f)},
{Rml::PropertyId::LetterSpacing, rml_dp(1.0f)},
{Rml::PropertyId::FontWeight, Rml::Style::FontWeight::Bold},
{Rml::PropertyId::TextAlign, Rml::Style::TextAlign::Center},
{Rml::PropertyId::Color, rml_color(Text)},
});
set_text(m_label, label);
m_indicator = append(m_element, "div", {},
{
{Rml::PropertyId::Position, Rml::Style::Position::Absolute},
{Rml::PropertyId::Left, rml_px(0.0f)},
{Rml::PropertyId::Right, rml_px(0.0f)},
{Rml::PropertyId::Bottom, rml_dp(-BorderWidth)},
{Rml::PropertyId::Height, rml_dp(2.0f)},
{Rml::PropertyId::BackgroundColor, rml_color(WindowAccent, 0)},
{Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None},
});
m_element->AddEventListener(Rml::EventId::Click, this);
m_element->AddEventListener(Rml::EventId::Focus, this);
m_element->AddEventListener(Rml::EventId::Blur, this);
m_element->AddEventListener(Rml::EventId::Mouseover, this);
m_element->AddEventListener(Rml::EventId::Mouseout, this);
apply_style();
}
WindowTab::~WindowTab() {
if (m_element == nullptr) {
return;
}
m_element->RemoveEventListener(Rml::EventId::Click, this);
m_element->RemoveEventListener(Rml::EventId::Focus, this);
m_element->RemoveEventListener(Rml::EventId::Blur, this);
m_element->RemoveEventListener(Rml::EventId::Mouseover, this);
m_element->RemoveEventListener(Rml::EventId::Mouseout, this);
m_element = nullptr;
}
void WindowTab::ProcessEvent(Rml::Event& event) {
switch (event.GetId()) {
case Rml::EventId::Click:
if (m_selectedCallback) {
m_selectedCallback();
const Rml::String kWindowDocumentRml = R"RML(
<rml>
<head>
<title>Window</title>
<style>
*, *:before, *:after {
box-sizing: border-box;
}
break;
case Rml::EventId::Focus:
m_focused = true;
apply_style();
break;
case Rml::EventId::Blur:
m_focused = false;
apply_style();
break;
case Rml::EventId::Mouseover:
m_hovered = true;
apply_style();
break;
case Rml::EventId::Mouseout:
m_hovered = false;
apply_style();
break;
default:
break;
}
}
std::string WindowTab::id() const {
return m_element == nullptr ? std::string{} : m_element->GetId();
}
body {
width: 100%;
height: 100%;
padding: 64dp;
font-family: "Fira Sans";
font-weight: normal;
font-style: normal;
font-size: 15dp;
color: #E0DBC8;
}
void WindowTab::set_selected(bool selected) {
if (m_selected == selected) {
return;
}
m_selected = selected;
apply_style();
}
.window {
max-width: 1088dp;
max-height: 768dp;
margin: auto;
border-radius: 14dp;
overflow: hidden;
border: 2dp #92875B;
backdrop-filter: blur(5dp);
box-shadow: 0 0 25dp 5dp;
background-color: rgba(21, 22, 16, 90%);
}
void WindowTab::apply_style() {
using namespace theme;
.window .tab-bar {
display: flex;
height: 64dp;
background-color: rgba(217, 217, 217, 10%);
font-family: "Fira Sans Condensed";
font-weight: bold;
font-size: 18dp;
text-transform: uppercase;
border-bottom: 2dp #92875B;
}
if (m_element == nullptr) {
return;
.window .tab-bar .tab {
padding: 0 24dp;
line-height: 64dp;
opacity: 0.25;
tab-index: auto;
nav: horizontal;
focus: auto;
}
.window .tab-bar .tab.active {
opacity: 1;
border-bottom: 4dp #C2A42D;
font-effect: glow(0dp 4dp 0dp 4dp black);
decorator: linear-gradient(to bottom, rgba(194, 164, 45, 0%) 0%, rgba(194, 164, 45, 15%) 100%);
}
.window .tab-bar .tab:focus-visible {
opacity: 1;
font-effect: glow(0dp 4dp 0dp 4dp black);
decorator: linear-gradient(to bottom, rgba(194, 164, 45, 0%) 0%, rgba(194, 164, 45, 15%) 100%);
}
.window .content {
display: flex;
height: 100%;
}
.window .content .pane {
display: flex;
flex-flow: column;
flex: 1 1 0;
height: 100%;
padding: 24dp;
gap: 8dp;
overflow: auto;
}
.window .content .pane:not(:last-of-type) {
border-right: 1dp #92875B;
}
.section-heading {
font-weight: bold;
text-transform: uppercase;
font-size: 22dp;
opacity: 0.25;
}
.button {
text-align: center;
background-color: rgba(17, 16, 10, 20%);
opacity: 0.9;
padding: 8dp 16dp;
border-radius: 14dp;
box-shadow: rgba(146, 135, 91, 25%) 0 0 0 1dp;
font-size: 20dp;
transition: background-color 0.1s linear-in-out, opacity 0.1s linear-in-out;
}
.button.active, .button:hover {
background-color: rgba(204, 184, 119, 20%);
box-shadow: #C2A42D 0 0 0 2dp;
}
.button.selected, .button:active {
opacity: 1;
background-color: rgba(204, 184, 119, 40%);
box-shadow: #C2A42D 0 0 0 2dp;
}
.select-button {
display: flex;
align-items: center;
gap: 8dp;
background-color: rgba(17, 16, 10, 20%);
opacity: 0.9;
padding: 8dp 16dp;
border-radius: 14dp;
box-shadow: rgba(146, 135, 91, 25%) 0 0 0 1dp;
transition: background-color 0.1s linear-in-out, opacity 0.1s linear-in-out;
}
.select-button.active, .select-button:hover {
background-color: rgba(204, 184, 119, 20%);
box-shadow: #C2A42D 0 0 0 2dp;
}
.select-button.selected, .select-button:active {
opacity: 1;
background-color: rgba(204, 184, 119, 40%);
box-shadow: #C2A42D 0 0 0 2dp;
}
.select-button .key {
font-family: "Fira Sans Condensed";
font-weight: bold;
font-size: 18dp;
text-transform: uppercase;
}
.select-button .value {
margin-left: auto;
font-size: 20dp;
}
</style>
</head>
<body data-model="window">
<div class="window">
<div class="tab-bar">
<button class="tab"
data-for="tab, i : tabs"
data-class-active="i == active_tab"
data-event-click="set_active_tab(i)">
{{ tab.label }}
</button>
</div>
<div id="content" class="content"></div>
</div>
</body>
</rml>
)RML";
bool setup_window_model(Rml::Context* context, WindowModel& model, Rml::DataModelHandle& handle) {
Rml::DataModelConstructor constructor = context->CreateDataModel("window");
if (!constructor) {
return false;
}
const bool active = m_hovered || m_focused;
int textOpacity;
if (m_selected) {
textOpacity = 255;
} else if (active) {
textOpacity = 200;
if (auto tab_handle = constructor.RegisterStruct<WindowTab>()) {
tab_handle.RegisterMember("label", &WindowTab::label);
} else {
textOpacity = 110;
}
const Color textColor = m_selected ? TextActive : Text;
m_label->SetProperty(Rml::PropertyId::Color, rml_color(textColor, textOpacity));
if (m_indicator != nullptr) {
const int indicatorOpacity = m_selected ? 255 : (active ? 96 : 0);
m_indicator->SetProperty(
Rml::PropertyId::BackgroundColor, rml_color(WindowAccent, indicatorOpacity));
return false;
}
set_focus_border_visible(m_element, m_focused);
if (!constructor.RegisterArray<std::vector<WindowTab> >()) {
return false;
}
constructor.Bind("active_tab", &model.activeTab);
constructor.Bind("tabs", &model.tabs);
constructor.BindEventCallback("set_active_tab", &WindowModel::set_active_tab, &model);
handle = constructor.GetModelHandle();
return true;
}
Window::Window(Rml::Element* parent, std::string_view id, std::function<void()> closeCallback)
: m_closeCallback(std::move(closeCallback)) {
using namespace theme;
} // namespace
m_element = append(parent, "div", id,
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::Width, rml_percent(100.0f)},
{Rml::PropertyId::MaxWidth, rml_dp(1088.0f)},
{Rml::PropertyId::BorderTopWidth, rml_dp(BorderWidth)},
{Rml::PropertyId::BorderRightWidth, rml_dp(BorderWidth)},
{Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth)},
{Rml::PropertyId::BorderLeftWidth, rml_dp(BorderWidth)},
{Rml::PropertyId::BorderTopLeftRadius, rml_dp(BorderRadiusMedium)},
{Rml::PropertyId::BorderTopRightRadius, rml_dp(BorderRadiusMedium)},
{Rml::PropertyId::BorderBottomRightRadius, rml_dp(BorderRadiusMedium)},
{Rml::PropertyId::BorderBottomLeftRadius, rml_dp(BorderRadiusMedium)},
{Rml::PropertyId::BorderTopColor, rml_color(ElevatedBorder)},
{Rml::PropertyId::BorderRightColor, rml_color(ElevatedBorder)},
{Rml::PropertyId::BorderBottomColor, rml_color(ElevatedBorder)},
{Rml::PropertyId::BorderLeftColor, rml_color(ElevatedBorder)},
{Rml::PropertyId::BackgroundColor, rml_color(WindowSurface)},
{Rml::PropertyId::OverflowX, Rml::Style::Overflow::Hidden},
{Rml::PropertyId::OverflowY, Rml::Style::Overflow::Hidden},
});
set_props(m_element, {
{"backdrop-filter", "blur(5dp)"},
{"box-shadow", "0 0 25dp 5dp"},
});
void WindowModel::set_active_tab(
Rml::DataModelHandle model, Rml::Event& event, const Rml::VariantList& arguments) {
if (arguments.empty()) {
return;
}
m_tabBar = append(m_element, "div", {},
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::Position, Rml::Style::Position::Relative},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Row},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::Width, rml_percent(100.0f)},
{Rml::PropertyId::Height, rml_dp(WindowTabBarHeight)},
{Rml::PropertyId::MinHeight, rml_dp(WindowTabBarHeight)},
{Rml::PropertyId::PaddingLeft, rml_dp(12.0f)},
{Rml::PropertyId::PaddingRight, rml_dp(12.0f)},
{Rml::PropertyId::RowGap, rml_dp(4.0f)},
{Rml::PropertyId::ColumnGap, rml_dp(4.0f)},
{Rml::PropertyId::BackgroundColor, rml_color(WindowTitleOverlay)},
{Rml::PropertyId::BorderBottomWidth, rml_dp(BorderWidth * 1.5f)},
{Rml::PropertyId::BorderBottomColor, rml_color(WindowDivider)},
});
const int tabIndex = arguments[0].Get<int>();
if (tabIndex < 0 || tabIndex >= static_cast<int>(tabs.size()) || tabIndex == activeTab) {
return;
}
m_tabStrip = append(m_tabBar, "div", {},
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Row},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Stretch},
{Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::FlexStart},
{Rml::PropertyId::FlexGrow, rml_number(1.0f)},
{Rml::PropertyId::FlexShrink, rml_number(1.0f)},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
{Rml::PropertyId::Height, rml_percent(100.0f)},
{Rml::PropertyId::RowGap, rml_dp(4.0f)},
{Rml::PropertyId::ColumnGap, rml_dp(4.0f)},
});
activeTab = tabIndex;
model.DirtyVariable("active_tab");
const std::string closeId = id.empty() ? std::string{} : std::string(id) + "-close";
m_closeButton = append(m_tabBar, "button", closeId,
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::Position, Rml::Style::Position::Relative},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Center},
{Rml::PropertyId::JustifyContent, Rml::Style::JustifyContent::Center},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::Width, rml_dp(36.0f)},
{Rml::PropertyId::Height, rml_dp(36.0f)},
{Rml::PropertyId::FlexShrink, rml_number(0.0f)},
{Rml::PropertyId::BorderTopWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderRightWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderBottomWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderLeftWidth, rml_px(0.0f)},
{Rml::PropertyId::BorderTopLeftRadius, rml_dp(BorderRadiusSmall)},
{Rml::PropertyId::BorderTopRightRadius, rml_dp(BorderRadiusSmall)},
{Rml::PropertyId::BorderBottomRightRadius, rml_dp(BorderRadiusSmall)},
{Rml::PropertyId::BorderBottomLeftRadius, rml_dp(BorderRadiusSmall)},
{Rml::PropertyId::BackgroundColor, rml_color(Transparent)},
{Rml::PropertyId::Cursor, rml_string("pointer")},
{Rml::PropertyId::TabIndex, Rml::Style::TabIndex::Auto},
{Rml::PropertyId::FontFamily, rml_string("Inter")},
});
add_focus_border(m_closeButton, BorderRadiusSmall);
// Replace window content with new tab content
auto* currentElem = event.GetCurrentElement();
if (currentElem == nullptr) {
return;
}
auto* doc = currentElem->GetOwnerDocument();
if (doc == nullptr) {
return;
}
auto* content = doc->GetElementById("content");
if (content == nullptr) {
return;
}
while (content->GetNumChildren() > 0) {
content->RemoveChild(content->GetFirstChild());
}
if (tabs[tabIndex].setContent) {
tabs[tabIndex].setContent(content);
}
}
auto* closeGlyph = append(m_closeButton, "span", {},
{
{Rml::PropertyId::FontSize, rml_dp(22.0f)},
{Rml::PropertyId::FontWeight, Rml::Style::FontWeight::Normal},
{Rml::PropertyId::Color, rml_color(WindowGlyph)},
{Rml::PropertyId::PointerEvents, Rml::Style::PointerEvents::None},
});
set_text(closeGlyph, "\xc3\x97");
m_closeButton->AddEventListener(Rml::EventId::Click, this);
m_closeButton->AddEventListener(Rml::EventId::Focus, this);
m_closeButton->AddEventListener(Rml::EventId::Blur, this);
m_closeButton->AddEventListener(Rml::EventId::Mouseover, this);
m_closeButton->AddEventListener(Rml::EventId::Mouseout, this);
m_contentRow = append(m_element, "div", {},
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Row},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::Stretch},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::Width, rml_percent(100.0f)},
{Rml::PropertyId::FlexGrow, rml_number(1.0f)},
{Rml::PropertyId::FlexShrink, rml_number(1.0f)},
{Rml::PropertyId::MinHeight, rml_px(0.0f)},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
{Rml::PropertyId::RowGap, rml_dp(20.0f)},
{Rml::PropertyId::ColumnGap, rml_dp(20.0f)},
});
m_leftPane = append(m_contentRow, "div", {},
{
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
{Rml::PropertyId::MinHeight, rml_px(0.0f)},
{Rml::PropertyId::PaddingTop, rml_dp(24.0f)},
{Rml::PropertyId::PaddingRight, rml_dp(24.0f)},
{Rml::PropertyId::PaddingBottom, rml_dp(24.0f)},
{Rml::PropertyId::PaddingLeft, rml_dp(24.0f)},
{Rml::PropertyId::RowGap, rml_dp(12.0f)},
{Rml::PropertyId::ColumnGap, rml_dp(12.0f)},
});
m_rightPane = append(m_contentRow, "div", {},
{
{Rml::PropertyId::Display, Rml::Style::Display::None},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
{Rml::PropertyId::MinHeight, rml_px(0.0f)},
{Rml::PropertyId::PaddingTop, rml_dp(24.0f)},
{Rml::PropertyId::PaddingBottom, rml_dp(24.0f)},
{Rml::PropertyId::PaddingRight, rml_dp(24.0f)},
{Rml::PropertyId::PaddingLeft, rml_dp(8.0f)},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::FlexStart},
{Rml::PropertyId::OverflowY, Rml::Style::Overflow::Auto},
});
m_rightPane = append(m_contentRow, "div", {},
{
{Rml::PropertyId::Display, Rml::Style::Display::None},
{Rml::PropertyId::FlexDirection, Rml::Style::FlexDirection::Column},
{Rml::PropertyId::BoxSizing, Rml::Style::BoxSizing::BorderBox},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
{Rml::PropertyId::MinHeight, rml_px(0.0f)},
{Rml::PropertyId::PaddingTop, rml_dp(24.0f)},
{Rml::PropertyId::PaddingBottom, rml_dp(24.0f)},
{Rml::PropertyId::PaddingRight, rml_dp(24.0f)},
{Rml::PropertyId::PaddingLeft, rml_dp(8.0f)},
{Rml::PropertyId::AlignItems, Rml::Style::AlignItems::FlexStart},
{Rml::PropertyId::OverflowY, Rml::Style::Overflow::Auto},
});
apply_pane_layout();
apply_close_style();
Window::Window(WindowModel model) : mModel(std::move(model)) {
auto* context = aurora::rmlui::get_context();
if (context == nullptr) {
return;
}
setup_window_model(context, mModel, mModelHandle);
mDocument = context->LoadDocumentFromMemory(kWindowDocumentRml);
if (mDocument == nullptr) {
return;
}
mModel.tabs[0].setContent(mDocument->GetElementById("content"));
}
Window::~Window() {
m_tabs.clear();
if (m_closeButton != nullptr) {
m_closeButton->RemoveEventListener(Rml::EventId::Click, this);
m_closeButton->RemoveEventListener(Rml::EventId::Focus, this);
m_closeButton->RemoveEventListener(Rml::EventId::Blur, this);
m_closeButton->RemoveEventListener(Rml::EventId::Mouseover, this);
m_closeButton->RemoveEventListener(Rml::EventId::Mouseout, this);
m_closeButton = nullptr;
}
m_element = nullptr;
}
void Window::ProcessEvent(Rml::Event& event) {
if (event.GetTargetElement() != m_closeButton) {
return;
}
switch (event.GetId()) {
case Rml::EventId::Click:
if (m_closeCallback) {
m_closeCallback();
}
break;
case Rml::EventId::Focus:
m_closeFocused = true;
apply_close_style();
break;
case Rml::EventId::Blur:
m_closeFocused = false;
apply_close_style();
break;
case Rml::EventId::Mouseover:
m_closeHovered = true;
apply_close_style();
break;
case Rml::EventId::Mouseout:
m_closeHovered = false;
apply_close_style();
break;
default:
break;
auto* context = aurora::rmlui::get_context();
if (context != nullptr && mDocument != nullptr) {
context->UnloadDocument(mDocument);
mDocument = nullptr;
}
}
WindowTab* Window::add_tab(
std::string_view id, std::string_view label, std::function<void()> selectedCallback) {
if (m_tabStrip == nullptr) {
return nullptr;
}
const std::string idString(id);
auto wrapped = [this, idString, cb = std::move(selectedCallback)]() {
set_selected_tab(idString);
if (cb) {
cb();
}
};
auto tab = std::make_unique<WindowTab>(m_tabStrip, idString, label, std::move(wrapped));
WindowTab* raw = tab.get();
m_tabs.push_back(std::move(tab));
return raw;
}
void Window::set_selected_tab(std::string_view id) {
for (auto& tab : m_tabs) {
tab->set_selected(tab->id() == id);
void Window::show() {
if (mDocument != nullptr) {
mDocument->Show();
}
}
std::string Window::selected_tab_id() const {
for (const auto& tab : m_tabs) {
if (tab->is_selected()) {
return tab->id();
}
}
return {};
}
void Window::set_right_pane_visible(bool visible) {
if (m_rightPaneVisible == visible) {
return;
}
m_rightPaneVisible = visible;
apply_pane_layout();
}
void Window::apply_pane_layout() {
using namespace theme;
if (m_leftPane == nullptr || m_rightPane == nullptr) {
return;
}
if (m_rightPaneVisible) {
set_props(m_leftPane, {
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexGrow, rml_number(1.0f)},
{Rml::PropertyId::FlexShrink, rml_number(1.0f)},
{Rml::PropertyId::FlexBasis, rml_px(0.0f)},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
});
set_props(m_rightPane, {
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexGrow, rml_number(0.0f)},
{Rml::PropertyId::FlexShrink, rml_number(0.0f)},
{Rml::PropertyId::FlexBasis, rml_percent(40.0f)},
{Rml::PropertyId::MinWidth, rml_px(0.0f)},
});
} else {
set_props(
m_leftPane, {
{Rml::PropertyId::Display, Rml::Style::Display::Flex},
{Rml::PropertyId::FlexGrow, rml_number(1.0f)},
{Rml::PropertyId::FlexShrink, rml_number(1.0f)},
{Rml::PropertyId::FlexBasis, Rml::Style::LengthPercentageAuto::Auto},
{Rml::PropertyId::Width, rml_percent(100.0f)},
});
set_props(m_rightPane, {
{Rml::PropertyId::Display, Rml::Style::Display::None},
});
void Window::hide() {
if (mDocument != nullptr) {
mDocument->Hide();
}
}
void Window::apply_close_style() {
using namespace theme;
if (m_closeButton == nullptr) {
return;
}
const bool active = m_closeHovered || m_closeFocused;
m_closeButton->SetProperty(Rml::PropertyId::BackgroundColor,
active ? rml_color(WindowAccent, 56) : rml_color(Transparent));
set_focus_border_visible(m_closeButton, m_closeFocused);
}
} // namespace dusk::ui