UI: Implement initial document stack logic

This commit is contained in:
Luke Street
2026-04-30 17:21:55 -06:00
parent 1c9e1c0a66
commit 62edb3abc6
9 changed files with 64 additions and 61 deletions
+2 -2
View File
@@ -29,11 +29,11 @@ button {
border-bottom: 2dp #92875B;
backdrop-filter: blur(5dp);
transform: translateY(0);
transition: transform 0.5s cubic-in-out, opacity 0.5s cubic-in-out;
transition: transform 0.2s cubic-in-out;
}
.popup.popup-hidden {
transform: translateY(-100%);
transform: translateY(-64dp);
}
.popup .tab-bar {
+1 -1
View File
@@ -4,6 +4,6 @@
<link type="text/rcss" href="popup.rcss" />
</head>
<body>
<div id="popup" class="popup"></div>
<div id="popup" class="popup popup-hidden"></div>
</body>
</rml>
+23 -34
View File
@@ -14,36 +14,40 @@ namespace dusk::ui {
Popup::Popup() : Document("res/rml/popup.rml"), mRoot(mDocument->GetElementById("popup")) {
mTabBar = std::make_unique<TabBar>(mRoot, TabBar::Props{.autoSelect = false});
mTabBar->add_tab("Settings", [this] {
hide();
// TODO: make this better
auto& settingsWindow = add_document(std::make_unique<SettingsWindow>());
settingsWindow.show();
});
mTabBar->add_tab("Settings", [] { push_document(std::make_unique<SettingsWindow>()); });
mTabBar->add_tab("Warp", [] {
// TODO
});
mTabBar->add_tab("Editor", [this] {
hide();
// TODO: make this better
auto& editorWindow = add_document(std::make_unique<EditorWindow>());
editorWindow.show();
});
mTabBar->add_tab("Editor", [] { push_document(std::make_unique<EditorWindow>()); });
mTabBar->add_tab("Reset", [] {
// TODO
});
mTabBar->add_tab("Exit", [] {
// TODO
});
// Hide document after transition completion
listen(mRoot, Rml::EventId::Transitionend, [this](Rml::Event& event) {
if (event.GetTargetElement() == mRoot &&
*mRoot->GetProperty(Rml::PropertyId::Visibility) == Rml::Style::Visibility::Visible &&
!mVisible)
{
Document::hide();
}
});
// We start hidden, but want focus for an open nav event
mDocument->Focus();
}
void Popup::show() {
if (mDocument == nullptr) {
if (mDocument == nullptr || mVisible) {
return;
}
mHideDeadline.reset();
Document::show();
mRoot->SetClass("popup-hidden", false);
mTabBar->set_active_tab(-1);
mVisible = true;
}
@@ -52,15 +56,11 @@ void Popup::hide() {
mVisible = false;
return;
}
if (auto* popup = mDocument->GetElementById("popup")) {
popup->SetClass("popup-hidden", true);
mHideDeadline =
std::chrono::steady_clock::now() +
std::chrono::milliseconds(500); // Must match the transition duration in popup.rcss
} else {
Document::hide();
if (!mVisible) {
return;
}
mRoot->SetClass("popup-hidden", true);
mVisible = false;
}
@@ -78,23 +78,12 @@ bool Popup::is_visible() const {
bool Popup::handle_nav_command(Rml::Event& event, NavCommand cmd) {
if (cmd == NavCommand::Cancel) {
hide();
toggle();
return true;
}
return false;
}
void Popup::update() {
if (mDocument == nullptr) {
return;
}
if (mHideDeadline.has_value() && std::chrono::steady_clock::now() >= *mHideDeadline) {
mDocument->Hide();
mHideDeadline.reset();
}
Document::update();
}
bool Popup::focus() {
return mTabBar->focus();
}
+2 -8
View File
@@ -2,14 +2,10 @@
#include "button.hpp"
#include "document.hpp"
#include <chrono>
#include <memory>
#include <optional>
#include <vector>
#include "tab_bar.hpp"
#include <memory>
namespace dusk::ui {
class Popup : public Document {
@@ -21,7 +17,6 @@ public:
void show() override;
void hide() override;
void update() override;
bool focus() override;
void toggle();
@@ -35,7 +30,6 @@ private:
std::unique_ptr<TabBar> mTabBar;
std::unique_ptr<Button> mCloseButton;
bool mVisible = false;
std::optional<std::chrono::steady_clock::time_point> mHideDeadline;
};
} // namespace dusk::ui
+9
View File
@@ -58,6 +58,15 @@ void TabBar::add_tab(const Rml::String& title, TabCallback callback) {
}
bool TabBar::set_active_tab(int index) {
if (index == -1) {
// Clear currently selected tab
for (int i = 0; i < static_cast<int>(mTabs.size()); ++i) {
mTabs[i].button.set_selected(false);
}
mProps.selectedTabIndex = -1;
return true;
}
if (index < 0 || index >= mTabs.size() || index == mProps.selectedTabIndex) {
return false;
}
+18 -6
View File
@@ -47,20 +47,32 @@ void handle_event(const SDL_Event& event) noexcept {
// TODO
}
Document& add_document(std::unique_ptr<Document> doc) noexcept {
Document& push_document(std::unique_ptr<Document> doc, bool show) noexcept {
if (auto* doc = top_document()) {
doc->hide();
}
Document& ret = *doc;
sDocuments.push_back(std::move(doc));
if (show) {
ret.show();
}
return ret;
}
void remove_document(Document& doc) noexcept {
const auto it = std::find_if(sDocuments.begin(), sDocuments.end(),
[&doc](const std::unique_ptr<Document>& current) { return current.get() == &doc; });
if (it != sDocuments.end()) {
sDocuments.erase(it);
void pop_document() noexcept {
sDocuments.pop_back();
if (auto* doc = top_document()) {
doc->show();
}
}
Document* top_document() noexcept {
if (sDocuments.empty()) {
return nullptr;
}
return sDocuments.back().get();
}
void update() noexcept {
for (const auto& doc : sDocuments) {
doc->update();
+3 -2
View File
@@ -32,8 +32,9 @@ void shutdown() noexcept;
void handle_event(const SDL_Event& event) noexcept;
void update() noexcept;
Document& add_document(std::unique_ptr<Document> doc) noexcept;
void remove_document(Document& doc) noexcept;
Document& push_document(std::unique_ptr<Document> doc, bool show = true) noexcept;
void pop_document() noexcept;
Document* top_document() noexcept;
Popup& add_popup(std::unique_ptr<Popup> popup) noexcept;
+4
View File
@@ -124,6 +124,10 @@ bool Window::handle_nav_command(Rml::Event& event, NavCommand cmd) {
return mContentComponents.front()->focus();
}
}
if (cmd == NavCommand::Cancel) {
pop_document();
return true;
}
return mTabBar->handle_nav_command(event, cmd);
}
+2 -8
View File
@@ -586,15 +586,9 @@ int game_main(int argc, char* argv[]) {
dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f);
dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb);
dusk::ui::initialize();
// TODO: just for testing
// auto& editorWindow = dusk::ui::add_document(std::make_unique<dusk::ui::EditorWindow>());
// editorWindow.show();
// auto& settingsWindow = dusk::ui::add_document(std::make_unique<dusk::ui::SettingsWindow>());
// settingsWindow.show();
auto& popup = dusk::ui::add_document(std::make_unique<dusk::ui::Popup>());
popup.show();
dusk::ui::initialize();
dusk::ui::push_document(std::make_unique<dusk::ui::Popup>(), false);
std::string dvd_path;
bool dvd_opened = false;