From 91546ac2bcc1baf8f080ca5138873f03bf4f49c8 Mon Sep 17 00:00:00 2001 From: Aloshi Date: Fri, 21 Mar 2014 11:10:19 -0500 Subject: [PATCH] Added new text editing style to GuiMetaDataEd as per UI concepts. --- CMakeLists.txt | 2 + src/MetaData.cpp | 36 ----------------- src/MetaData.h | 19 --------- src/components/DateTimeComponent.cpp | 4 +- src/components/DateTimeComponent.h | 17 ++++---- src/components/TextEditComponent.h | 1 + src/guis/GuiMetaDataEd.cpp | 60 +++++++++++++++++++++++++++- src/guis/GuiTextEditPopup.cpp | 59 +++++++++++++++++++++++++++ src/guis/GuiTextEditPopup.h | 27 +++++++++++++ 9 files changed, 157 insertions(+), 68 deletions(-) create mode 100644 src/guis/GuiTextEditPopup.cpp create mode 100644 src/guis/GuiTextEditPopup.h diff --git a/CMakeLists.txt b/CMakeLists.txt index c60009dfb..359dcb081 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -192,6 +192,7 @@ set(ES_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.h ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperStart.h + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiTextEditPopup.h ${CMAKE_CURRENT_SOURCE_DIR}/src/scrapers/Scraper.h ${CMAKE_CURRENT_SOURCE_DIR}/src/scrapers/GamesDBScraper.h @@ -276,6 +277,7 @@ set(ES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiSettings.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperMulti.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiScraperStart.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/src/guis/GuiTextEditPopup.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/scrapers/Scraper.cpp ${CMAKE_CURRENT_SOURCE_DIR}/src/scrapers/GamesDBScraper.cpp diff --git a/src/MetaData.cpp b/src/MetaData.cpp index 917fb07f4..5ea5a5bb3 100644 --- a/src/MetaData.cpp +++ b/src/MetaData.cpp @@ -2,11 +2,6 @@ #include "components/TextComponent.h" #include "Log.h" -#include "components/TextEditComponent.h" -#include "components/RatingComponent.h" -#include "components/DateTimeComponent.h" - - MetaDataDecl gameDecls[] = { {"name", MD_STRING, "", false}, {"desc", MD_MULTILINE_STRING, "", false}, @@ -133,37 +128,6 @@ boost::posix_time::ptime MetaDataList::getTime(const std::string& key) const return string_to_ptime(get(key), "%Y%m%dT%H%M%S%F%q"); } -std::shared_ptr MetaDataList::makeEditor(Window* window, MetaDataType as) -{ - switch(as) - { - case MD_RATING: - { - return std::make_shared(window); - } - case MD_MULTILINE_STRING: - { - auto comp = std::make_shared(window); - comp->setSize(comp->getSize().x(), comp->getSize().y() * 3); - return comp; - } - case MD_DATE: - { - return std::make_shared(window); - } - case MD_TIME: - { - auto comp = std::make_shared(window); - comp->setDisplayMode(DateTimeComponent::DISP_RELATIVE_TO_NOW); - return comp; - } - default: - { - return std::make_shared(window); - } - } -} - //util function boost::posix_time::ptime string_to_ptime(const std::string& str, const std::string& fmt) { diff --git a/src/MetaData.h b/src/MetaData.h index f7a2b5c0a..9842edfb7 100644 --- a/src/MetaData.h +++ b/src/MetaData.h @@ -55,8 +55,6 @@ public: float getFloat(const std::string& key) const; boost::posix_time::ptime getTime(const std::string& key) const; - static std::shared_ptr makeEditor(Window* window, MetaDataType as); - inline MetaDataListType getType() const { return mType; } inline const std::vector& getMDD() const { return getMDDByType(getType()); } @@ -64,20 +62,3 @@ private: MetaDataListType mType; std::map mMap; }; - - - -//options for storing metadata... -//store internally everything as a string - this is all going to be read to/from XML anyway, after all -// - problem: this does not play nice with lists of values -//store using individual get/set functions ala Settings - this is a fair amount of work but the most explicit and type-safe, for better or worse - -//let's think about some of the special types we would like to support... -//image paths, sound paths, ratings, play counts -//these get represented behind-the-scenes as strings, floats, and integers, and are eventually saved as strings -//the only specialty is how they're edited and viewed, really - -//so we need... -//to be able to iterate through the available metadata -//create components designed to either DISPLAY or EDIT a given piece of metadata -//save and load metadata diff --git a/src/components/DateTimeComponent.cpp b/src/components/DateTimeComponent.cpp index aeda8cbc4..390807c85 100644 --- a/src/components/DateTimeComponent.cpp +++ b/src/components/DateTimeComponent.cpp @@ -5,8 +5,8 @@ #include "../Log.h" #include "../Util.h" -DateTimeComponent::DateTimeComponent(Window* window) : GuiComponent(window), - mEditing(false), mEditIndex(0), mDisplayMode(DISP_DATE), mRelativeUpdateAccumulator(0), +DateTimeComponent::DateTimeComponent(Window* window, DisplayMode dispMode) : GuiComponent(window), + mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0), mColor(0x000000FF) { mSize << 64, (float)getFont()->getHeight(); diff --git a/src/components/DateTimeComponent.h b/src/components/DateTimeComponent.h index 0fd5274fc..2df70b08b 100644 --- a/src/components/DateTimeComponent.h +++ b/src/components/DateTimeComponent.h @@ -8,8 +8,14 @@ class DateTimeComponent : public GuiComponent { public: - // Display mode will initialize to DISP_DATE. - DateTimeComponent(Window* window); + enum DisplayMode + { + DISP_DATE, + DISP_DATE_TIME, + DISP_RELATIVE_TO_NOW + }; + + DateTimeComponent(Window* window, DisplayMode dispMode = DISP_DATE); void setValue(const std::string& val) override; std::string getValue() const override; @@ -18,13 +24,6 @@ public: void update(int deltaTime) override; void render(const Eigen::Affine3f& parentTrans) override; - enum DisplayMode - { - DISP_DATE, - DISP_DATE_TIME, - DISP_RELATIVE_TO_NOW - }; - // Set how the point in time will be displayed: // * DISP_DATE - only display the date. // * DISP_DATE_TIME - display both the date and the time on that date. diff --git a/src/components/TextEditComponent.h b/src/components/TextEditComponent.h index 62c24688f..b0f8a7e0d 100644 --- a/src/components/TextEditComponent.h +++ b/src/components/TextEditComponent.h @@ -26,6 +26,7 @@ public: std::string getValue() const override; inline bool isEditing() const { return mEditing; }; + inline const std::shared_ptr& getFont() const { return mFont; } virtual std::vector getHelpPrompts() override; diff --git a/src/guis/GuiMetaDataEd.cpp b/src/guis/GuiMetaDataEd.cpp index 5cee1ed57..83b83939c 100644 --- a/src/guis/GuiMetaDataEd.cpp +++ b/src/guis/GuiMetaDataEd.cpp @@ -7,6 +7,11 @@ #include "GuiMsgBox.h" #include +#include "../components/TextEditComponent.h" +#include "../components/DateTimeComponent.h" +#include "../components/RatingComponent.h" +#include "GuiTextEditPopup.h" + GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector& mdd, ScraperSearchParams scraperParams, const std::string& header, std::function saveCallback, std::function deleteFunc) : GuiComponent(window), mScraperParams(scraperParams), @@ -22,10 +27,61 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector // populate list for(auto iter = mdd.begin(); iter != mdd.end(); iter++) { - auto ed = MetaDataList::makeEditor(mWindow, iter->type); + std::shared_ptr ed; + + // create ed and add it (and any related components) to mMenu + // ed's value will be set below + switch(iter->type) + { + case MD_RATING: + { + ed = std::make_shared(window); + mMenu.addWithLabel(iter->key, ed); + break; + } + case MD_DATE: + { + ed = std::make_shared(window); + mMenu.addWithLabel(iter->key, ed); + break; + } + case MD_TIME: + { + ed = std::make_shared(window, DateTimeComponent::DISP_RELATIVE_TO_NOW); + mMenu.addWithLabel(iter->key, ed); + break; + } + case MD_MULTILINE_STRING: + default: + { + // MD_STRING + ComponentListRow row; + auto lbl = std::make_shared(mWindow, iter->key, Font::get(FONT_SIZE_SMALL), 0x777777FF); + row.addElement(lbl, true); // label + + ed = std::make_shared(window, "", Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT), 0x777777FF); + row.addElement(ed, true); + + auto bracket = std::make_shared(mWindow); + bracket->setImage(":/sq_bracket.png"); + bracket->setResize(Eigen::Vector2f(0, lbl->getSize().y() * 0.8f)); + row.addElement(bracket, false); + + bool multiLine = iter->type == MD_MULTILINE_STRING; + const std::string& title = iter->key; + auto updateVal = [ed](const std::string& newVal) { ed->setValue(newVal); }; // ok callback (apply new value to ed) + row.makeAcceptInputHandler([this, title, ed, updateVal, multiLine] { + mWindow->pushGui(new GuiTextEditPopup(mWindow, title, ed->getValue(), updateVal, multiLine)); + }); + + mMenu.addRow(row); + break; + } + } + + assert(ed); ed->setValue(mMetaData->get(iter->key)); mEditors.push_back(ed); - mMenu.addWithLabel(iter->key, ed); } //add buttons diff --git a/src/guis/GuiTextEditPopup.cpp b/src/guis/GuiTextEditPopup.cpp new file mode 100644 index 000000000..342f74785 --- /dev/null +++ b/src/guis/GuiTextEditPopup.cpp @@ -0,0 +1,59 @@ +#include "GuiTextEditPopup.h" +#include "../components/MenuComponent.h" + +using namespace Eigen; + +GuiTextEditPopup::GuiTextEditPopup(Window* window, const std::string& title, const std::string& initValue, + const std::function& okCallback, bool multiLine, const char* acceptBtnText) + : GuiComponent(window), mBackground(window, ":/frame.png"), mGrid(window, Vector2i(1, 3)), mMultiLine(multiLine) +{ + addChild(&mBackground); + addChild(&mGrid); + + mTitle = std::make_shared(mWindow, strToUpper(title), Font::get(FONT_SIZE_MEDIUM), 0x777777FF, true); + + mText = std::make_shared(mWindow); + mText->setValue(initValue); + + std::vector< std::shared_ptr > buttons; + buttons.push_back(std::make_shared(mWindow, acceptBtnText, acceptBtnText, [this, okCallback] { okCallback(mText->getValue()); delete this; })); + buttons.push_back(std::make_shared(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, true); + mGrid.setEntry(mButtonGrid, Vector2i(0, 2), true, false); + + float textHeight = mText->getFont()->getHeight(); + if(multiLine) + textHeight *= 3; + + setSize(Renderer::getScreenWidth() * 0.5f, mTitle->getFont()->getHeight() + textHeight + mButtonGrid->getSize().y()); + setPosition((Renderer::getScreenWidth() - mSize.x()) / 2, (Renderer::getScreenHeight() - mSize.y()) / 2); +} + +void GuiTextEditPopup::onSizeChanged() +{ + mBackground.fitTo(mSize, Eigen::Vector3f::Zero(), Eigen::Vector2f(-32, -32)); + + // update grid + mGrid.setRowHeightPerc(0, mTitle->getFont()->getHeight() / mSize.y()); + mGrid.setRowHeightPerc(2, mButtonGrid->getSize().y() / mSize.y()); + mGrid.setSize(mSize); +} + +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; + } + + return false; +} \ No newline at end of file diff --git a/src/guis/GuiTextEditPopup.h b/src/guis/GuiTextEditPopup.h new file mode 100644 index 000000000..b891efb4f --- /dev/null +++ b/src/guis/GuiTextEditPopup.h @@ -0,0 +1,27 @@ +#include "../GuiComponent.h" + +#include "../components/NinePatchComponent.h" +#include "../components/ButtonComponent.h" +#include "../components/ComponentGrid.h" +#include "../components/TextEditComponent.h" +#include "../components/TextComponent.h" + +class GuiTextEditPopup : public GuiComponent +{ +public: + GuiTextEditPopup(Window* window, const std::string& title, const std::string& initValue, + const std::function& okCallback, bool multiLine, const char* acceptBtnText = "OK"); + + bool input(InputConfig* config, Input input); + void onSizeChanged(); + +private: + NinePatchComponent mBackground; + ComponentGrid mGrid; + + std::shared_ptr mTitle; + std::shared_ptr mText; + std::shared_ptr mButtonGrid; + + bool mMultiLine; +};