From: Mikko Rasa Date: Mon, 13 Aug 2018 19:32:23 +0000 (+0300) Subject: Initial version from when I last played X-Git-Url: http://git.tdb.fi/?p=poefilter.git;a=commitdiff_plain;h=fc27eb63c05d915d606e17992ecd5b7f68478101 Initial version from when I last played --- fc27eb63c05d915d606e17992ecd5b7f68478101 diff --git a/Build b/Build new file mode 100644 index 0000000..5e575bd --- /dev/null +++ b/Build @@ -0,0 +1,10 @@ +package "poefilter" +{ + require "mspcore"; + require "mspdatafile"; + + program "poefilter" + { + source "source"; + }; +}; diff --git a/source/category.cpp b/source/category.cpp new file mode 100644 index 0000000..2ea4818 --- /dev/null +++ b/source/category.cpp @@ -0,0 +1,151 @@ +#include "category.h" +#include "choicecondition.h" +#include "filter.h" +#include "rangecondition.h" +#include "theme.h" + +using namespace std; +using namespace Msp; + +Category::Category(): + condition(0), + font_size(1.0f), + order(0), + sound_type(0), + sound_volume(100) +{ } + +Category::Category(const Category &other): + condition(other.condition ? other.condition->clone() : 0), + font_size(other.font_size), + border_color(other.border_color), + order(other.order), + sound_type(other.sound_type), + sound_volume(other.sound_volume) +{ } + +Category &Category::operator=(const Category &other) +{ + delete condition; + condition = (other.condition ? other.condition->clone() : 0); + font_size = other.font_size; + border_color = other.border_color; + order = other.order; + sound_type = other.sound_type; + sound_volume = other.sound_volume; + return *this; +} + +Category::~Category() +{ + delete condition; +} + +void Category::create_statements(list &st, const Theme &theme) const +{ + st.clear(); + st.push_back(FilterStatement()); + st.back().add_line(format("SetFontSize %d", static_cast(font_size*theme.get_base_font_size()+0.5))); + if(!border_color.empty()) + { + const Color &color = theme.get_color(border_color); + st.back().add_line(format("SetBorderColor %d %d %d", color.r, color.g, color.b)); + } + if(sound_type) + st.back().add_line(format("PlayAlertSound %d %d", sound_type, sound_volume)); + if(condition) + condition->add_lines(st); +} + + +Category::Loader::Loader(Category &c, CompoundCondition *n): + DataFile::ObjectLoader(c), + compound(n) +{ + add("alert_sound", &Category::sound_type, &Category::sound_volume); + add("and", &Loader::and_); + add("base_type", &Loader::condition); + add("border_color", &Category::border_color); + add("class", &Loader::condition); + add_range("drop_level"); + add("font_size", &Category::font_size); + add_range("height"); + add_range("item_level"); + add("linked_colors", &Loader::linked_colors); + add_range("linked_sockets"); + add_range("sockets"); + add("or", &Loader::or_); + add("order", &Category::order); + add_range("quality"); + add_range("rarity"); + add_range("width"); +} + +template +void Category::Loader::add_range(const string &keyword) +{ + add(keyword, &Loader::condition); + add(keyword, &Loader::condition_range); + add("min_"+keyword, &Loader::condition_min); + add("max_"+keyword, &Loader::condition_max); +} + +void Category::Loader::add_condition(Condition *cond) +{ + if(compound) + compound->add(cond); + else if(!obj.condition) + obj.condition = cond; + else + { + compound = new AndCondition; + compound->add(obj.condition); + compound->add(cond); + obj.condition = compound; + } +} + +void Category::Loader::and_() +{ + RefPtr cond = new AndCondition; + Loader sub_ldr(obj, cond.get()); + load_sub_with(sub_ldr); + add_condition(cond.release()); +} + +template +void Category::Loader::condition(typename T::Type value) +{ + add_condition(new T(value)); +} + +template +void Category::Loader::condition_max(typename T::Type max) +{ + add_condition(new T(T::Traits::get_min(), max)); +} + +template +void Category::Loader::condition_min(typename T::Type min) +{ + add_condition(new T(min, T::Traits::get_max())); +} + +template +void Category::Loader::condition_range(typename T::Type min, typename T::Type max) +{ + add_condition(new T(min, max)); +} + +void Category::Loader::linked_colors(const LinkedColorsCondition::Colors &colors) +{ + add_condition(new LinkedColorsCondition(colors)); +} + +void Category::Loader::or_() +{ + RefPtr cond = new OrCondition; + Loader sub_ldr(obj, cond.get()); + load_sub_with(sub_ldr); + add_condition(cond.release()); +} diff --git a/source/category.h b/source/category.h new file mode 100644 index 0000000..53b1beb --- /dev/null +++ b/source/category.h @@ -0,0 +1,67 @@ +#ifndef CATEGORY_H_ +#define CATEGORY_H_ + +#include +#include +#include +#include "condition.h" +#include "rarity.h" + +class FilterStatement; +class Theme; + +class Category +{ +public: + class Loader: public Msp::DataFile::ObjectLoader + { + private: + CompoundCondition *compound; + + public: + Loader(Category &, CompoundCondition * = 0); + + protected: + template + void add_range(const std::string &); + + void add_condition(Condition *); + + private: + void and_(); + + template + void condition(typename T::Type); + + template + void condition_max(typename T::Type); + + template + void condition_min(typename T::Type); + + template + void condition_range(typename T::Type, typename T::Type); + + void linked_colors(const LinkedColorsCondition::Colors &); + void or_(); + }; + +private: + Condition *condition; + float font_size; + std::string border_color; + unsigned order; + unsigned sound_type; + unsigned sound_volume; + +public: + Category(); + Category(const Category &); + Category &operator=(const Category &); + ~Category(); + + unsigned get_order() const { return order; } + void create_statements(std::list &, const Theme &) const; +}; + +#endif diff --git a/source/choicecondition.h b/source/choicecondition.h new file mode 100644 index 0000000..5a45329 --- /dev/null +++ b/source/choicecondition.h @@ -0,0 +1,81 @@ +#ifndef CHOICECONDITION_H_ +#define CHOICECONDITION_H_ + +#include "condition.h" +#include "filter.h" + +template +class ChoiceCondition: public Condition +{ +public: + typedef T Traits; + typedef typename Traits::Type Type; + +private: + Type value; + +public: + ChoiceCondition(Type); + + virtual Condition *clone() const; + virtual bool can_merge(const Condition &, const CompoundCondition &) const; + virtual void add_lines(std::list &) const; + virtual void add_merged_lines(const std::list &, const CompoundCondition &, std::list &) const; +}; + + +struct ClassTraits +{ + typedef std::string Type; + static const char *get_keyword() { return "Class"; } +}; + +typedef ChoiceCondition ClassCondition; + + +struct BaseTypeTraits +{ + typedef std::string Type; + static const char *get_keyword() { return "BaseType"; } +}; + +typedef ChoiceCondition BaseTypeCondition; + + +template +ChoiceCondition::ChoiceCondition(Type v): + value(v) +{ } + +template +Condition *ChoiceCondition::clone() const +{ + return new ChoiceCondition(value); +} + +template +bool ChoiceCondition::can_merge(const Condition &other, const CompoundCondition &parent) const +{ + return dynamic_cast *>(&other) && dynamic_cast(&parent); +} + +template +void ChoiceCondition::add_lines(std::list &st) const +{ + const char *keyword = Traits::get_keyword(); + FilterStatement::add_line(st, Msp::format("%s \"%s\"", keyword, value)); +} + +template +void ChoiceCondition::add_merged_lines(const std::list &conditions, const CompoundCondition &parent, std::list &st) const +{ + if(dynamic_cast(&parent)) + { + std::string line = Traits::get_keyword(); + for(std::list::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + line += Msp::format(" \"%s\"", static_cast *>(*i)->value); + FilterStatement::add_line(st, line); + } +} + +#endif diff --git a/source/condition.cpp b/source/condition.cpp new file mode 100644 index 0000000..12ee730 --- /dev/null +++ b/source/condition.cpp @@ -0,0 +1,94 @@ +#include "condition.h" +#include "filter.h" + +using namespace std; +using namespace Msp; + +CompoundCondition::~CompoundCondition() +{ + for(list::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + delete *i; +} + +void CompoundCondition::clone_to(CompoundCondition &other) const +{ + for(list::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + other.add((*i)->clone()); +} + +void CompoundCondition::add(Condition *cond) +{ + conditions.push_back(cond); +} + + +Condition *AndCondition::clone() const +{ + AndCondition *result = new AndCondition; + clone_to(*result); + return result; +} + +void AndCondition::add_lines(list &st) const +{ + for(list::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + (*i)->add_lines(st); +} + + +Condition *OrCondition::clone() const +{ + OrCondition *result = new OrCondition; + clone_to(*result); + return result; +} + +void OrCondition::add_lines(list &st) const +{ + bool merge = conditions.size()>1; + for(list::const_iterator i=conditions.begin(); (merge && ++i!=conditions.end()); ) + merge = conditions.front()->can_merge(**i, *this); + + if(merge) + conditions.front()->add_merged_lines(conditions, *this, st); + else + { + list result; + for(list::const_iterator i=conditions.begin(); i!=conditions.end(); ++i) + { + list sub_result = st; + (*i)->add_lines(sub_result); + result.splice(result.end(), sub_result); + } + swap(result, st); + } +} + + +LinkedColorsCondition::LinkedColorsCondition(const Colors &c): + colors(c) +{ } + +Condition *LinkedColorsCondition::clone() const +{ + return new LinkedColorsCondition(colors); +} + +void LinkedColorsCondition::add_lines(list &st) const +{ + FilterStatement::add_line(st, format("SocketGroup %s", colors.colors)); +} + + +void operator>>(const LexicalConverter &conv, LinkedColorsCondition::Colors &colors) +{ + const string &str = conv.get(); + bool rgb = true; + for(string::const_iterator i=str.begin(); (rgb && i!=str.end()); ++i) + rgb = (*i=='R' || *i=='G' || *i=='B'); + if(str.size()>6 || !rgb) + throw lexical_error(format("conversion of '%s' to LinkedColorsCondition::Colors", str)); + + fill(colors.colors, colors.colors+7, '\0'); + copy(str.begin(), str.end(), colors.colors); +} diff --git a/source/condition.h b/source/condition.h new file mode 100644 index 0000000..59976aa --- /dev/null +++ b/source/condition.h @@ -0,0 +1,78 @@ +#ifndef CONDITION_H_ +#define CONDITION_H_ + +#include +#include +#include +#include "rarity.h" + +class CompoundCondition; +class FilterStatement; + +class Condition +{ +protected: + Condition() { } +public: + virtual ~Condition() { } + + virtual Condition *clone() const = 0; + virtual bool can_merge(const Condition &, const CompoundCondition &) const { return false; } + virtual void add_lines(std::list &) const = 0; + virtual void add_merged_lines(const std::list &, const CompoundCondition &, std::list &) const { } +}; + + +class CompoundCondition: public Condition +{ +protected: + std::list conditions; + +public: + virtual ~CompoundCondition(); + +protected: + void clone_to(CompoundCondition &) const; + +public: + void add(Condition *); +}; + + +class AndCondition: public CompoundCondition +{ +public: + virtual Condition *clone() const; + virtual void add_lines(std::list &) const; +}; + + +class OrCondition: public CompoundCondition +{ +public: + virtual Condition *clone() const; + virtual void add_lines(std::list &) const; +}; + + +class LinkedColorsCondition: public Condition +{ +public: + struct Colors + { + char colors[7]; + }; + +private: + Colors colors; + +public: + LinkedColorsCondition(const Colors &); + + virtual Condition *clone() const; + virtual void add_lines(std::list &) const; +}; + +void operator>>(const Msp::LexicalConverter &, LinkedColorsCondition::Colors &); + +#endif diff --git a/source/filter.cpp b/source/filter.cpp new file mode 100644 index 0000000..c694ca6 --- /dev/null +++ b/source/filter.cpp @@ -0,0 +1,138 @@ +#include +#include +#include +#include "category.h" +#include "filter.h" +#include "poefilter.h" + +using namespace std; +using namespace Msp; + +FilterStatement::FilterStatement(): + show(true) +{ } + +void FilterStatement::set_show(bool s) +{ + show = s; +} + +void FilterStatement::add_line(const string &l) +{ + lines.push_back(l); +} + +void FilterStatement::add_line(list &st, const string &line) +{ + for(list::iterator i=st.begin(); i!=st.end(); ++i) + i->add_line(line); +} + +void FilterStatement::write(IO::Base &out) const +{ + if(show) + out.write("Show\n"); + else + out.write("Hide\n"); + + for(list::const_iterator i=lines.begin(); i!=lines.end(); ++i) + IO::print(out, "\t%s\n", *i); +} + + +Filter::Filter(): + abstract(false) +{ } + +void Filter::write(IO::Base &out, const Theme &theme) const +{ + for(list::const_iterator i=categories.begin(); i!=categories.end(); ++i) + { + list st; + //IO::print(out, "# %s\n", i->first); + (*i)->create_statements(st, theme); + for(list::const_iterator j=st.begin(); j!=st.end(); ++j) + j->write(out); + } + + out.write("# unmatched\nHide\n"); +} + + +Filter::Loader::Loader(Filter &f, const PoeFilter &p): + DataFile::ObjectLoader(f), + poe(p) +{ + add("abstract", &Filter::abstract); + add("hide", &Loader::hide); + add("include", &Loader::include); + add("show", &Loader::show); +} + +string Filter::Loader::glob_to_re(const string &glob) +{ + string result = "^"; + for(string::const_iterator i=glob.begin(); i!=glob.end(); ++i) + { + if(*i=='*') + result += '.'; + else if(!isalnum(*i)) + result += '\\'; + result += *i; + } + result += '$'; + + return result; +} + +bool Filter::Loader::category_order(const Category *c1, const Category *c2) +{ + return c1->get_order()get_order(); +} + +void Filter::Loader::hide(const string &name) +{ + list categs; + if(name.find('*')!=string::npos) + { + poe.find_categories(glob_to_re(name), categs); + + if(categs.empty()) + throw key_error(name); + } + else + categs.push_back(&poe.get_category(name)); + + for(list::const_iterator i=categs.begin(); i!=categs.end(); ++i) + { + list::iterator j = find(obj.categories.begin(), obj.categories.end(), *i); + if(j!=obj.categories.end()) + obj.categories.erase(j); + } +} + +void Filter::Loader::include(const string &name) +{ + const Filter &base = poe.get_filter(name); + obj.categories.insert(obj.categories.end(), base.categories.begin(), base.categories.end()); +} + +void Filter::Loader::show(const string &name) +{ + list categs; + if(name.find('*')!=string::npos) + { + poe.find_categories(glob_to_re(name), categs); + + if(categs.empty()) + throw key_error(name); + + categs.sort(&category_order); + } + else + categs.push_back(&poe.get_category(name)); + + for(list::const_iterator i=categs.begin(); i!=categs.end(); ++i) + if(find(obj.categories.begin(), obj.categories.end(), *i)==obj.categories.end()) + obj.categories.push_back(*i); +} diff --git a/source/filter.h b/source/filter.h new file mode 100644 index 0000000..4642943 --- /dev/null +++ b/source/filter.h @@ -0,0 +1,63 @@ +#ifndef FILTER_H_ +#define FILTER_H_ + +#include +#include +#include +#include +#include + +class Category; +class PoeFilter; +class Theme; + +class FilterStatement +{ +private: + bool show; + std::list lines; + +public: + FilterStatement(); + + void set_show(bool); + void add_line(const std::string &); + + static void add_line(std::list &, const std::string &); + + void write(Msp::IO::Base &) const; +}; + + +class Filter +{ +public: + class Loader: public Msp::DataFile::ObjectLoader + { + private: + const PoeFilter &poe; + + public: + Loader(Filter &, const PoeFilter &); + + private: + static std::string glob_to_re(const std::string &); + static bool category_order(const Category *, const Category *); + + void hide(const std::string &); + void include(const std::string &); + void show(const std::string &); + }; + +private: + std::list categories; + bool abstract; + +public: + Filter(); + + bool is_abstract() const { return abstract; } + void write(Msp::IO::Base &, const Theme &) const; +}; + +#endif diff --git a/source/poefilter.cpp b/source/poefilter.cpp new file mode 100644 index 0000000..032b871 --- /dev/null +++ b/source/poefilter.cpp @@ -0,0 +1,75 @@ +#include +#include +#include +#include "category.h" +#include "filter.h" +#include "poefilter.h" + +using namespace std; +using namespace Msp; + +PoeFilter::PoeFilter(int argc, char **argv) +{ + GetOpt getopt; + getopt.add_argument("filename", filename, GetOpt::REQUIRED_ARG); + getopt(argc, argv); +} + +int PoeFilter::main() +{ + DataFile::load(*this, filename); + + for(map::const_iterator i=filters.begin(); i!=filters.end(); ++i) + if(!i->second.is_abstract()) + { + IO::BufferedFile out(i->first+".filter", IO::M_WRITE); + i->second.write(out, theme); + } + + return 0; +} + +const Category &PoeFilter::get_category(const string &name) const +{ + return get_item(categories, name); +} + +void PoeFilter::find_categories(const Regex &re, list &categs) const +{ + for(map::const_iterator i=categories.begin(); i!=categories.end(); ++i) + if(re.match(i->first)) + categs.push_back(&i->second); +} + +const Filter &PoeFilter::get_filter(const string &name) const +{ + return get_item(filters, name); +} + + +PoeFilter::Loader::Loader(PoeFilter &f): + DataFile::ObjectLoader(f) +{ + add("category", &Loader::category); + add("filter", &Loader::filter); + add("theme", &Loader::theme); +} + +void PoeFilter::Loader::category(const string &name) +{ + Category cat; + load_sub(cat); + obj.categories[name] = cat; +} + +void PoeFilter::Loader::filter(const string &name) +{ + Filter flt; + load_sub(flt, obj); + obj.filters[name] = flt; +} + +void PoeFilter::Loader::theme() +{ + load_sub(obj.theme); +} diff --git a/source/poefilter.h b/source/poefilter.h new file mode 100644 index 0000000..0e87d2d --- /dev/null +++ b/source/poefilter.h @@ -0,0 +1,43 @@ +#ifndef POEFILTER_H_ +#define POEFILTER_H_ + +#include +#include +#include +#include +#include "theme.h" + +class Category; +class Filter; + +class PoeFilter: public Msp::RegisteredApplication +{ +public: + class Loader: public Msp::DataFile::ObjectLoader + { + public: + Loader(PoeFilter &); + + private: + void category(const std::string &); + void filter(const std::string &); + void theme(); + }; + +private: + std::string filename; + Theme theme; + std::map categories; + std::map filters; + +public: + PoeFilter(int, char **); + + virtual int main(); + + const Category &get_category(const std::string &) const; + void find_categories(const Msp::Regex &, std::list &) const; + const Filter &get_filter(const std::string &) const; +}; + +#endif diff --git a/source/rangecondition.h b/source/rangecondition.h new file mode 100644 index 0000000..d4cc19a --- /dev/null +++ b/source/rangecondition.h @@ -0,0 +1,148 @@ +#ifndef RANGECONDITION_H_ +#define RANGECONDITION_H_ + +#include "condition.h" +#include "filter.h" + +template +class RangeCondition: public Condition +{ +public: + typedef T Traits; + typedef typename Traits::Type Type; + +protected: + Type min; + Type max; + +public: + RangeCondition(Type); + RangeCondition(Type, Type); + + virtual Condition *clone() const; + virtual void add_lines(std::list &) const; +}; + + +struct RarityTraits +{ + typedef Rarity Type; + static Rarity get_min() { return NORMAL; } + static Rarity get_max() { return UNIQUE; } + static const char *get_keyword() { return "Rarity"; } +}; + +typedef RangeCondition RarityCondition; + + +struct QualityTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 0; } + static unsigned get_max() { return 20; } + static const char *get_keyword() { return "Quality"; } +}; + +typedef RangeCondition QualityCondition; + + +struct ItemLevelTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 0; } + static unsigned get_max() { return 100; } + static const char *get_keyword() { return "ItemLevel"; } +}; + +typedef RangeCondition ItemLevelCondition; + + +struct DropLevelTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 0; } + static unsigned get_max() { return 100; } + static const char *get_keyword() { return "DropLevel"; } +}; + +typedef RangeCondition DropLevelCondition; + + +struct WidthTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 1; } + static unsigned get_max() { return 2; } + static const char *get_keyword() { return "Width"; } +}; + +typedef RangeCondition WidthCondition; + + +struct HeightTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 1; } + static unsigned get_max() { return 4; } + static const char *get_keyword() { return "Height"; } +}; + +typedef RangeCondition HeightCondition; + + +struct SocketsTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 1; } + static unsigned get_max() { return 6; } + static const char *get_keyword() { return "Sockets"; } +}; + +typedef RangeCondition SocketsCondition; + + +struct LinkedSocketsTraits +{ + typedef unsigned Type; + static unsigned get_min() { return 1; } + static unsigned get_max() { return 6; } + static const char *get_keyword() { return "LinkedSockets"; } +}; + +typedef RangeCondition LinkedSocketsCondition; + + +template +RangeCondition::RangeCondition(Type v): + min(v), + max(v) +{ } + +template +RangeCondition::RangeCondition(Type n, Type x): + min(n), + max(x) +{ } + +template +Condition *RangeCondition::clone() const +{ + return new RangeCondition(min, max); +} + +template +void RangeCondition::add_lines(std::list &st) const +{ + const char *keyword = Traits::get_keyword(); + if(min==max) + FilterStatement::add_line(st, Msp::format("%s %s", keyword, min)); + else + { + if(min!=Traits::get_min()) + FilterStatement::add_line(st, Msp::format("%s >= %s", keyword, min)); + if(max!=Traits::get_max()) + FilterStatement::add_line(st, Msp::format("%s <= %s", keyword, max)); + } +} + +#endif diff --git a/source/rarity.cpp b/source/rarity.cpp new file mode 100644 index 0000000..4cfc570 --- /dev/null +++ b/source/rarity.cpp @@ -0,0 +1,32 @@ +#include +#include "rarity.h" + +using namespace std; +using namespace Msp; + +void operator>>(const LexicalConverter &conv, Rarity &rarity) +{ + const string &str = conv.get(); + if(str=="Normal") + rarity = NORMAL; + else if(str=="Magic") + rarity = MAGIC; + else if(str=="Rare") + rarity = RARE; + else if(str=="Unique") + rarity = UNIQUE; + else + throw lexical_error(format("Conversion of %s to Rarity", str)); +} + +void operator<<(LexicalConverter &conv, Rarity rarity) +{ + switch(rarity) + { + case NORMAL: conv.result("Normal"); return; + case MAGIC: conv.result("Magic"); return; + case RARE: conv.result("Rare"); return; + case UNIQUE: conv.result("Unique"); return; + default: conv.result(format("Rarity(%d)", static_cast(rarity))); return; + } +} diff --git a/source/rarity.h b/source/rarity.h new file mode 100644 index 0000000..1a82c9e --- /dev/null +++ b/source/rarity.h @@ -0,0 +1,17 @@ +#ifndef RARITY_H_ +#define RARITY_H_ + +#include + +enum Rarity +{ + NORMAL, + MAGIC, + RARE, + UNIQUE +}; + +void operator>>(const Msp::LexicalConverter &, Rarity &); +void operator<<(Msp::LexicalConverter &, Rarity); + +#endif diff --git a/source/theme.cpp b/source/theme.cpp new file mode 100644 index 0000000..3b09dc3 --- /dev/null +++ b/source/theme.cpp @@ -0,0 +1,50 @@ +#include +#include "theme.h" + +using namespace std; +using namespace Msp; + +Color::Color(): + r(200), + g(200), + b(200) +{ } + +Color::Color(unsigned r_, unsigned g_, unsigned b_): + r(r_), + g(g_), + b(b_) +{ } + + +Theme::Theme(): + base_font_size(32) +{ } + +void Theme::set_color(const string &name, const Color &color) +{ + colors[name] = color; +} + +const Color &Theme::get_color(const string &name) const +{ + return get_item(colors, name); +} + +void Theme::set_base_font_size(unsigned size) +{ + base_font_size = size; +} + + +Theme::Loader::Loader(Theme &t): + DataFile::ObjectLoader(t) +{ + add("base_font_size", &Theme::base_font_size); + add("color", &Loader::color); +} + +void Theme::Loader::color(const string &name, unsigned r, unsigned g, unsigned b) +{ + obj.set_color(name, Color(r, g, b)); +} diff --git a/source/theme.h b/source/theme.h new file mode 100644 index 0000000..7e296ae --- /dev/null +++ b/source/theme.h @@ -0,0 +1,47 @@ +#ifndef THEME_H_ +#define THEME_H_ + +#include +#include +#include + +struct Color +{ + unsigned r; + unsigned g; + unsigned b; + + Color(); + Color(unsigned, unsigned, unsigned); +}; + + +class Theme +{ +public: + class Loader: public Msp::DataFile::ObjectLoader + { + public: + Loader(Theme &); + + private: + void color(const std::string &, unsigned, unsigned, unsigned); + }; + +private: + typedef std::map ColorMap; + + ColorMap colors; + unsigned base_font_size; + +public: + Theme(); + + void set_color(const std::string &, const Color &); + const Color &get_color(const std::string &) const; + + void set_base_font_size(unsigned); + unsigned get_base_font_size() const { return base_font_size; } +}; + +#endif