Added save confirmation dialogs to the text edit components, reorganized the scraper menu slightly and fixed a bug when toggling the screensaver.

This commit is contained in:
Leon Styhre 2020-06-07 10:57:49 +02:00
parent a104b653ae
commit b7d4274c6e
13 changed files with 177 additions and 87 deletions

View file

@ -95,13 +95,6 @@ void GuiScraperMenu::openContentSettings()
{ {
auto s = new GuiSettings(mWindow, "SCRAPER CONTENT SETTINGS"); auto s = new GuiSettings(mWindow, "SCRAPER CONTENT SETTINGS");
// Scrape metadata.
auto scrape_metadata = std::make_shared<SwitchComponent>(mWindow);
scrape_metadata->setState(Settings::getInstance()->getBool("ScrapeMetadata"));
s->addWithLabel("SCRAPE METADATA", scrape_metadata);
s->addSaveFunc([scrape_metadata] { Settings::getInstance()->setBool("ScrapeMetadata",
scrape_metadata->getState()); });
// Scrape game names. // Scrape game names.
auto scrape_gamename = std::make_shared<SwitchComponent>(mWindow); auto scrape_gamename = std::make_shared<SwitchComponent>(mWindow);
scrape_gamename->setState(Settings::getInstance()->getBool("ScrapeGameNames")); scrape_gamename->setState(Settings::getInstance()->getBool("ScrapeGameNames"));
@ -116,6 +109,13 @@ void GuiScraperMenu::openContentSettings()
s->addSaveFunc([scrape_ratings] { Settings::getInstance()->setBool("ScrapeRatings", s->addSaveFunc([scrape_ratings] { Settings::getInstance()->setBool("ScrapeRatings",
scrape_ratings->getState()); }); scrape_ratings->getState()); });
// Scrape other metadata.
auto scrape_metadata = std::make_shared<SwitchComponent>(mWindow);
scrape_metadata->setState(Settings::getInstance()->getBool("ScrapeMetadata"));
s->addWithLabel("SCRAPE OTHER METADATA", scrape_metadata);
s->addSaveFunc([scrape_metadata] { Settings::getInstance()->setBool("ScrapeMetadata",
scrape_metadata->getState()); });
// Scrape screenshots images. // Scrape screenshots images.
auto scrape_screenshots = std::make_shared<SwitchComponent>(mWindow); auto scrape_screenshots = std::make_shared<SwitchComponent>(mWindow);
scrape_screenshots->setState(Settings::getInstance()->getBool("ScrapeScreenshots")); scrape_screenshots->setState(Settings::getInstance()->getBool("ScrapeScreenshots"));

View file

@ -590,13 +590,13 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams& params)
params.nameOverride.empty() ? params.nameOverride.empty() ?
MameNames::getInstance()->getCleanName(params.game->getCleanName()) : MameNames::getInstance()->getCleanName(params.game->getCleanName()) :
params.nameOverride, params.nameOverride,
searchForFunc, false, "SEARCH")); searchForFunc, false, "SEARCH", "APPLY CHANGES?"));
} }
else { else {
mWindow->pushGui(new GuiTextEditPopup(mWindow, "SEARCH FOR", mWindow->pushGui(new GuiTextEditPopup(mWindow, "SEARCH FOR",
// Initial value is last search if there was one, otherwise the clean path name. // Initial value is last search if there was one, otherwise the clean path name.
params.nameOverride.empty() ? params.game->getCleanName() : params.nameOverride, params.nameOverride.empty() ? params.game->getCleanName() : params.nameOverride,
searchForFunc, false, "SEARCH")); searchForFunc, false, "SEARCH", "APPLY CHANGES?"));
} }
} }

View file

@ -212,8 +212,13 @@ bool SystemView::input(InputConfig* config, Input input)
if (!UIModeController::getInstance()->isUIModeKid() && if (!UIModeController::getInstance()->isUIModeKid() &&
config->isMappedTo("select", input) && config->isMappedTo("select", input) &&
Settings::getInstance()->getBool("ScreenSaverControls")) { Settings::getInstance()->getBool("ScreenSaverControls")) {
mWindow->startScreenSaver(); if (!mWindow->isScreenSaverActive()) {
mWindow->renderScreenSaver(); mWindow->startScreenSaver();
mWindow->renderScreenSaver();
}
else {
mWindow->cancelScreenSaver();
}
return true; return true;
} }
} }
@ -394,7 +399,7 @@ std::vector<HelpPrompt> SystemView::getHelpPrompts()
if (!UIModeController::getInstance()->isUIModeKid() && if (!UIModeController::getInstance()->isUIModeKid() &&
Settings::getInstance()->getBool("ScreenSaverControls")) Settings::getInstance()->getBool("ScreenSaverControls"))
prompts.push_back(HelpPrompt("select", "launch screensaver")); prompts.push_back(HelpPrompt("select", "toggle screensaver"));
return prompts; return prompts;
} }

View file

@ -153,8 +153,9 @@ void Window::input(InputConfig* config, Input input)
} }
mTimeSinceLastInput = 0; mTimeSinceLastInput = 0;
if (cancelScreenSaver()) if (!config->isMappedTo("select", input))
return; if (cancelScreenSaver())
return;
if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_g && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug")) if(config->getDeviceId() == DEVICE_KEYBOARD && input.value && input.id == SDLK_g && SDL_GetModState() & KMOD_LCTRL && Settings::getInstance()->getBool("Debug"))
{ {

View file

@ -76,6 +76,7 @@ public:
void startScreenSaver(); void startScreenSaver();
bool cancelScreenSaver(); bool cancelScreenSaver();
void renderScreenSaver(); void renderScreenSaver();
bool isScreenSaverActive() { return mRenderScreenSaver; };
private: private:
void onSleep(); void onSleep();

View file

@ -51,6 +51,7 @@ void TextEditComponent::onSizeChanged()
void TextEditComponent::setValue(const std::string& val) void TextEditComponent::setValue(const std::string& val)
{ {
mText = val; mText = val;
mTextOrig = val;
onTextChanged(); onTextChanged();
} }
@ -126,8 +127,10 @@ bool TextEditComponent::input(InputConfig* config, Input input)
return true; return true;
} }
// Stop editing.
if ((config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_ESCAPE) || if ((config->getDeviceId() == DEVICE_KEYBOARD && input.id == SDLK_ESCAPE) ||
(config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedTo("b", input))) { (config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedTo("b", input))) {
mTextOrig = mText;
stopEditing(); stopEditing();
return true; return true;
} }
@ -138,11 +141,9 @@ bool TextEditComponent::input(InputConfig* config, Input input)
else if (config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedLike("down", input)) { else if (config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedLike("down", input)) {
// TODO. // TODO.
} }
else if (config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedTo("y", input)) { else if (config->getDeviceId() != DEVICE_KEYBOARD && config->isMappedTo("y", input)) {
textInput("\b"); textInput("\b");
} }
else if (cursor_left || cursor_right) { else if (cursor_left || cursor_right) {
mCursorRepeatDir = cursor_left ? -1 : 1; mCursorRepeatDir = cursor_left ? -1 : 1;
mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED); mCursorRepeatTimer = -(CURSOR_REPEAT_START_DELAY - CURSOR_REPEAT_SPEED);

View file

@ -55,6 +55,7 @@ private:
Vector2f getTextAreaSize() const; Vector2f getTextAreaSize() const;
std::string mText; std::string mText;
std::string mTextOrig;
bool mFocused; bool mFocused;
bool mEditing; bool mEditing;
unsigned int mCursor; // Cursor position in characters. unsigned int mCursor; // Cursor position in characters.

View file

@ -7,10 +7,12 @@
// //
#include "guis/GuiComplexTextEditPopup.h" #include "guis/GuiComplexTextEditPopup.h"
#include "guis/GuiMsgBox.h"
#include "components/ButtonComponent.h" #include "components/ButtonComponent.h"
#include "components/MenuComponent.h" #include "components/MenuComponent.h"
#include "components/TextEditComponent.h" #include "components/TextEditComponent.h"
#include "Window.h"
GuiComplexTextEditPopup::GuiComplexTextEditPopup( GuiComplexTextEditPopup::GuiComplexTextEditPopup(
Window* window, Window* window,
@ -19,11 +21,16 @@ GuiComplexTextEditPopup::GuiComplexTextEditPopup(
const std::string& infoString2, const std::string& infoString2,
const std::string& initValue, const std::string& initValue,
const std::function<void(const std::string&)>& okCallback, const std::function<void(const std::string&)>& okCallback,
bool multiLine, const char* acceptBtnText) bool multiLine,
const char* acceptBtnText,
const char* saveConfirmationText)
: GuiComponent(window), : GuiComponent(window),
mBackground(window, ":/frame.png"), mBackground(window, ":/frame.png"),
mGrid(window, Vector2i(1, 5)), mGrid(window, Vector2i(1, 5)),
mMultiLine(multiLine) mMultiLine(multiLine),
mInitValue(initValue),
mOkCallback(okCallback),
mSaveConfirmationText(saveConfirmationText)
{ {
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
@ -80,7 +87,7 @@ void GuiComplexTextEditPopup::onSizeChanged()
mText->setSize(mSize.x() - 40, mText->getSize().y()); mText->setSize(mSize.x() - 40, mText->getSize().y());
// Update grid // Update grid.
mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y()); mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y());
mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y()); mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y());
mGrid.setSize(mSize); mGrid.setSize(mSize);
@ -91,12 +98,18 @@ bool GuiComplexTextEditPopup::input(InputConfig* config, Input input)
if (GuiComponent::input(config, input)) if (GuiComponent::input(config, input))
return true; return true;
// Pressing back button when not text editing closes us // Pressing back when not text editing closes us.
if (config->isMappedTo("b", input) && input.value) { if (config->isMappedTo("b", input) && input.value) {
delete this; if (mText->getValue() != mInitValue) {
return true; // Changes were made, ask if the user wants to save them.
mWindow->pushGui(new GuiMsgBox(mWindow, mSaveConfirmationText, "YES",
[this] { this->mOkCallback(mText->getValue()); delete this; return true; },
"NO", [this] { delete this; return false; }));
}
else {
delete this;
}
} }
return false; return false;
} }

View file

@ -28,7 +28,8 @@ public:
const std::string& initValue, const std::string& initValue,
const std::function<void(const std::string&)>& okCallback, const std::function<void(const std::string&)>& okCallback,
bool multiLine, bool multiLine,
const char* acceptBtnText = "OK"); const char* acceptBtnText = "OK",
const char* saveConfirmationText = "SAVE CHANGES?");
bool input(InputConfig* config, Input input); bool input(InputConfig* config, Input input);
void onSizeChanged(); void onSizeChanged();
@ -45,6 +46,9 @@ private:
std::shared_ptr<ComponentGrid> mButtonGrid; std::shared_ptr<ComponentGrid> mButtonGrid;
bool mMultiLine; bool mMultiLine;
std::string mInitValue;
std::function<void(const std::string&)> mOkCallback;
std::string mSaveConfirmationText;
}; };
#endif // ES_CORE_GUIS_GUI_COMPLEX_TEXT_EDIT_POPUP_H #endif // ES_CORE_GUIS_GUI_COMPLEX_TEXT_EDIT_POPUP_H

View file

@ -1,3 +1,10 @@
//
// GuiMsgBox.cpp
//
// Popup message dialog with a notification text and a choice of one,
// two or three buttons.
//
#include "guis/GuiMsgBox.h" #include "guis/GuiMsgBox.h"
#include "components/ButtonComponent.h" #include "components/ButtonComponent.h"
@ -6,58 +13,64 @@
#define HORIZONTAL_PADDING_PX 20 #define HORIZONTAL_PADDING_PX 20
GuiMsgBox::GuiMsgBox(Window* window, const std::string& text, GuiMsgBox::GuiMsgBox(Window* window, const std::string& text,
const std::string& name1, const std::function<void()>& func1, const std::string& name1, const std::function<void()>& func1,
const std::string& name2, const std::function<void()>& func2, const std::string& name2, const std::function<void()>& func2,
const std::string& name3, const std::function<void()>& func3) : GuiComponent(window), const std::string& name3, const std::function<void()>& func3)
mBackground(window, ":/frame.png"), mGrid(window, Vector2i(1, 2)) : GuiComponent(window),
mBackground(window, ":/frame.png"),
mGrid(window, Vector2i(1, 2))
{ {
float width = Renderer::getScreenWidth() * 0.6f; // max width float width = Renderer::getScreenWidth() * 0.6f; // Max width.
float minWidth = Renderer::getScreenWidth() * 0.3f; // minimum width float minWidth = Renderer::getScreenWidth() * 0.3f; // Minimum width.
mMsg = std::make_shared<TextComponent>(mWindow, text, Font::get(FONT_SIZE_MEDIUM), 0x777777FF, ALIGN_CENTER); mMsg = std::make_shared<TextComponent>(mWindow, text, Font::get(FONT_SIZE_MEDIUM),
0x777777FF, ALIGN_CENTER);
mGrid.setEntry(mMsg, Vector2i(0, 0), false, false); mGrid.setEntry(mMsg, Vector2i(0, 0), false, false);
// create the buttons // Create the buttons.
mButtons.push_back(std::make_shared<ButtonComponent>(mWindow, name1, name1, std::bind(&GuiMsgBox::deleteMeAndCall, this, func1))); mButtons.push_back(std::make_shared<ButtonComponent>
if(!name2.empty()) (mWindow, name1, name1, std::bind(&GuiMsgBox::deleteMeAndCall, this, func1)));
mButtons.push_back(std::make_shared<ButtonComponent>(mWindow, name2, name3, std::bind(&GuiMsgBox::deleteMeAndCall, this, func2))); if (!name2.empty())
if(!name3.empty()) mButtons.push_back(std::make_shared<ButtonComponent>
mButtons.push_back(std::make_shared<ButtonComponent>(mWindow, name3, name3, std::bind(&GuiMsgBox::deleteMeAndCall, this, func3))); (mWindow, name2, name3, std::bind(&GuiMsgBox::deleteMeAndCall, this, func2)));
if (!name3.empty())
mButtons.push_back(std::make_shared<ButtonComponent>
(mWindow, name3, name3, std::bind(&GuiMsgBox::deleteMeAndCall, this, func3)));
// set accelerator automatically (button to press when "b" is pressed) // Set accelerator automatically (button to press when "b" is pressed).
if(mButtons.size() == 1) if (mButtons.size() == 1) {
{
mAcceleratorFunc = mButtons.front()->getPressedFunc(); mAcceleratorFunc = mButtons.front()->getPressedFunc();
}else{ }
for(auto it = mButtons.cbegin(); it != mButtons.cend(); it++) else {
{ for (auto it = mButtons.cbegin(); it != mButtons.cend(); it++) {
if(Utils::String::toUpper((*it)->getText()) == "OK" || Utils::String::toUpper((*it)->getText()) == "NO") if (Utils::String::toUpper((*it)->getText()) == "OK" ||
{ Utils::String::toUpper((*it)->getText()) == "NO") {
mAcceleratorFunc = (*it)->getPressedFunc(); mAcceleratorFunc = (*it)->getPressedFunc();
break; break;
} }
} }
} }
// put the buttons into a ComponentGrid // Put the buttons into a ComponentGrid.
mButtonGrid = makeButtonGrid(mWindow, mButtons); mButtonGrid = makeButtonGrid(mWindow, mButtons);
mGrid.setEntry(mButtonGrid, Vector2i(0, 1), true, false, Vector2i(1, 1), GridFlags::BORDER_TOP); mGrid.setEntry(mButtonGrid, Vector2i(0, 1), true, false, Vector2i(1, 1), GridFlags::BORDER_TOP);
// decide final width // Decide final width.
if(mMsg->getSize().x() < width && mButtonGrid->getSize().x() < width) if (mMsg->getSize().x() < width && mButtonGrid->getSize().x() < width) {
{ // mMsg and buttons are narrower than width.
// mMsg and buttons are narrower than width
width = Math::max(mButtonGrid->getSize().x(), mMsg->getSize().x()); width = Math::max(mButtonGrid->getSize().x(), mMsg->getSize().x());
width = Math::max(width, minWidth); width = Math::max(width, minWidth);
} }
// now that we know width, we can find height // Now that we know width, we can find height.
mMsg->setSize(width, 0); // mMsg->getSize.y() now returns the proper length mMsg->setSize(width, 0); // mMsg->getSize.y() now returns the proper length.
const float msgHeight = Math::max(Font::get(FONT_SIZE_LARGE)->getHeight(), mMsg->getSize().y()*1.225f); const float msgHeight = Math::max(Font::get(FONT_SIZE_LARGE)->getHeight(),
mMsg->getSize().y()*1.225f);
setSize(width + HORIZONTAL_PADDING_PX*2, msgHeight + mButtonGrid->getSize().y()); setSize(width + HORIZONTAL_PADDING_PX*2, msgHeight + mButtonGrid->getSize().y());
// center for good measure // Center for good measure.
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, (Renderer::getScreenHeight() - mSize.y()) / 2.0f); setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f,
(Renderer::getScreenHeight() - mSize.y()) / 2.0f);
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
@ -65,16 +78,15 @@ GuiMsgBox::GuiMsgBox(Window* window, const std::string& text,
bool GuiMsgBox::input(InputConfig* config, Input input) bool GuiMsgBox::input(InputConfig* config, Input input)
{ {
// special case for when GuiMsgBox comes up to report errors before anything has been configured // Special case for when GuiMsgBox comes up to report errors before
if(config->getDeviceId() == DEVICE_KEYBOARD && !config->isConfigured() && input.value && // anything has been configured.
(input.id == SDLK_RETURN || input.id == SDLK_ESCAPE || input.id == SDLK_SPACE)) if (config->getDeviceId() == DEVICE_KEYBOARD && !config->isConfigured() && input.value &&
{ (input.id == SDLK_RETURN || input.id == SDLK_ESCAPE || input.id == SDLK_SPACE)) {
mAcceleratorFunc(); mAcceleratorFunc();
return true; return true;
} }
if(mAcceleratorFunc && config->isMappedTo("b", input) && input.value != 0) if (mAcceleratorFunc && config->isMappedTo("b", input) && input.value != 0) {
{
mAcceleratorFunc(); mAcceleratorFunc();
return true; return true;
} }
@ -87,7 +99,7 @@ void GuiMsgBox::onSizeChanged()
mGrid.setSize(mSize); mGrid.setSize(mSize);
mGrid.setRowHeightPerc(1, mButtonGrid->getSize().y() / mSize.y()); mGrid.setRowHeightPerc(1, mButtonGrid->getSize().y() / mSize.y());
// update messagebox size // Update messagebox size.
mMsg->setSize(mSize.x() - HORIZONTAL_PADDING_PX*2, mGrid.getRowHeight(0)); mMsg->setSize(mSize.x() - HORIZONTAL_PADDING_PX*2, mGrid.getRowHeight(0));
mGrid.onSizeChanged(); mGrid.onSizeChanged();
@ -99,9 +111,8 @@ void GuiMsgBox::deleteMeAndCall(const std::function<void()>& func)
auto funcCopy = func; auto funcCopy = func;
delete this; delete this;
if(funcCopy) if (funcCopy)
funcCopy(); funcCopy();
} }
std::vector<HelpPrompt> GuiMsgBox::getHelpPrompts() std::vector<HelpPrompt> GuiMsgBox::getHelpPrompts()

View file

@ -1,3 +1,10 @@
//
// GuiMsgBox.h
//
// Popup message dialog with a notification text and a choice of one,
// two or three buttons.
//
#pragma once #pragma once
#ifndef ES_CORE_GUIS_GUI_MSG_BOX_H #ifndef ES_CORE_GUIS_GUI_MSG_BOX_H
#define ES_CORE_GUIS_GUI_MSG_BOX_H #define ES_CORE_GUIS_GUI_MSG_BOX_H
@ -27,9 +34,8 @@ private:
NinePatchComponent mBackground; NinePatchComponent mBackground;
ComponentGrid mGrid; ComponentGrid mGrid;
std::shared_ptr<TextComponent> mMsg; std::shared_ptr<TextComponent> mMsg;
std::vector< std::shared_ptr<ButtonComponent> > mButtons; std::vector<std::shared_ptr<ButtonComponent>> mButtons;
std::shared_ptr<ComponentGrid> mButtonGrid; std::shared_ptr<ComponentGrid> mButtonGrid;
std::function<void()> mAcceleratorFunc; std::function<void()> mAcceleratorFunc;
}; };

View file

@ -1,41 +1,68 @@
//
// GuiTextEditPopup.cpp
//
// Simple text edit popup with a title, a text input box and OK and Cancel buttons.
//
#include "guis/GuiTextEditPopup.h" #include "guis/GuiTextEditPopup.h"
#include "guis/GuiMsgBox.h"
#include "components/ButtonComponent.h" #include "components/ButtonComponent.h"
#include "components/MenuComponent.h" #include "components/MenuComponent.h"
#include "components/TextEditComponent.h" #include "components/TextEditComponent.h"
#include "Window.h"
GuiTextEditPopup::GuiTextEditPopup(Window* window, const std::string& title, const std::string& initValue, GuiTextEditPopup::GuiTextEditPopup(
const std::function<void(const std::string&)>& okCallback, bool multiLine, const char* acceptBtnText) Window* window,
: GuiComponent(window), mBackground(window, ":/frame.png"), mGrid(window, Vector2i(1, 3)), mMultiLine(multiLine) const std::string& title,
const std::string& initValue,
const std::function<void(const std::string&)>& okCallback,
bool multiLine,
const char* acceptBtnText,
const char* saveConfirmationText)
: GuiComponent(window),
mBackground(window, ":/frame.png"),
mGrid(window, Vector2i(1, 3)),
mMultiLine(multiLine),
mInitValue(initValue),
mOkCallback(okCallback),
mSaveConfirmationText(saveConfirmationText)
{ {
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
mTitle = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(title), Font::get(FONT_SIZE_MEDIUM), 0x555555FF, ALIGN_CENTER); mTitle = std::make_shared<TextComponent>(mWindow, Utils::String::toUpper(title),
Font::get(FONT_SIZE_MEDIUM), 0x555555FF, ALIGN_CENTER);
mText = std::make_shared<TextEditComponent>(mWindow); mText = std::make_shared<TextEditComponent>(mWindow);
mText->setValue(initValue); mText->setValue(initValue);
if(!multiLine) if (!multiLine)
mText->setCursor(initValue.size()); mText->setCursor(initValue.size());
std::vector< std::shared_ptr<ButtonComponent> > buttons; std::vector< std::shared_ptr<ButtonComponent> > buttons;
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, acceptBtnText, acceptBtnText, [this, okCallback] { okCallback(mText->getValue()); delete this; })); buttons.push_back(std::make_shared<ButtonComponent>(mWindow, acceptBtnText, acceptBtnText,
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "discard changes", [this] { delete this; })); [this, okCallback] { okCallback(mText->getValue()); delete this; }));
buttons.push_back(std::make_shared<ButtonComponent>(mWindow, "CANCEL", "discard changes",
[this] { delete this; }));
mButtonGrid = makeButtonGrid(mWindow, buttons); mButtonGrid = makeButtonGrid(mWindow, buttons);
mGrid.setEntry(mTitle, Vector2i(0, 0), false, true); mGrid.setEntry(mTitle, Vector2i(0, 0), false, true);
mGrid.setEntry(mText, Vector2i(0, 1), true, false, Vector2i(1, 1), GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM); mGrid.setEntry(mText, Vector2i(0, 1), true, false, Vector2i(1, 1),
GridFlags::BORDER_TOP | GridFlags::BORDER_BOTTOM);
mGrid.setEntry(mButtonGrid, Vector2i(0, 2), true, false); mGrid.setEntry(mButtonGrid, Vector2i(0, 2), true, false);
float textHeight = mText->getFont()->getHeight(); float textHeight = mText->getFont()->getHeight();
if(multiLine)
if (multiLine)
textHeight *= 6; textHeight *= 6;
mText->setSize(0, textHeight); mText->setSize(0, textHeight);
setSize(Renderer::getScreenWidth() * 0.5f, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y() + 40); setSize(Renderer::getScreenWidth() * 0.5f, mTitle->getFont()->getHeight() +
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, (Renderer::getScreenHeight() - mSize.y()) / 2); textHeight + mButtonGrid->getSize().y() + 40);
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, (Renderer::getScreenHeight() -
mSize.y()) / 2);
} }
void GuiTextEditPopup::onSizeChanged() void GuiTextEditPopup::onSizeChanged()
@ -44,7 +71,7 @@ void GuiTextEditPopup::onSizeChanged()
mText->setSize(mSize.x() - 40, mText->getSize().y()); mText->setSize(mSize.x() - 40, mText->getSize().y());
// update grid // Update grid.
mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y()); mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y());
mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y()); mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y());
mGrid.setSize(mSize); mGrid.setSize(mSize);
@ -52,16 +79,21 @@ void GuiTextEditPopup::onSizeChanged()
bool GuiTextEditPopup::input(InputConfig* config, Input input) bool GuiTextEditPopup::input(InputConfig* config, Input input)
{ {
if(GuiComponent::input(config, input)) if (GuiComponent::input(config, input))
return true; return true;
// pressing back when not text editing closes us // Pressing back when not text editing closes us.
if(config->isMappedTo("b", input) && input.value) if (config->isMappedTo("b", input) && input.value) {
{ if (mText->getValue() != mInitValue) {
delete this; // Changes were made, ask if the user wants to save them.
return true; mWindow->pushGui(new GuiMsgBox(mWindow, mSaveConfirmationText, "YES",
[this] { this->mOkCallback(mText->getValue()); delete this; return true; },
"NO", [this] { delete this; return false; }));
}
else {
delete this;
}
} }
return false; return false;
} }

View file

@ -1,3 +1,9 @@
//
// GuiTextEditPopup.h
//
// Simple text edit popup with a title, a text input box and OK and Cancel buttons.
//
#pragma once #pragma once
#ifndef ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H #ifndef ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H
#define ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H #define ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H
@ -12,8 +18,14 @@ class TextEditComponent;
class GuiTextEditPopup : public GuiComponent class GuiTextEditPopup : public GuiComponent
{ {
public: public:
GuiTextEditPopup(Window* window, const std::string& title, const std::string& initValue, GuiTextEditPopup(
const std::function<void(const std::string&)>& okCallback, bool multiLine, const char* acceptBtnText = "OK"); Window* window,
const std::string& title,
const std::string& initValue,
const std::function<void(const std::string&)>& okCallback,
bool multiLine,
const char* acceptBtnText = "OK",
const char* saveConfirmationText = "SAVE CHANGES?");
bool input(InputConfig* config, Input input); bool input(InputConfig* config, Input input);
void onSizeChanged(); void onSizeChanged();
@ -28,6 +40,9 @@ private:
std::shared_ptr<ComponentGrid> mButtonGrid; std::shared_ptr<ComponentGrid> mButtonGrid;
bool mMultiLine; bool mMultiLine;
std::string mInitValue;
std::function<void(const std::string&)> mOkCallback;
std::string mSaveConfirmationText;
}; };
#endif // ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H #endif // ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H