30 #define DBG_DP LOG_STREAM(debug, log_display)
31 #define LOG_DP LOG_STREAM(info, log_display)
32 #define ERR_DP LOG_STREAM(err, log_display)
35 const int XDim = 1024;
39 const Uint32 DefaultFontRGB = 0x00C8C8C8;
41 _rect ref_rect = { 0, 0, 0, 0 };
48 expr = expr.substr(1);
49 }
else if ((expr[0] ==
'+') || (expr[0] ==
'-')) {
53 return ref + atoi(expr.c_str());
58 _rect rect = { 0, 0, 0, 0 };
61 rect.
x1 = atoi(items[0].c_str());
64 rect.
y1 = atoi(items[1].c_str());
67 rect.
x2 = atoi(items[2].c_str());
72 rect.
y2 = atoi(items[3].c_str());
84 sdlrect.w = (rect.
x2 > rect.
x1) ? (rect.
x2 - rect.
x1) : 0;
85 sdlrect.h = (rect.
y2 > rect.
y1) ? (rect.
y2 - rect.
y1) : 0;
91 _rect rect = { 0, 0, 0, 0 };
92 std::stringstream resolved;
94 if(items.size() >= 1) {
95 rect.
x1 =
compute(items[0], ref_rect.x1, ref_rect.x2);
98 if(items.size() >= 2) {
99 rect.
y1 =
compute(items[1], ref_rect.y1, ref_rect.y2);
100 resolved <<
"," << rect.
y1;
102 if(items.size() >= 3) {
104 resolved <<
"," << rect.
x2;
106 if(items.size() >= 4) {
108 resolved <<
"," << rect.
y2;
114 return resolved.str();
119 static config empty_config;
125 if (
i->cfg[
"id"] ==
id) {
136 if (&c != &empty_config) {
183 "[partialresolution] refers to non-existent [resolution] " +
id);
206 for(
const auto& part : theme.
child_range(
"partialresolution")) {
210 for(
const auto&
remove : part.child_range(
"remove")) {
213 "[theme][partialresolution][remove]"
216 find_ref(
remove[
"id"], resolution,
true);
219 for(
const auto& change : part.child_range(
"change")) {
222 "[theme][partialresolution][change]"
230 for(
const auto& add : part.child_range(
"add")) {
231 for(
const auto& child : add.all_children_range()) {
232 resolution.
add_child(child.key, child.cfg);
236 result.
add_child(
"resolution", resolution);
248 value.key ==
"resolution" ? &childcfg : resol_cfg);
255 if (!cfg[
"ref"].empty()) {
256 if (resol_cfg ==
nullptr) {
257 ERR_DP <<
"Use of ref= outside a [resolution] block" << std::endl;
262 if (ref[
"id"].empty()) {
263 ERR_DP <<
"Reference to non-existent rect id \"" << cfg[
"ref"] <<
"\"" << std::endl;
264 }
else if (ref[
"rect"].empty()) {
265 ERR_DP <<
"Reference to id \"" << cfg[
"ref"] <<
266 "\" which does not have a \"rect\"\n";
273 if (!cfg[
"rect"].empty()) {
279 location_modified_(false),
292 xanchor_(read_anchor(cfg[
"xanchor"])), yanchor_(read_anchor(cfg[
"yanchor"]))
300 corner_image_top_left(),
301 corner_image_bottom_left(),
302 corner_image_top_right_odd(),
303 corner_image_top_right_even(),
304 corner_image_bottom_right_odd(),
305 corner_image_bottom_right_even(),
307 border_image_right(),
308 border_image_top_odd(),
309 border_image_top_even(),
310 border_image_bottom_odd(),
311 border_image_bottom_even()
316 size(cfg[
"border_size"].to_double()),
318 background_image(cfg[
"background_image"]),
319 tile_image(cfg[
"tile_image"]),
321 corner_image_top_left(cfg[
"corner_image_top_left"]),
322 corner_image_bottom_left(cfg[
"corner_image_bottom_left"]),
324 corner_image_top_right_odd(cfg[
"corner_image_top_right_odd"]),
325 corner_image_top_right_even(cfg[
"corner_image_top_right_even"]),
327 corner_image_bottom_right_odd(cfg[
"corner_image_bottom_right_odd"]),
328 corner_image_bottom_right_even(cfg[
"corner_image_bottom_right_even"]),
330 border_image_left(cfg[
"border_image_left"]),
331 border_image_right(cfg[
"border_image_right"]),
333 border_image_top_odd(cfg[
"border_image_top_odd"]),
334 border_image_top_even(cfg[
"border_image_top_even"]),
336 border_image_bottom_odd(cfg[
"border_image_bottom_odd"]),
337 border_image_bottom_even(cfg[
"border_image_bottom_even"])
339 VALIDATE(
size >= 0.0 &&
size <= 0.5,
_(
"border_size should be between 0.0 and 0.5."));
344 if(last_screen_ == screen && !location_modified_)
345 return relative_loc_;
351 relative_loc_.x =
loc_.
x;
352 relative_loc_.w =
loc_.w;
356 relative_loc_.w = screen.w - std::min<size_t>(XDim -
loc_.w,screen.w);
358 case BOTTOM_ANCHORED:
359 relative_loc_.x = screen.w - std::min<size_t>(XDim -
loc_.
x,screen.w);
360 relative_loc_.w =
loc_.w;
363 relative_loc_.
x = (
loc_.
x*screen.w)/XDim;
364 relative_loc_.w = (
loc_.w*screen.w)/XDim;
372 relative_loc_.y =
loc_.
y;
373 relative_loc_.h =
loc_.h;
377 relative_loc_.h = screen.h - std::min<size_t>(YDim -
loc_.h,screen.h);
379 case BOTTOM_ANCHORED:
380 relative_loc_.y = screen.h - std::min<size_t>(YDim -
loc_.
y,screen.h);
381 relative_loc_.h =
loc_.h;
384 relative_loc_.
y = (
loc_.
y*screen.h)/YDim;
385 relative_loc_.h = (
loc_.h*screen.h)/YDim;
391 relative_loc_.x = std::min<int>(relative_loc_.x,screen.w);
392 relative_loc_.w = std::min<int>(relative_loc_.w,screen.w - relative_loc_.x);
393 relative_loc_.y = std::min<int>(relative_loc_.y,screen.h);
394 relative_loc_.h = std::min<int>(relative_loc_.h,screen.h - relative_loc_.y);
396 return relative_loc_;
401 static const std::string top_anchor =
"top", left_anchor =
"left",
402 bot_anchor =
"bottom", right_anchor =
"right",
403 proportional_anchor =
"proportional";
404 if(str == top_anchor || str == left_anchor)
406 else if(str == bot_anchor || str == right_anchor)
407 return BOTTOM_ANCHORED;
408 else if(str == proportional_anchor)
419 location_modified_ =
true;
423 _rect rect = { 0, 0, 0, 0 };
425 if(items.size() >= 1) {
426 rect.
x1 =
compute(items[0], ref_rect.x, ref_rect.x + ref_rect.w);
428 if(items.size() >= 2) {
429 rect.
y1 =
compute(items[1], ref_rect.y, ref_rect.y + ref_rect.h);
431 if(items.size() >= 3) {
432 rect.
x2 =
compute(items[2], ref_rect.x + ref_rect.w, rect.
x1);
434 if(items.size() >= 4) {
435 rect.
y2 =
compute(items[3], ref_rect.y + ref_rect.h, rect.
y1);
437 modify_location(rect);
444 font_rgb_set_(false),
445 font_rgb_(DefaultFontRGB)
450 text_(cfg[
"prefix"].str() + cfg[
"text"].str() + cfg[
"postfix"].str()),
452 font_(cfg[
"font_size"]),
453 font_rgb_set_(false),
454 font_rgb_(DefaultFontRGB)
457 font_ = DefaultFontSize;
461 std::vector<std::string> rgb_vec =
utils::split(cfg[
"font_rgb"]);
462 if (3 <= rgb_vec.size()) {
465 r = (atoi(c->c_str()));
467 if (c != rgb_vec.end()) {
468 g = (atoi(c->c_str()));
473 if (c != rgb_vec.end()) {
474 b=(atoi(c->c_str()));
478 font_rgb_ = (((r<<16) & 0x00FF0000) + ((g<<8) & 0x0000FF00) + ((
b) & 0x000000FF));
486 prefix_(cfg[
"prefix"].str() + cfg[
"prefix_literal"].str()),
487 postfix_(cfg[
"postfix_literal"].str() + cfg[
"postfix"].str()),
489 font_(cfg[
"font_size"]),
490 font_rgb_set_(false),
491 font_rgb_(DefaultFontRGB)
494 font_ = DefaultFontSize;
496 if (
const config &label_child = cfg.
child(
"label")) {
502 std::vector<std::string> rgb_vec =
utils::split(cfg[
"font_rgb"]);
503 if(3 <= rgb_vec.size()){
506 r = (atoi(c->c_str()));
508 if(c != rgb_vec.end()){
509 g = (atoi(c->c_str()));
514 if(c != rgb_vec.end()){
515 b=(atoi(c->c_str()));
519 font_rgb_ = (((r<<16) & 0x00FF0000) + ((g<<8) & 0x0000FF00) + ((
b) & 0x000000FF));
538 title_(cfg[
"title"].str() + cfg[
"title_literal"].str()),
539 tooltip_(cfg[
"tooltip"]),
image_(cfg[
"image"]), overlay_(cfg[
"overlay"]),
540 black_line_(cfg[
"black_line"].to_bool(false))
556 button_(cfg[
"button"].to_bool(true)),
557 context_(cfg[
"is_context_menu"].to_bool(false)),
558 title_(cfg[
"title"].str() + cfg[
"title_literal"].str()),
559 tooltip_(cfg[
"tooltip"]),
image_(cfg[
"image"]), overlay_(cfg[
"overlay"]),
562 if (cfg[
"auto_tooltip"].to_bool() &&
tooltip_.empty() &&
items_.size() == 1) {
565 }
else if (cfg[
"tooltip_name_prepend"].to_bool() &&
items_.size() == 1) {
574 auto_tooltip_(false),
575 tooltip_name_prepend_(false),
586 auto_tooltip_(cfg[
"auto_tooltip"].to_bool(false)),
587 tooltip_name_prepend_(cfg[
"tooltip_name_prepend"].to_bool(false)),
588 title_(cfg[
"title"].str() + cfg[
"title_literal"].str()),
589 tooltip_(cfg[
"tooltip"]),
image_(cfg[
"image"]), overlay_(cfg[
"overlay"]), type_(cfg[
"type"]),
596 if (auto_tooltip_ && tooltip_.empty() &&
items_.size() >
index) {
601 }
else if (tooltip_name_prepend_ &&
items_.size() == 1) {
605 result <<
"\n" << tooltip_;
637 int current_rating = 1000000;
638 const config *current =
nullptr;
643 LOG_DP <<
"comparing resolution " << screen.w <<
"," << screen.h <<
" to " << width <<
"," << height <<
"\n";
644 if(screen.w >= width && screen.h >= height) {
645 LOG_DP <<
"loading theme: " << width <<
"," << height <<
"\n";
651 const int rating = width*
height;
652 if(rating < current_rating) {
654 current_rating = rating;
660 ERR_DP <<
"No valid resolution found" << std::endl;
665 std::map<std::string,std::string> title_stash_menus;
668 if (!m->title().empty() && !m->get_id().empty())
669 title_stash_menus[m->get_id()] = m->title();
672 std::map<std::string,std::string> title_stash_actions;
675 if (!a->title().empty() && !a->get_id().empty())
676 title_stash_actions[a->get_id()] = a->title();
689 if (title_stash_menus.find(m->get_id()) != title_stash_menus.end())
690 m->set_title(title_stash_menus[m->get_id()]);
694 if (title_stash_actions.find(a->get_id()) != title_stash_actions.end())
695 a->set_title(title_stash_actions[a->get_id()]);
717 if (
const config &status_cfg = cfg.
child(
"status"))
722 if (
const config &unit_image_cfg = status_cfg.
child(
"unit_image")) {
744 DBG_DP <<
"adding menu: " << (new_menu.
is_context() ?
"is context" :
"not context") <<
"\n";
749 menus_.push_back(new_menu);
752 DBG_DP <<
"done adding menu...\n";
758 DBG_DP <<
"adding action: " << (new_action.
is_context() ?
"is context" :
"not context") <<
"\n";
766 DBG_DP <<
"done adding action...\n";
772 DBG_DP <<
"adding slider\n";
776 DBG_DP <<
"done adding slider...\n";
788 if (
p->get_id() ==
id){
794 if (
l->get_id() ==
id){
800 if (
m->get_id() ==
id){
806 if (
a->get_id() ==
id){
812 if (
s->get_id() ==
id){
821 if (ref_id.empty()) {
822 ref_id = element.
get_id();
827 if (ref_element.
get_id() == ref_id){
835 std::map<std::string,std::string> title_stash;
838 if (!m->title().empty() && !m->get_id().empty())
839 title_stash[m->get_id()] = m->title();
844 if (!a->title().empty() && !a->get_id().empty())
845 title_stash[a->get_id()] = a->title();
869 if (title_stash.find(m->get_id()) != title_stash.end())
870 m->set_title(title_stash[m->get_id()]);
873 if (title_stash.find(a->get_id()) != title_stash.end())
874 a->set_title(title_stash[a->get_id()]);
882 if (
p->get_id() ==
id) { res = &(*p); }
885 if (
l->get_id() ==
id) { res = &(*l); }
888 if (
m->get_id() ==
id) { res = &(*m); }
891 if (
a->get_id() ==
id) { res = &(*a); }
893 if (
id ==
"main-map") { res = &
main_map_; }
894 if (
id ==
"mini-map") { res = &
mini_map_; }
895 if (
id ==
"palette") { res = &
palette_; }
902 const std::map<std::string,status_item>::const_iterator
i =
status_.find(key);
922 if (!thm[
"hidden"].to_bool(
false)) {
930 std::vector<theme_info>
res;
932 for(known_themes_map::const_iterator
i =
known_themes.begin();
937 res.back().id =
i->first;
938 res.back().name =
i->second[
"name"].t_str();
939 res.back().description =
i->second[
"description"].t_str();
948 if (
m.get_id() == key)
return &
m;
956 if (
a.get_id() == key)
return &
a;
966 if (
a->get_id() ==
id) {
968 a->set_title(new_title);
973 if (
m->get_id() ==
id) {
975 m->set_title(new_title);
986 if (! cfg[title_tag].empty())
987 new_title = cfg[title_tag].str();
996 LOG_DP <<
"Theme contains no label called '" <<
id <<
"'.\n";
std::vector< label > labels_
child_itors child_range(const std::string &key)
events::generic_event theme_reset_event_
static lg::log_domain log_display("display")
virtual void notify_observers()
std::vector< action > actions_
static void set_known_themes(const config *cfg)
Add a special kind of assert to validate whether the input from WML doesn't contain any problems that...
const std::string tooltip(size_t index) const
static l_noret error(LoadState *S, const char *why)
const SDL_Rect empty_rect
void remove_object(std::string id)
surface image_
The image is cached in this surface.
std::vector< panel > panels_
static config expand_partialresolution(const config &theme)
Returns a config with all partial resolutions of a theme expanded.
std::vector< slider > sliders_
const std::vector< std::string > items
static void do_resolve_rects(const config &cfg, config &resolved_config, config *resol_cfg=nullptr)
void add_object(const config &cfg)
tformula< t_string > text_
The text to draw.
status_item(const config &cfg)
static std::map< std::string, config > known_themes
SDL_Rect & location(const SDL_Rect &screen) const
std::string missing_mandatory_wml_key(const std::string §ion, const std::string &key, const std::string &primary_key, const std::string &primary_value)
Returns a standard message for a missing wml key.
GLdouble GLdouble GLdouble b
const std::string & get_tooltip(const std::string &command)
static UNUSEDNOWARN std::string _(const char *str)
static config get_resolution(const config &resolutions, const std::string &id)
Returns a copy of the wanted resolution.
#define VALIDATE(cond, message)
The macro to use for the validation of WML.
std::vector< menu > menus_
const status_item * get_status_item(const std::string &item) const
GLsizei const GLfloat * value
all_children_itors all_children_range() const
In-order iteration over all children.
const std::string & get_id() const
GLboolean GLboolean GLboolean GLboolean a
theme(const config &cfg, const SDL_Rect &screen)
std::pair< all_children_iterator, all_children_iterator > all_children_itors
config & add_child(const std::string &key)
std::pair< int, int > resolution()
const menu * get_menu_item(const std::string &key) const
void modify(const config &cfg)
all_children_iterator erase(const all_children_iterator &i)
static _rect read_rect(const config &cfg)
static std::vector< theme_info > get_known_themes()
object * refresh_title(const std::string &id, const std::string &new_title)
static void expr(LexState *ls, expdesc *v)
void modify_label(const std::string &id, const std::string &text)
Definitions related to theme-support.
GLdouble GLdouble GLdouble r
std::string get_names(std::string id)
Returns a comma-separated string of hotkey names.
const action * get_action_item(const std::string &key) const
const std::string & get_description(const std::string &command)
unsigned child_count(const std::string &key) const
void merge_attributes(const config &)
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
bool set_resolution(const SDL_Rect &screen)
void set_text(const std::string &text)
static config & find_ref(const std::string &id, config &cfg, bool remove=false)
Contains the SDL_Rect helper code.
bool has_attribute(const std::string &key) const
static SDL_Rect read_sdl_rect(const config &cfg)
std::map< std::string, config > known_themes_map
config & child(const std::string &key, int n=0)
Returns the nth child with the given key, or a reference to an invalid config if there is none...
object * refresh_title2(const std::string &id, const std::string &title_tag)
Standard logging facilities (interface).
theme::object & find_element(std::string id)
void modify_location(const _rect &rect)
void set_object_location(theme::object &element, std::string rect_str, std::string ref_id)
const SDL_Rect & get_location() const
GLint GLint GLint GLint GLint GLint GLsizei width
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
static size_t compute(std::string expr, size_t ref1, size_t ref2=0)
A config object defines a single node in a WML file, with access to child nodes.
static ANCHORING read_anchor(const std::string &str)
std::map< std::string, status_item > status_
GLsizei const GLcharARB ** string
static std::string resolve_rect(const std::string &rect_str)