mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2024-11-22 06:05:38 +00:00
Theme applicators have become the virtual method
GuiComponent::applyTheme(theme, view, element, properties). Applying fonts works now.
This commit is contained in:
parent
8bc33ce309
commit
e6d0da998b
|
@ -233,7 +233,6 @@ 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/ThemeData_applicators.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/VolumeControl.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/Window.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/XMLReader.cpp
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
#include "Log.h"
|
||||
#include "Renderer.h"
|
||||
#include "animations/AnimationController.h"
|
||||
#include "ThemeData.h"
|
||||
|
||||
GuiComponent::GuiComponent(Window* window) : mWindow(window), mParent(NULL), mOpacity(255),
|
||||
mPosition(Eigen::Vector3f::Zero()), mSize(Eigen::Vector2f::Zero()), mTransform(Eigen::Affine3f::Identity())
|
||||
|
@ -225,3 +226,20 @@ void GuiComponent::stopAnimation(unsigned char slot)
|
|||
mAnimationMap[slot] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void GuiComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||
{
|
||||
Eigen::Vector2f scale = getParent() ? getParent()->getSize() : Eigen::Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "");
|
||||
|
||||
using namespace ThemeFlags;
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
{
|
||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||
setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||
}
|
||||
|
||||
if(properties & ThemeFlags::SIZE && elem->has("size"))
|
||||
setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
class Window;
|
||||
class Animation;
|
||||
class AnimationController;
|
||||
class ThemeData;
|
||||
|
||||
class GuiComponent
|
||||
{
|
||||
|
@ -66,6 +67,10 @@ public:
|
|||
virtual void onFocusGained() {};
|
||||
virtual void onFocusLost() {};
|
||||
|
||||
// Default implementation just handles <pos> and <size> tags as normalized float pairs.
|
||||
// You probably want to keep this behavior for any derived classes as well as add your own.
|
||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties);
|
||||
|
||||
protected:
|
||||
void renderChildren(const Eigen::Affine3f& transform) const;
|
||||
|
||||
|
|
|
@ -209,6 +209,7 @@ void ThemeData::parseElement(const pugi::xml_node& root, const std::map<std::str
|
|||
ThemeException error;
|
||||
error.setFiles(mPaths);
|
||||
|
||||
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())
|
||||
|
@ -272,4 +273,51 @@ 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
|
||||
{
|
||||
auto viewIt = mViews.find(view);
|
||||
if(viewIt == mViews.end())
|
||||
{
|
||||
// also check common if the view never existed to begin with
|
||||
viewIt = mViews.find("common");
|
||||
if(viewIt == mViews.end())
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auto elemIt = viewIt->second.elements.find(element);
|
||||
if(elemIt == viewIt->second.elements.end()) return NULL;
|
||||
|
||||
if(elemIt->second.type != expectedType && !expectedType.empty())
|
||||
{
|
||||
LOG(LogWarning) << " requested mismatched theme type for [" << view << "." << element << "] - expected \""
|
||||
<< expectedType << "\", got \"" << elemIt->second.type << "\"";
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return &elemIt->second;
|
||||
}
|
||||
|
||||
void ThemeData::playSound(const std::string& elementName)
|
||||
{
|
||||
const ThemeElement* elem = getElement("common", elementName, "sound");
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
if(elem->has("path"))
|
||||
{
|
||||
const std::string path = elem->get<std::string>("path");
|
||||
auto cacheIt = mSoundCache.find(path);
|
||||
if(cacheIt != mSoundCache.end())
|
||||
{
|
||||
cacheIt->second->play();
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<Sound> sound = std::shared_ptr<Sound>(new Sound(path));
|
||||
sound->play();
|
||||
mSoundCache[path] = sound;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,7 +69,7 @@ ThemeException& operator<<(ThemeException& e, T appendMsg)
|
|||
|
||||
class ThemeData
|
||||
{
|
||||
private:
|
||||
public:
|
||||
|
||||
class ThemeElement
|
||||
{
|
||||
|
@ -80,11 +80,12 @@ private:
|
|||
std::map< std::string, boost::variant<Eigen::Vector2f, std::string, unsigned int, float, bool> > properties;
|
||||
|
||||
template<typename T>
|
||||
T get(const std::string& prop) { return boost::get<T>(properties.at(prop)); }
|
||||
T get(const std::string& prop) const { return boost::get<T>(properties.at(prop)); }
|
||||
|
||||
inline bool has(const std::string& prop) { return (properties.find(prop) != properties.end()); }
|
||||
inline bool has(const std::string& prop) const { return (properties.find(prop) != properties.end()); }
|
||||
};
|
||||
|
||||
private:
|
||||
class ThemeView
|
||||
{
|
||||
private:
|
||||
|
@ -119,17 +120,10 @@ public:
|
|||
|
||||
void renderExtras(const std::string& view, Window* window, const Eigen::Affine3f& transform);
|
||||
|
||||
void applyToImage(const std::string& view, const std::string& element, ImageComponent* image, unsigned int properties);
|
||||
void applyToNinePatch(const std::string& view, const std::string& element, NinePatchComponent* patch, unsigned int properties);
|
||||
void applyToText(const std::string& view, const std::string& element, TextComponent* text, unsigned int properties);
|
||||
|
||||
template <typename T>
|
||||
void applyToTextList(const std::string& view, const std::string& element, TextListComponent<T>* list, unsigned int properties);
|
||||
|
||||
void playSound(const std::string& name);
|
||||
|
||||
private:
|
||||
void applyPosAndSize(ThemeElement* elem, GuiComponent* comp, unsigned int properties);
|
||||
// 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;
|
||||
|
||||
private:
|
||||
static std::map< std::string, std::map<std::string, ElementPropertyType> > sElementMap;
|
||||
|
@ -142,16 +136,24 @@ private:
|
|||
void parseView(const pugi::xml_node& viewNode, ThemeView& view);
|
||||
void parseElement(const pugi::xml_node& elementNode, const std::map<std::string, ElementPropertyType>& typeMap, ThemeElement& element);
|
||||
|
||||
ThemeElement* getElement(const std::string& viewName, const std::string& elementName);
|
||||
|
||||
std::map<std::string, ThemeView> mViews;
|
||||
|
||||
std::map< std::string, std::shared_ptr<Sound> > mSoundCache;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
void ThemeData::applyToTextList(const std::string& view, const std::string& element, TextListComponent<T>* list, unsigned int properties)
|
||||
{
|
||||
|
||||
}
|
||||
// okay ideas for applying themes to GuiComponents:
|
||||
// 1. ThemeData::applyToImage(component, args)
|
||||
// NO, BECAUSE:
|
||||
// - for templated types (TextListComponent) have to include the whole template in a header
|
||||
// - inconsistent definitions if mixing templated types (some in a .cpp, some in a .h/.inl)
|
||||
// 2. template<typename T> ThemeData::apply(component, args) with specialized templates
|
||||
// NO, BECAUSE:
|
||||
// - doesn't solve the first drawback
|
||||
// - can't customize arguments for specific types
|
||||
// 3. GuiComponent::applyTheme(theme, args) - WINNER
|
||||
// NO, BECAUSE:
|
||||
// - can't access private members of ThemeData
|
||||
// - can't this be solved with enough getters?
|
||||
// - theme->hasElement and theme->getProperty will require 2x as many map lookups (4 vs 2)
|
||||
// - why not just return a const ThemeElement...
|
|
@ -1,146 +0,0 @@
|
|||
#include "ThemeData.h"
|
||||
|
||||
#include "Renderer.h"
|
||||
#include "components/ImageComponent.h"
|
||||
#include "components/NinePatchComponent.h"
|
||||
#include "components/TextComponent.h"
|
||||
#include "Sound.h"
|
||||
#include "Log.h"
|
||||
|
||||
using namespace ThemeFlags;
|
||||
|
||||
|
||||
Eigen::Vector2f getScale(GuiComponent* comp)
|
||||
{
|
||||
if(comp && comp->getParent())
|
||||
return comp->getParent()->getSize();
|
||||
|
||||
return Eigen::Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
}
|
||||
|
||||
void ThemeData::applyPosAndSize(ThemeElement* elem, GuiComponent* comp, unsigned int properties)
|
||||
{
|
||||
Eigen::Vector2f scale = getScale(comp);
|
||||
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
{
|
||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||
comp->setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||
}
|
||||
|
||||
if(properties & ThemeFlags::SIZE && elem->has("size"))
|
||||
comp->setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
|
||||
}
|
||||
|
||||
ThemeData::ThemeElement* ThemeData::getElement(const std::string& viewName, const std::string& elementName)
|
||||
{
|
||||
auto viewIt = mViews.find(viewName);
|
||||
if(viewIt == mViews.end())
|
||||
return NULL;
|
||||
|
||||
auto elemIt = viewIt->second.elements.find(elementName);
|
||||
if(elemIt == viewIt->second.elements.end())
|
||||
return NULL;
|
||||
|
||||
return &elemIt->second;
|
||||
}
|
||||
|
||||
void ThemeData::applyToImage(const std::string& viewName, const std::string& elementName, ImageComponent* image, unsigned int properties)
|
||||
{
|
||||
LOG(LogInfo) << " req image [" << viewName << "." << elementName << "] (flags: " << properties << ")";
|
||||
|
||||
ThemeElement* elem = getElement(viewName, elementName);
|
||||
if(!elem)
|
||||
{
|
||||
LOG(LogInfo) << " (missing)";
|
||||
return;
|
||||
}
|
||||
|
||||
Eigen::Vector2f scale = getScale(image);
|
||||
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
{
|
||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||
image->setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||
}
|
||||
|
||||
if(properties & ThemeFlags::SIZE && elem->has("size"))
|
||||
image->setResize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale), true);
|
||||
|
||||
if(properties & ORIGIN && elem->has("origin"))
|
||||
image->setOrigin(elem->get<Eigen::Vector2f>("origin"));
|
||||
|
||||
if(properties & PATH && elem->has("path"))
|
||||
image->setImage(elem->get<std::string>("path"));
|
||||
|
||||
if(properties & TILING && elem->has("tile"))
|
||||
image->setTiling(elem->get<bool>("tile"));
|
||||
}
|
||||
|
||||
void ThemeData::applyToNinePatch(const std::string& viewName, const std::string& elementName, NinePatchComponent* patch, unsigned int properties)
|
||||
{
|
||||
ThemeElement* elem = getElement(viewName, elementName);
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
Eigen::Vector2f scale = getScale(patch);
|
||||
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
{
|
||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||
patch->setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||
}
|
||||
|
||||
applyPosAndSize(elem, patch, properties);
|
||||
}
|
||||
|
||||
void ThemeData::applyToText(const std::string& viewName, const std::string& elementName, TextComponent* text, unsigned int properties)
|
||||
{
|
||||
ThemeElement* elem = getElement(viewName, elementName);
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
Eigen::Vector2f scale = getScale(text);
|
||||
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
{
|
||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||
text->setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||
}
|
||||
|
||||
if(properties & ThemeFlags::SIZE && elem->has("size"))
|
||||
text->setSize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale));
|
||||
|
||||
if(properties & COLOR && elem->has("color"))
|
||||
text->setColor(elem->get<unsigned int>("color"));
|
||||
|
||||
if(properties & CENTER && elem->has("center"))
|
||||
text->setCentered(elem->get<bool>("center"));
|
||||
|
||||
if(properties & TEXT && elem->has("text"))
|
||||
text->setText(elem->get<std::string>("text"));
|
||||
|
||||
// TODO - fonts
|
||||
}
|
||||
|
||||
void ThemeData::playSound(const std::string& elementName)
|
||||
{
|
||||
ThemeElement* elem = getElement("common", elementName);
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
if(elem->has("path"))
|
||||
{
|
||||
const std::string path = elem->get<std::string>("path");
|
||||
auto cacheIt = mSoundCache.find(path);
|
||||
if(cacheIt != mSoundCache.end())
|
||||
{
|
||||
cacheIt->second->play();
|
||||
return;
|
||||
}
|
||||
|
||||
std::shared_ptr<Sound> sound = std::shared_ptr<Sound>(new Sound(path));
|
||||
sound->play();
|
||||
mSoundCache[path] = sound;
|
||||
}
|
||||
}
|
|
@ -14,20 +14,20 @@ GuiFastSelect::GuiFastSelect(Window* window, IGameListView* gamelist) : GuiCompo
|
|||
const std::shared_ptr<ThemeData>& theme = mGameList->getTheme();
|
||||
using namespace ThemeFlags;
|
||||
|
||||
theme->applyToNinePatch("fastSelect", "background", &mBackground, PATH);
|
||||
mBackground.applyTheme(theme, "fastSelect", "background", PATH);
|
||||
mBackground.fitTo(mSize);
|
||||
addChild(&mBackground);
|
||||
|
||||
mLetterText.setSize(mSize.x(), mSize.y() * 0.75f);
|
||||
mLetterText.setCentered(true);
|
||||
theme->applyToText("fastSelect", "letter", &mLetterText, FONT_PATH | COLOR);
|
||||
mLetterText.applyTheme(theme, "fastSelect", "letter", FONT_PATH | COLOR);
|
||||
// TODO - set font size
|
||||
addChild(&mLetterText);
|
||||
|
||||
mSortText.setPosition(0, mSize.y() * 0.75f);
|
||||
mSortText.setSize(mSize.x(), mSize.y() * 0.25f);
|
||||
mSortText.setCentered(true);
|
||||
theme->applyToText("fastSelect", "subtext", &mSortText, FONT_PATH | COLOR);
|
||||
mSortText.applyTheme(theme, "fastSelect", "subtext", FONT_PATH | COLOR);
|
||||
// TODO - set font size
|
||||
addChild(&mSortText);
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ GuiMenu::GuiMenu(Window* window) : GuiComponent(window), mBackground(window, ":/
|
|||
|
||||
mTheme = std::make_shared<ThemeData>();
|
||||
using namespace ThemeFlags;
|
||||
mTheme->applyToTextList< std::function<void()> >("common", "menu", &mList, FONT_PATH | COLOR);
|
||||
mList.applyTheme(mTheme, "common", "menu", FONT_PATH | COLOR);
|
||||
mList.setSelectorColor(0xBBBBBBFF);
|
||||
mList.setColor(0, 0x0000FFFF);
|
||||
mList.setColor(1, 0xFF0000FF);
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <math.h>
|
||||
#include "../Log.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../ThemeData.h"
|
||||
|
||||
Eigen::Vector2i ImageComponent::getTextureSize() const
|
||||
{
|
||||
|
@ -243,3 +244,37 @@ void ImageComponent::copyScreen()
|
|||
|
||||
resize();
|
||||
}
|
||||
|
||||
void ImageComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||
{
|
||||
LOG(LogInfo) << " req image [" << view << "." << element << "] (flags: " << properties << ")";
|
||||
|
||||
using namespace ThemeFlags;
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "image");
|
||||
if(!elem)
|
||||
{
|
||||
LOG(LogInfo) << " (missing)";
|
||||
return;
|
||||
}
|
||||
|
||||
Eigen::Vector2f scale = getParent() ? getParent()->getSize() : Eigen::Vector2f((float)Renderer::getScreenWidth(), (float)Renderer::getScreenHeight());
|
||||
|
||||
if(properties & POSITION && elem->has("pos"))
|
||||
{
|
||||
Eigen::Vector2f denormalized = elem->get<Eigen::Vector2f>("pos").cwiseProduct(scale);
|
||||
setPosition(Eigen::Vector3f(denormalized.x(), denormalized.y(), 0));
|
||||
}
|
||||
|
||||
if(properties & ThemeFlags::SIZE && elem->has("size"))
|
||||
setResize(elem->get<Eigen::Vector2f>("size").cwiseProduct(scale), true);
|
||||
|
||||
if(properties & ORIGIN && elem->has("origin"))
|
||||
setOrigin(elem->get<Eigen::Vector2f>("origin"));
|
||||
|
||||
if(properties & PATH && elem->has("path"))
|
||||
setImage(elem->get<std::string>("path"));
|
||||
|
||||
if(properties & TILING && elem->has("tile"))
|
||||
setTiling(elem->get<bool>("tile"));
|
||||
}
|
||||
|
|
|
@ -41,6 +41,8 @@ public:
|
|||
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
|
||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
||||
|
||||
private:
|
||||
Eigen::Vector2f mTargetSize;
|
||||
Eigen::Vector2f mOrigin;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "../Window.h"
|
||||
#include "../Log.h"
|
||||
#include "../Renderer.h"
|
||||
#include "../ThemeData.h"
|
||||
|
||||
NinePatchComponent::NinePatchComponent(Window* window, const std::string& path, unsigned int edgeColor, unsigned int centerColor) : GuiComponent(window),
|
||||
mEdgeColor(edgeColor), mCenterColor(centerColor),
|
||||
|
@ -193,3 +194,17 @@ void NinePatchComponent::setCenterColor(unsigned int centerColor)
|
|||
mCenterColor = centerColor;
|
||||
updateColors();
|
||||
}
|
||||
|
||||
void NinePatchComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||
{
|
||||
GuiComponent::applyTheme(theme, view, element, properties);
|
||||
|
||||
using namespace ThemeFlags;
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "ninepatch");
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
if(properties & PATH && elem->has("path"))
|
||||
setImagePath(elem->get<std::string>("path"));
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@ public:
|
|||
void setEdgeColor(unsigned int edgeColor);
|
||||
void setCenterColor(unsigned int centerColor);
|
||||
|
||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
||||
|
||||
private:
|
||||
Eigen::Vector2f getCornerSize() const;
|
||||
|
||||
|
|
|
@ -138,3 +138,25 @@ std::string TextComponent::getValue() const
|
|||
{
|
||||
return mText;
|
||||
}
|
||||
|
||||
void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||
{
|
||||
GuiComponent::applyTheme(theme, view, element, properties);
|
||||
|
||||
using namespace ThemeFlags;
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "text");
|
||||
if(!elem)
|
||||
return;
|
||||
|
||||
if(properties & COLOR && elem->has("color"))
|
||||
setColor(elem->get<unsigned int>("color"));
|
||||
|
||||
if(properties & CENTER && elem->has("center"))
|
||||
setCentered(elem->get<bool>("center"));
|
||||
|
||||
if(properties & TEXT && elem->has("text"))
|
||||
setText(elem->get<std::string>("text"));
|
||||
|
||||
setFont(Font::getFromTheme(elem, properties, mFont));
|
||||
}
|
||||
|
|
|
@ -28,6 +28,8 @@ public:
|
|||
|
||||
std::shared_ptr<Font> getFont() const;
|
||||
|
||||
virtual void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
||||
|
||||
private:
|
||||
void calculateExtent();
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ public:
|
|||
bool input(InputConfig* config, Input input) override;
|
||||
void update(int deltaTime) override;
|
||||
void render(const Eigen::Affine3f& parentTrans) override;
|
||||
void applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties) override;
|
||||
|
||||
struct ListRow
|
||||
{
|
||||
|
@ -405,4 +406,27 @@ void TextListComponent<T>::onCursorChanged(CursorState state)
|
|||
mCursorChangedCallback(state);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, const std::string& view, const std::string& element, unsigned int properties)
|
||||
{
|
||||
GuiComponent::applyTheme(theme, view, element, properties);
|
||||
|
||||
const ThemeData::ThemeElement* elem = theme->getElement(view, element, "textlist");
|
||||
|
||||
using namespace ThemeFlags;
|
||||
if(properties & COLOR)
|
||||
{
|
||||
if(elem->has("selectorColor"))
|
||||
setSelectorColor(elem->get<unsigned int>("selectorColor"));
|
||||
if(elem->has("selectedColor"))
|
||||
setSelectedColor(elem->get<unsigned int>("selectedColor"));
|
||||
if(elem->has("primaryColor"))
|
||||
setColor(0, elem->get<unsigned int>("primaryColor"));
|
||||
if(elem->has("secondaryColor"))
|
||||
setColor(1, elem->get<unsigned int>("secondaryColor"));
|
||||
}
|
||||
|
||||
setFont(Font::getFromTheme(elem, properties, mFont));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -553,3 +553,22 @@ void TextCache::setColor(unsigned int color)
|
|||
{
|
||||
Renderer::buildGLColorArray(const_cast<GLubyte*>(colors), color, vertCount);
|
||||
}
|
||||
|
||||
std::shared_ptr<Font> Font::getFromTheme(const ThemeData::ThemeElement* elem, unsigned int properties, const std::shared_ptr<Font>& orig)
|
||||
{
|
||||
using namespace ThemeFlags;
|
||||
if(!(properties & FONT_PATH) && !(properties & FONT_SIZE))
|
||||
return orig;
|
||||
|
||||
std::shared_ptr<Font> font;
|
||||
int size = (orig ? orig->mSize : FONT_SIZE_MEDIUM);
|
||||
std::string path = (orig ? orig->mPath : getDefaultPath());
|
||||
|
||||
float sh = (float)Renderer::getScreenHeight();
|
||||
if(properties & FONT_SIZE && elem->has("fontSize"))
|
||||
size = (int)(sh * elem->get<float>("fontSize"));
|
||||
if(properties & FONT_PATH && elem->has("fontPath"))
|
||||
path = elem->get<std::string>("fontPath");
|
||||
|
||||
return get(size, path);
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
#include FT_FREETYPE_H
|
||||
#include <Eigen/Dense>
|
||||
#include "ResourceManager.h"
|
||||
#include "../ThemeData.h"
|
||||
|
||||
class TextCache;
|
||||
|
||||
|
@ -69,6 +70,9 @@ public:
|
|||
int getSize() const;
|
||||
|
||||
static std::string getDefaultPath();
|
||||
|
||||
static std::shared_ptr<Font> getFromTheme(const ThemeData::ThemeElement* elem, unsigned int properties, const std::shared_ptr<Font>& orig);
|
||||
|
||||
private:
|
||||
static int getDpiX();
|
||||
static int getDpiY();
|
||||
|
|
|
@ -38,7 +38,7 @@ void SystemView::updateData()
|
|||
using namespace ThemeFlags;
|
||||
|
||||
mHeaderImage.setImage("");
|
||||
mSystem->getTheme()->applyToImage("common", "header", &mHeaderImage, PATH);
|
||||
mHeaderImage.applyTheme(mSystem->getTheme(), "system", "header", PATH);
|
||||
|
||||
// header
|
||||
if(mHeaderImage.hasImage())
|
||||
|
@ -51,7 +51,7 @@ void SystemView::updateData()
|
|||
mHeaderText.setText(mSystem->getFullName());
|
||||
}
|
||||
|
||||
mSystem->getTheme()->applyToImage("common", "system", &mImage, PATH);
|
||||
mImage.applyTheme(mSystem->getTheme(), "system", "system", PATH);
|
||||
}
|
||||
|
||||
bool SystemView::input(InputConfig* config, Input input)
|
||||
|
|
|
@ -19,7 +19,7 @@ void BasicGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
|||
{
|
||||
ISimpleGameListView::onThemeChanged(theme);
|
||||
using namespace ThemeFlags;
|
||||
theme->applyToTextList(getName(), "gamelist", &mList, POSITION | ThemeFlags::SIZE | COLOR | SOUND);
|
||||
mList.applyTheme(theme, getName(), "gamelist", POSITION | ThemeFlags::SIZE | COLOR | SOUND | FONT_PATH | FONT_SIZE);
|
||||
}
|
||||
|
||||
void BasicGameListView::onFileChanged(FileData* file, FileChangeType change)
|
||||
|
|
|
@ -26,6 +26,7 @@ DetailedGameListView::DetailedGameListView(Window* window, FileData* root) :
|
|||
mDescContainer.setAutoScroll((int)(1600 + mDescContainer.getSize().x()), 0.025f);
|
||||
addChild(&mDescContainer);
|
||||
|
||||
mDescription.setFont(Font::get(FONT_SIZE_SMALL));
|
||||
mDescription.setSize(mDescContainer.getSize().x(), 0);
|
||||
mDescContainer.addChild(&mDescription);
|
||||
|
||||
|
@ -41,7 +42,7 @@ void DetailedGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& them
|
|||
mHeaderImage.setResize(0, mSize.y() * 0.185f, true);
|
||||
|
||||
using namespace ThemeFlags;
|
||||
theme->applyToText("detailed", "description", &mDescription, POSITION | FONT_PATH | FONT_SIZE);
|
||||
mDescription.applyTheme(theme, getName(), "description", POSITION | FONT_PATH | FONT_SIZE | COLOR);
|
||||
}
|
||||
|
||||
void DetailedGameListView::updateInfoPanel()
|
||||
|
|
|
@ -24,9 +24,9 @@ ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGame
|
|||
void ISimpleGameListView::onThemeChanged(const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
using namespace ThemeFlags;
|
||||
theme->applyToImage(getName(), "background", &mBackground, PATH | TILING);
|
||||
theme->applyToImage(getName(), "header", &mHeaderImage, PATH);
|
||||
|
||||
mBackground.applyTheme(theme, getName(), "background", PATH | TILING);
|
||||
mHeaderImage.applyTheme(theme, getName(), "header", PATH);
|
||||
|
||||
if(mHeaderImage.hasImage())
|
||||
{
|
||||
removeChild(&mHeaderText);
|
||||
|
|
Loading…
Reference in a new issue