mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-21 21:55:38 +00:00
Added support for theme "extras".
Fixed a few crashes (e.g. TextListComponent::applyTheme).
This commit is contained in:
parent
e6d0da998b
commit
8a52866ca6
|
@ -155,6 +155,7 @@ set(ES_HEADERS
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeData.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeDumper.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.h
|
||||
|
@ -233,6 +234,7 @@ set(ES_SOURCES
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/src/Sound.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/SystemData.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeData.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/ThemeDumper.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.cpp
|
||||
|
|
|
@ -232,6 +232,8 @@ void GuiComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std
|
|||
Eigen::Vector2f scale = getParent() ? getParent()->getSize() : Eigen::Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "");
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
using namespace ThemeFlags;
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
|
|
|
@ -7,6 +7,9 @@
|
|||
#include "pugiXML/pugixml.hpp"
|
||||
#include <boost/assign.hpp>
|
||||
|
||||
#include "components/ImageComponent.h"
|
||||
#include "components/TextComponent.h"
|
||||
|
||||
std::map< std::string, std::map<std::string, ThemeData::ElementPropertyType> > ThemeData::sElementMap = boost::assign::map_list_of
|
||||
("image", boost::assign::map_list_of
|
||||
("pos", NORMALIZED_PAIR)
|
||||
|
@ -31,6 +34,9 @@ std::map< std::string, std::map<std::string, ThemeData::ElementPropertyType> > T
|
|||
("secondaryColor", COLOR)
|
||||
("fontPath", PATH)
|
||||
("fontSize", FLOAT))
|
||||
("container", boost::assign::map_list_of
|
||||
("pos", NORMALIZED_PAIR)
|
||||
("size", NORMALIZED_PAIR))
|
||||
("sound", boost::assign::map_list_of
|
||||
("path", PATH));
|
||||
|
||||
|
@ -211,7 +217,7 @@ void ThemeData::parseElement(const pugi::xml_node& root, const std::map<std::str
|
|||
|
||||
element.type = root.name();
|
||||
element.extra = root.attribute("extra").as_bool(false);
|
||||
|
||||
|
||||
for(pugi::xml_node node = root.first_child(); node; node = node.next_sibling())
|
||||
{
|
||||
auto typeIt = typeMap.find(node.name());
|
||||
|
@ -269,12 +275,6 @@ void ThemeData::parseElement(const pugi::xml_node& root, const std::map<std::str
|
|||
}
|
||||
}
|
||||
|
||||
ThemeData::ThemeView::~ThemeView()
|
||||
{
|
||||
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
||||
|
||||
const ThemeData::ThemeElement* ThemeData::getElement(const std::string& view, const std::string& element, const std::string& expectedType) const
|
||||
{
|
||||
|
@ -321,3 +321,48 @@ void ThemeData::playSound(const std::string& elementName)
|
|||
mSoundCache[path] = sound;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<GuiComponent*> ThemeData::makeExtras(const std::shared_ptr<ThemeData>& theme, const std::string& view, Window* window)
|
||||
{
|
||||
std::vector<GuiComponent*> comps;
|
||||
|
||||
auto viewIt = theme->mViews.find(view);
|
||||
if(viewIt == theme->mViews.end())
|
||||
return comps;
|
||||
|
||||
for(auto it = viewIt->second.elements.begin(); it != viewIt->second.elements.end(); it++)
|
||||
{
|
||||
if(it->second.extra)
|
||||
{
|
||||
GuiComponent* comp = NULL;
|
||||
const std::string& t = it->second.type;
|
||||
if(t == "image")
|
||||
comp = new ImageComponent(window);
|
||||
else if(t == "text")
|
||||
comp = new TextComponent(window);
|
||||
|
||||
comp->applyTheme(theme, view, it->first, ThemeFlags::ALL);
|
||||
comps.push_back(comp);
|
||||
}
|
||||
}
|
||||
|
||||
return comps;
|
||||
}
|
||||
|
||||
void ThemeExtras::setExtras(const std::vector<GuiComponent*>& extras)
|
||||
{
|
||||
// delete old extras (if any)
|
||||
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
|
||||
delete *it;
|
||||
|
||||
mExtras = extras;
|
||||
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
|
||||
addChild(*it);
|
||||
}
|
||||
|
||||
ThemeExtras::~ThemeExtras()
|
||||
{
|
||||
for(auto it = mExtras.begin(); it != mExtras.end(); it++)
|
||||
delete *it;
|
||||
}
|
||||
|
|
|
@ -35,7 +35,9 @@ namespace ThemeFlags
|
|||
TILING = 128,
|
||||
SOUND = 256,
|
||||
CENTER = 512,
|
||||
TEXT = 1024
|
||||
TEXT = 1024,
|
||||
|
||||
ALL = 0xFFFFFFFF
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -67,6 +69,20 @@ ThemeException& operator<<(ThemeException& e, T appendMsg)
|
|||
return e;
|
||||
}
|
||||
|
||||
class ThemeExtras : public GuiComponent
|
||||
{
|
||||
public:
|
||||
ThemeExtras(Window* window) : GuiComponent(window) {};
|
||||
|
||||
// will take ownership of the components within extras (delete them in destructor or when setExtras is called again)
|
||||
void setExtras(const std::vector<GuiComponent*>& extras);
|
||||
|
||||
virtual ~ThemeExtras();
|
||||
|
||||
private:
|
||||
std::vector<GuiComponent*> mExtras;
|
||||
};
|
||||
|
||||
class ThemeData
|
||||
{
|
||||
public:
|
||||
|
@ -88,17 +104,8 @@ public:
|
|||
private:
|
||||
class ThemeView
|
||||
{
|
||||
private:
|
||||
bool mExtrasDirty;
|
||||
std::vector<GuiComponent*> mExtras;
|
||||
|
||||
public:
|
||||
ThemeView() : mExtrasDirty(true) {}
|
||||
virtual ~ThemeView();
|
||||
|
||||
std::map<std::string, ThemeElement> elements;
|
||||
|
||||
const std::vector<GuiComponent*>& getExtras(Window* window);
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -125,6 +132,8 @@ public:
|
|||
// If expectedType is an empty string, will do no type checking.
|
||||
const ThemeElement* getElement(const std::string& view, const std::string& element, const std::string& expectedType) const;
|
||||
|
||||
static std::vector<GuiComponent*> makeExtras(const std::shared_ptr<ThemeData>& theme, const std::string& view, Window* window);
|
||||
|
||||
private:
|
||||
static std::map< std::string, std::map<std::string, ElementPropertyType> > sElementMap;
|
||||
|
||||
|
@ -141,7 +150,6 @@ private:
|
|||
std::map< std::string, std::shared_ptr<Sound> > mSoundCache;
|
||||
};
|
||||
|
||||
|
||||
// okay ideas for applying themes to GuiComponents:
|
||||
// 1. ThemeData::applyToImage(component, args)
|
||||
// NO, BECAUSE:
|
||||
|
|
2
src/ThemeDumper.cpp
Normal file
2
src/ThemeDumper.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#include "ThemeDumper.h"
|
||||
|
13
src/ThemeDumper.h
Normal file
13
src/ThemeDumper.h
Normal file
|
@ -0,0 +1,13 @@
|
|||
#pragma once
|
||||
|
||||
#include "ThemeData.h"
|
||||
|
||||
// Should be able to:
|
||||
// 1. Take a list of "tests" to run.
|
||||
// a. Each test works by calling setTheme on a theme with a "fake" theme that records all getElement() access.
|
||||
// 2. Results can be output to a text file, OR compared with a loaded theme to create warnings about potentially unused elements.
|
||||
|
||||
class ThemeDumper
|
||||
{
|
||||
|
||||
};
|
|
@ -35,16 +35,18 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mBackground(window, ":/
|
|||
mList.setPosition(mSize.x() * 0.175f, mSize.y() * 0.05f);
|
||||
mList.setSize(mSize.x() * 0.65f, mSize.y() * 0.9f);
|
||||
|
||||
using namespace ThemeFlags;
|
||||
mBackground.applyTheme(mTheme, "menu", "background", PATH);
|
||||
mBackground.fitTo(Eigen::Vector2f(mList.getSize().x(), mSize.y()), Eigen::Vector3f(mList.getPosition().x(), 0, 0));
|
||||
addChild(&mBackground);
|
||||
|
||||
mTheme = std::make_shared<ThemeData>();
|
||||
using namespace ThemeFlags;
|
||||
mList.applyTheme(mTheme, "common", "menu", FONT_PATH | COLOR);
|
||||
|
||||
mList.setFont(Font::get((int)(0.09f * Renderer::getScreenHeight())));
|
||||
mList.applyTheme(mTheme, "menu", "menulist", FONT_PATH | COLOR);
|
||||
mList.setSelectorColor(0xBBBBBBFF);
|
||||
mList.setColor(0, 0x0000FFFF);
|
||||
mList.setColor(1, 0xFF0000FF);
|
||||
// TODO - set font size to 0.09f
|
||||
|
||||
addChild(&mList);
|
||||
}
|
||||
|
|
|
@ -269,7 +269,8 @@ void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const s
|
|||
if(properties & ThemeFlags::SIZE && elem->has("size"))
|
||||
setResize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale), true);
|
||||
|
||||
if(properties & ORIGIN && elem->has("origin"))
|
||||
// position + size also implies origin
|
||||
if((properties & ORIGIN || (properties & POSITION && properties & ThemeFlags::SIZE)) && elem->has("origin"))
|
||||
setOrigin(elem->get<Eigen::Vector2f>("origin"));
|
||||
|
||||
if(properties & PATH && elem->has("path"))
|
||||
|
|
|
@ -412,6 +412,8 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, c
|
|||
GuiComponent::applyTheme(theme, view, element, properties);
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "textlist");
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
using namespace ThemeFlags;
|
||||
if(properties & COLOR)
|
||||
|
|
|
@ -42,6 +42,8 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& them
|
|||
mHeaderImage.setResize(0, mSize.y() * 0.185f, true);
|
||||
|
||||
using namespace ThemeFlags;
|
||||
mImage.applyTheme(theme, getName(), "gameimage", POSITION | ThemeFlags::SIZE);
|
||||
mDescContainer.applyTheme(theme, getName(), "infoPanel", POSITION | ThemeFlags::SIZE);
|
||||
mDescription.applyTheme(theme, getName(), "description", POSITION | FONT_PATH | FONT_SIZE | COLOR);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
#include "../ViewController.h"
|
||||
|
||||
ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGameListView(window, root),
|
||||
mHeaderText(window), mHeaderImage(window), mBackground(window)
|
||||
mHeaderText(window), mHeaderImage(window), mBackground(window), mThemeExtras(window)
|
||||
{
|
||||
mHeaderText.setText("Header");
|
||||
mHeaderText.setSize(mSize.x(), 0);
|
||||
|
@ -19,14 +19,16 @@ ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGame
|
|||
|
||||
addChild(&mHeaderText);
|
||||
addChild(&mBackground);
|
||||
addChild(&mThemeExtras);
|
||||
}
|
||||
|
||||
void ISimpleGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
using namespace ThemeFlags;
|
||||
mBackground.applyTheme(theme, getName(), "background", PATH | TILING);
|
||||
mHeaderImage.applyTheme(theme, getName(), "header", PATH);
|
||||
|
||||
mHeaderImage.applyTheme(theme, getName(), "header", POSITION | ThemeFlags::SIZE | PATH);
|
||||
mThemeExtras.setExtras(ThemeData::makeExtras(theme, getName(), mWindow));
|
||||
|
||||
if(mHeaderImage.hasImage())
|
||||
{
|
||||
removeChild(&mHeaderText);
|
||||
|
|
|
@ -32,5 +32,7 @@ protected:
|
|||
ImageComponent mHeaderImage;
|
||||
ImageComponent mBackground;
|
||||
|
||||
ThemeExtras mThemeExtras;
|
||||
|
||||
std::stack<FileData*> mCursorStack;
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue