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");
// 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.
auto scrape_gamename = std::make_shared<SwitchComponent>(mWindow);
scrape_gamename->setState(Settings::getInstance()->getBool("ScrapeGameNames"));
@ -116,6 +109,13 @@ void GuiScraperMenu::openContentSettings()
s->addSaveFunc([scrape_ratings] { Settings::getInstance()->setBool("ScrapeRatings",
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.
auto scrape_screenshots = std::make_shared<SwitchComponent>(mWindow);
scrape_screenshots->setState(Settings::getInstance()->getBool("ScrapeScreenshots"));

View file

@ -590,13 +590,13 @@ void GuiScraperSearch::openInputScreen(ScraperSearchParams& params)
params.nameOverride.empty() ?
MameNames::getInstance()->getCleanName(params.game->getCleanName()) :
params.nameOverride,
searchForFunc, false, "SEARCH"));
searchForFunc, false, "SEARCH", "APPLY CHANGES?"));
}
else {
mWindow->pushGui(new GuiTextEditPopup(mWindow, "SEARCH FOR",
// Initial value is last search if there was one, otherwise the clean path name.
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() &&
config->isMappedTo("select", input) &&
Settings::getInstance()->getBool("ScreenSaverControls")) {
if (!mWindow->isScreenSaverActive()) {
mWindow->startScreenSaver();
mWindow->renderScreenSaver();
}
else {
mWindow->cancelScreenSaver();
}
return true;
}
}
@ -394,7 +399,7 @@ std::vector<HelpPrompt> SystemView::getHelpPrompts()
if (!UIModeController::getInstance()->isUIModeKid() &&
Settings::getInstance()->getBool("ScreenSaverControls"))
prompts.push_back(HelpPrompt("select", "launch screensaver"));
prompts.push_back(HelpPrompt("select", "toggle screensaver"));
return prompts;
}

View file

@ -153,6 +153,7 @@ void Window::input(InputConfig* config, Input input)
}
mTimeSinceLastInput = 0;
if (!config->isMappedTo("select", input))
if (cancelScreenSaver())
return;

View file

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

View file

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

View file

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

View file

@ -7,10 +7,12 @@
//
#include "guis/GuiComplexTextEditPopup.h"
#include "guis/GuiMsgBox.h"
#include "components/ButtonComponent.h"
#include "components/MenuComponent.h"
#include "components/TextEditComponent.h"
#include "Window.h"
GuiComplexTextEditPopup::GuiComplexTextEditPopup(
Window* window,
@ -19,11 +21,16 @@ GuiComplexTextEditPopup::GuiComplexTextEditPopup(
const std::string& infoString2,
const std::string& initValue,
const std::function<void(const std::string&)>& okCallback,
bool multiLine, const char* acceptBtnText)
bool multiLine,
const char* acceptBtnText,
const char* saveConfirmationText)
: GuiComponent(window),
mBackground(window, ":/frame.png"),
mGrid(window, Vector2i(1, 5)),
mMultiLine(multiLine)
mMultiLine(multiLine),
mInitValue(initValue),
mOkCallback(okCallback),
mSaveConfirmationText(saveConfirmationText)
{
addChild(&mBackground);
addChild(&mGrid);
@ -80,7 +87,7 @@ void GuiComplexTextEditPopup::onSizeChanged()
mText->setSize(mSize.x() - 40, mText->getSize().y());
// Update grid
// Update grid.
mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y());
mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y());
mGrid.setSize(mSize);
@ -91,12 +98,18 @@ bool GuiComplexTextEditPopup::input(InputConfig* config, Input input)
if (GuiComponent::input(config, input))
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) {
delete this;
return true;
if (mText->getValue() != mInitValue) {
// 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;
}

View file

@ -28,7 +28,8 @@ public:
const std::string& initValue,
const std::function<void(const std::string&)>& okCallback,
bool multiLine,
const char* acceptBtnText = "OK");
const char* acceptBtnText = "OK",
const char* saveConfirmationText = "SAVE CHANGES?");
bool input(InputConfig* config, Input input);
void onSizeChanged();
@ -45,6 +46,9 @@ private:
std::shared_ptr<ComponentGrid> mButtonGrid;
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

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 "components/ButtonComponent.h"
@ -8,56 +15,62 @@
GuiMsgBox::GuiMsgBox(Window* window, const std::string& text,
const std::string& name1, const std::function<void()>& func1,
const std::string& name2, const std::function<void()>& func2,
const std::string& name3, const std::function<void()>& func3) : GuiComponent(window),
mBackground(window, ":/frame.png"), mGrid(window, Vector2i(1, 2))
const std::string& name3, const std::function<void()>& func3)
: GuiComponent(window),
mBackground(window, ":/frame.png"),
mGrid(window, Vector2i(1, 2))
{
float width = Renderer::getScreenWidth() * 0.6f; // max width
float minWidth = Renderer::getScreenWidth() * 0.3f; // minimum width
float width = Renderer::getScreenWidth() * 0.6f; // Max 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);
// create the buttons
mButtons.push_back(std::make_shared<ButtonComponent>(mWindow, name1, name1, std::bind(&GuiMsgBox::deleteMeAndCall, this, func1)));
// Create the buttons.
mButtons.push_back(std::make_shared<ButtonComponent>
(mWindow, name1, name1, std::bind(&GuiMsgBox::deleteMeAndCall, this, func1)));
if (!name2.empty())
mButtons.push_back(std::make_shared<ButtonComponent>(mWindow, name2, name3, std::bind(&GuiMsgBox::deleteMeAndCall, this, func2)));
mButtons.push_back(std::make_shared<ButtonComponent>
(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)));
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)
if(mButtons.size() == 1)
{
// Set accelerator automatically (button to press when "b" is pressed).
if (mButtons.size() == 1) {
mAcceleratorFunc = mButtons.front()->getPressedFunc();
}else{
for(auto it = mButtons.cbegin(); it != mButtons.cend(); it++)
{
if(Utils::String::toUpper((*it)->getText()) == "OK" || Utils::String::toUpper((*it)->getText()) == "NO")
{
}
else {
for (auto it = mButtons.cbegin(); it != mButtons.cend(); it++) {
if (Utils::String::toUpper((*it)->getText()) == "OK" ||
Utils::String::toUpper((*it)->getText()) == "NO") {
mAcceleratorFunc = (*it)->getPressedFunc();
break;
}
}
}
// put the buttons into a ComponentGrid
// Put the buttons into a ComponentGrid.
mButtonGrid = makeButtonGrid(mWindow, mButtons);
mGrid.setEntry(mButtonGrid, Vector2i(0, 1), true, false, Vector2i(1, 1), GridFlags::BORDER_TOP);
// decide final width
if(mMsg->getSize().x() < width && mButtonGrid->getSize().x() < width)
{
// mMsg and buttons are narrower than width
// Decide final width.
if (mMsg->getSize().x() < width && mButtonGrid->getSize().x() < width) {
// mMsg and buttons are narrower than width.
width = Math::max(mButtonGrid->getSize().x(), mMsg->getSize().x());
width = Math::max(width, minWidth);
}
// now that we know width, we can find height
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);
// Now that we know width, we can find height.
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);
setSize(width + HORIZONTAL_PADDING_PX*2, msgHeight + mButtonGrid->getSize().y());
// center for good measure
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f, (Renderer::getScreenHeight() - mSize.y()) / 2.0f);
// Center for good measure.
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2.0f,
(Renderer::getScreenHeight() - mSize.y()) / 2.0f);
addChild(&mBackground);
addChild(&mGrid);
@ -65,16 +78,15 @@ GuiMsgBox::GuiMsgBox(Window* window, const std::string& text,
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
// anything has been configured.
if (config->getDeviceId() == DEVICE_KEYBOARD && !config->isConfigured() && input.value &&
(input.id == SDLK_RETURN || input.id == SDLK_ESCAPE || input.id == SDLK_SPACE))
{
(input.id == SDLK_RETURN || input.id == SDLK_ESCAPE || input.id == SDLK_SPACE)) {
mAcceleratorFunc();
return true;
}
if(mAcceleratorFunc && config->isMappedTo("b", input) && input.value != 0)
{
if (mAcceleratorFunc && config->isMappedTo("b", input) && input.value != 0) {
mAcceleratorFunc();
return true;
}
@ -87,7 +99,7 @@ void GuiMsgBox::onSizeChanged()
mGrid.setSize(mSize);
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));
mGrid.onSizeChanged();
@ -101,7 +113,6 @@ void GuiMsgBox::deleteMeAndCall(const std::function<void()>& func)
if (funcCopy)
funcCopy();
}
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
#ifndef ES_CORE_GUIS_GUI_MSG_BOX_H
#define ES_CORE_GUIS_GUI_MSG_BOX_H
@ -27,7 +34,6 @@ private:
NinePatchComponent mBackground;
ComponentGrid mGrid;
std::shared_ptr<TextComponent> mMsg;
std::vector<std::shared_ptr<ButtonComponent>> mButtons;
std::shared_ptr<ComponentGrid> mButtonGrid;

View file

@ -1,17 +1,38 @@
//
// GuiTextEditPopup.cpp
//
// Simple text edit popup with a title, a text input box and OK and Cancel buttons.
//
#include "guis/GuiTextEditPopup.h"
#include "guis/GuiMsgBox.h"
#include "components/ButtonComponent.h"
#include "components/MenuComponent.h"
#include "components/TextEditComponent.h"
#include "Window.h"
GuiTextEditPopup::GuiTextEditPopup(Window* window, const std::string& title, const std::string& initValue,
const std::function<void(const std::string&)>& okCallback, bool multiLine, const char* acceptBtnText)
: GuiComponent(window), mBackground(window, ":/frame.png"), mGrid(window, Vector2i(1, 3)), mMultiLine(multiLine)
GuiTextEditPopup::GuiTextEditPopup(
Window* window,
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(&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->setValue(initValue);
@ -20,22 +41,28 @@ GuiTextEditPopup::GuiTextEditPopup(Window* window, const std::string& title, con
mText->setCursor(initValue.size());
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, "CANCEL", "discard changes", [this] { delete this; }));
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, "CANCEL", "discard changes",
[this] { delete this; }));
mButtonGrid = makeButtonGrid(mWindow, buttons);
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);
float textHeight = mText->getFont()->getHeight();
if (multiLine)
textHeight *= 6;
mText->setSize(0, textHeight);
setSize(Renderer::getScreenWidth() * 0.5f, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y() + 40);
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, (Renderer::getScreenHeight() - mSize.y()) / 2);
setSize(Renderer::getScreenWidth() * 0.5f, mTitle->getFont()->getHeight() +
textHeight + mButtonGrid->getSize().y() + 40);
setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, (Renderer::getScreenHeight() -
mSize.y()) / 2);
}
void GuiTextEditPopup::onSizeChanged()
@ -44,7 +71,7 @@ void GuiTextEditPopup::onSizeChanged()
mText->setSize(mSize.x() - 40, mText->getSize().y());
// update grid
// Update grid.
mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y());
mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y());
mGrid.setSize(mSize);
@ -55,13 +82,18 @@ bool GuiTextEditPopup::input(InputConfig* config, Input input)
if (GuiComponent::input(config, input))
return true;
// pressing back when not text editing closes us
if(config->isMappedTo("b", input) && input.value)
{
delete this;
return true;
// Pressing back when not text editing closes us.
if (config->isMappedTo("b", input) && input.value) {
if (mText->getValue() != mInitValue) {
// 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;
}

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
#ifndef 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
{
public:
GuiTextEditPopup(Window* window, const std::string& title, const std::string& initValue,
const std::function<void(const std::string&)>& okCallback, bool multiLine, const char* acceptBtnText = "OK");
GuiTextEditPopup(
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);
void onSizeChanged();
@ -28,6 +40,9 @@ private:
std::shared_ptr<ComponentGrid> mButtonGrid;
bool mMultiLine;
std::string mInitValue;
std::function<void(const std::string&)> mOkCallback;
std::string mSaveConfirmationText;
};
#endif // ES_CORE_GUIS_GUI_TEXT_EDIT_POPUP_H