mirror of
https://github.com/TwilitRealm/dusklight
synced 2026-07-25 14:06:03 -04:00
146 lines
3.9 KiB
C++
146 lines
3.9 KiB
C++
#include "modal.hpp"
|
|
|
|
#include "string_button.hpp"
|
|
|
|
namespace dusk::ui {
|
|
|
|
Modal::Modal(Props props) : WindowSmall("modal", "modal-dialog"), mProps(std::move(props)) {
|
|
if (!mProps.variant.empty()) {
|
|
mRoot->SetClass(mProps.variant, true);
|
|
}
|
|
|
|
auto* header = append(mDialog, "div");
|
|
header->SetClass("modal-header", true);
|
|
|
|
auto* title = append(header, "div");
|
|
title->SetClass("modal-title", true);
|
|
title->SetInnerRML(mProps.title);
|
|
|
|
if (!mProps.icon.empty()) {
|
|
auto* icon = append(header, "icon");
|
|
icon->SetClass(mProps.icon, true);
|
|
}
|
|
|
|
auto* body = append(mDialog, "div");
|
|
body->SetClass("modal-body", true);
|
|
body->SetInnerRML(mProps.bodyRml);
|
|
|
|
auto* actions = append(mDialog, "div");
|
|
actions->SetClass("modal-actions", true);
|
|
|
|
for (auto& action : mProps.actions) {
|
|
add_action(std::move(action));
|
|
}
|
|
|
|
mDoAud_seStartMenu(kSoundWindowOpen);
|
|
}
|
|
|
|
void Modal::add_action(ModalAction action) {
|
|
auto* actions = mDialog->QuerySelector(".modal-actions");
|
|
auto btn = std::make_unique<Button>(actions, action.label);
|
|
btn->root()->SetClass("modal-btn", true);
|
|
btn->on_pressed([this, callback = std::move(action.onPressed)] {
|
|
if (callback) {
|
|
callback(*this);
|
|
}
|
|
});
|
|
mButtons.push_back(std::move(btn));
|
|
}
|
|
|
|
void Modal::set_body(const Rml::String& bodyRml) {
|
|
mDialog->QuerySelector(".modal-body")->SetInnerRML(bodyRml);
|
|
}
|
|
|
|
void Modal::set_icon(const Rml::String& icon) {
|
|
auto* iconElem = mDialog->QuerySelector("icon");
|
|
if (icon.empty()) {
|
|
if (iconElem != nullptr) {
|
|
iconElem->GetParentNode()->RemoveChild(iconElem);
|
|
}
|
|
return;
|
|
}
|
|
if (iconElem == nullptr) {
|
|
// The constructor only creates the icon element when Props.icon is set.
|
|
iconElem = append(mDialog->QuerySelector(".modal-header"), "icon");
|
|
}
|
|
iconElem->SetClassNames(icon);
|
|
}
|
|
|
|
bool Modal::focus() {
|
|
if (!mButtons.empty()) {
|
|
return mButtons.front()->focus();
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void Modal::dismiss() {
|
|
if (mProps.onDismiss) {
|
|
mProps.onDismiss(*this);
|
|
return;
|
|
}
|
|
pop();
|
|
}
|
|
|
|
bool Modal::handle_nav_command(Rml::Event& event, NavCommand cmd) {
|
|
if (cmd == NavCommand::Cancel || cmd == NavCommand::Menu) {
|
|
mDoAud_seStartMenu(kSoundWindowClose);
|
|
dismiss();
|
|
return true;
|
|
}
|
|
|
|
int direction = 0;
|
|
if (cmd == NavCommand::Left) {
|
|
direction = -1;
|
|
} else if (cmd == NavCommand::Right) {
|
|
direction = 1;
|
|
} else {
|
|
return false;
|
|
}
|
|
|
|
auto* target = event.GetTargetElement();
|
|
for (int i = 0; i < static_cast<int>(mButtons.size()); ++i) {
|
|
if (mButtons[i]->contains(target)) {
|
|
const int next = i + direction;
|
|
if (next >= 0 && next < static_cast<int>(mButtons.size()) && mButtons[next]->focus()) {
|
|
mDoAud_seStartMenu(kSoundItemFocus);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
TextInputModal::TextInputModal(Props props) : Modal(props) {
|
|
auto modalBody = mDialog->QuerySelector(".modal-body");
|
|
|
|
mInput = std::make_unique<StringButton>(modalBody, StringButton::Props{
|
|
.getValue = [this]{return mInputText;},
|
|
.setValue = [this](Rml::String value) { mInputText = value; },
|
|
});
|
|
|
|
mInput->start_editing();
|
|
}
|
|
|
|
bool TextInputModal::handle_nav_command(Rml::Event& event, NavCommand cmd) {
|
|
auto retVal = Modal::handle_nav_command(event, cmd);
|
|
if (!retVal) {
|
|
if (mInput->root()->IsPseudoClassSet("focus") && cmd == NavCommand::Down) {
|
|
mButtons[0]->focus();
|
|
retVal = true;
|
|
} else if (!mInput->root()->IsPseudoClassSet("focus") && cmd == NavCommand::Up) {
|
|
mInput->focus();
|
|
retVal = true;
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
void TextInputModal::update() {
|
|
mInput->update();
|
|
Document::update();
|
|
}
|
|
|
|
} // namespace dusk::ui
|