1 /* 2 Copyright (C) 2003 - 2018 by David White <dave@whitevine.net> 3 Part of the Battle for Wesnoth Project https://www.wesnoth.org/ 4 5 This program is free software; you can redistribute it and/or modify 6 it under the terms of the GNU General Public License as published by 7 the Free Software Foundation; either version 2 of the License, or 8 (at your option) any later version. 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY. 11 12 See the COPYING file for more details. 13 */ 14 15 /** 16 * @file 17 * Definitions related to theme-support. 18 */ 19 20 #pragma once 21 22 #include "color.hpp" 23 #include "config.hpp" 24 #include "generic_event.hpp" 25 26 #include <memory> 27 #include <SDL2/SDL_rect.h> 28 29 struct _rect { size_t x1,y1,x2,y2; }; 30 31 struct theme_info 32 { 33 std::string id; 34 t_string name; 35 t_string description; 36 }; 37 38 class theme 39 { 40 41 class object 42 { 43 public: 44 object(); 45 object(const config& cfg); ~object()46 virtual ~object() { } 47 48 virtual SDL_Rect& location(const SDL_Rect& screen) const; get_location() const49 const SDL_Rect& get_location() const { return loc_; } get_id() const50 const std::string& get_id() const { return id_; } 51 52 // This supports relocating of theme elements ingame. 53 // It is needed for [change] tags in theme WML. 54 void modify_location(const _rect& rect); 55 void modify_location(std::string rect_str, SDL_Rect rect_ref); 56 57 // All on-screen objects have 'anchoring' in the x and y dimensions. 58 // 'fixed' means that they have fixed co-ordinates and don't move. 59 // 'top anchored' means they are anchored to the top (or left) side 60 // of the screen - the top (or left) edge stays a constant distance 61 // from the top of the screen. 62 // 'bottom anchored' is the inverse of top anchored. 63 // 'proportional' means the location and dimensions change 64 // proportionally to the screen size. 65 enum ANCHORING { FIXED, TOP_ANCHORED, PROPORTIONAL, BOTTOM_ANCHORED }; 66 67 private: 68 bool location_modified_; 69 std::string id_; 70 SDL_Rect loc_; 71 mutable SDL_Rect relative_loc_; 72 mutable SDL_Rect last_screen_; 73 74 ANCHORING xanchor_, yanchor_; 75 76 static ANCHORING read_anchor(const std::string& str); 77 }; 78 79 struct border_t 80 { 81 82 border_t(); 83 border_t(const config& cfg); 84 85 double size; 86 87 std::string background_image; 88 std::string tile_image; 89 90 bool show_border; 91 }; 92 93 public: 94 95 class label : public object 96 { 97 public: 98 label(); 99 explicit label(const config& cfg); 100 101 using object::location; 102 text() const103 const std::string& text() const { return text_; } set_text(const std::string & text)104 void set_text(const std::string& text) { text_ = text; } icon() const105 const std::string& icon() const { return icon_; } 106 empty() const107 bool empty() const { return text_.empty() && icon_.empty(); } 108 font_size() const109 size_t font_size() const { return font_; } font_rgb() const110 color_t font_rgb() const { return font_rgb_; } font_rgb_set() const111 bool font_rgb_set() const { return font_rgb_set_; } 112 private: 113 std::string text_, icon_; 114 size_t font_; 115 bool font_rgb_set_; 116 color_t font_rgb_; 117 }; 118 119 class status_item : public object 120 { 121 public: 122 123 explicit status_item(const config& cfg); 124 125 using object::location; 126 prefix() const127 const std::string& prefix() const { return prefix_; } postfix() const128 const std::string& postfix() const { return postfix_; } 129 130 // If the item has a label associated with it, Show where the label is get_label() const131 const label* get_label() const { return label_.empty() ? nullptr : &label_; } 132 font_size() const133 size_t font_size() const { return font_; } font_rgb() const134 color_t font_rgb() const { return font_rgb_; } font_rgb_set() const135 bool font_rgb_set() const { return font_rgb_set_; } 136 137 private: 138 std::string prefix_, postfix_; 139 label label_; 140 size_t font_; 141 bool font_rgb_set_; 142 color_t font_rgb_; 143 }; 144 145 class panel : public object 146 { 147 public: 148 explicit panel(const config& cfg); 149 150 using object::location; 151 image() const152 const std::string& image() const { return image_; } 153 154 private: 155 std::string image_; 156 }; 157 158 class action : public object 159 { 160 public: 161 action(); 162 explicit action(const config& cfg); 163 164 using object::location; 165 is_context() const166 bool is_context() const { return context_; } 167 title() const168 const std::string& title() const { return title_; } 169 170 const std::string tooltip(size_t index) const; 171 type() const172 const std::string& type() const { return type_; } 173 image() const174 const std::string& image() const { return image_; } 175 overlay() const176 const std::string& overlay() const { return overlay_; } 177 items() const178 const std::vector<std::string>& items() const { return items_; } 179 set_title(const std::string & new_title)180 void set_title(const std::string& new_title) { title_ = new_title; } 181 private: 182 bool context_, auto_tooltip_, tooltip_name_prepend_; 183 std::string title_, tooltip_, image_, overlay_, type_; 184 std::vector<std::string> items_; 185 }; 186 187 class slider : public object 188 { 189 public: 190 slider(); 191 explicit slider(const config& cfg); 192 193 using object::location; 194 title() const195 const std::string& title() const { return title_; } 196 tooltip() const197 const std::string& tooltip() const { return tooltip_; } 198 image() const199 const std::string& image() const { return image_; } 200 overlay() const201 const std::string& overlay() const { return overlay_; } 202 black_line() const203 bool black_line() const { return black_line_; } 204 set_title(const std::string & new_title)205 void set_title(const std::string& new_title) { title_ = new_title; } 206 private: 207 std::string title_, tooltip_, image_, overlay_; 208 bool black_line_; 209 }; 210 211 class menu : public object 212 { 213 public: 214 menu(); 215 explicit menu(const config& cfg); 216 217 using object::location; 218 is_button() const219 bool is_button() const { return button_; } 220 is_context() const221 bool is_context() const { return context_; } 222 title() const223 const std::string& title() const { return title_; } 224 tooltip() const225 const std::string& tooltip() const { return tooltip_; } 226 image() const227 const std::string& image() const { return image_; } 228 overlay() const229 const std::string& overlay() const { return overlay_; } 230 items() const231 const std::vector<config>& items() const { return items_; } 232 set_title(const std::string & new_title)233 void set_title(const std::string& new_title) { title_ = new_title; } 234 private: 235 bool button_; 236 bool context_; 237 std::string title_, tooltip_, image_, overlay_; 238 std::vector<config> items_; 239 }; 240 241 explicit theme(const config& cfg, const SDL_Rect& screen); 242 theme(const theme&) = delete; 243 theme& operator=(const theme&) = delete; 244 theme& operator=(theme&&); 245 246 bool set_resolution(const SDL_Rect& screen); 247 void modify(const config &cfg); 248 panels() const249 const std::vector<panel>& panels() const { return panels_; } labels() const250 const std::vector<label>& labels() const { return labels_; } menus() const251 const std::vector<menu>& menus() const { return menus_; } sliders() const252 const std::vector<slider>& sliders() const { return sliders_; } actions() const253 const std::vector<action>& actions() const { return actions_; } 254 context_menu() const255 const menu* context_menu() const 256 { return context_.is_context() ? &context_ : nullptr; } 257 258 //refresh_title2 changes the title of a menu entry, identified by id. 259 //If no menu entry is found, an empty menu object is returned. 260 object* refresh_title(const std::string& id, const std::string& new_title); 261 object* refresh_title2(const std::string& id, const std::string& title_tag); 262 void modify_label(const std::string& id, const std::string& text); 263 264 const status_item* get_status_item(const std::string& item) const; 265 const menu *get_menu_item(const std::string &key) const; 266 const action* get_action_item(const std::string &key) const; 267 main_map_location(const SDL_Rect & screen) const268 const SDL_Rect& main_map_location(const SDL_Rect& screen) const 269 { return main_map_.location(screen); } mini_map_location(const SDL_Rect & screen) const270 const SDL_Rect& mini_map_location(const SDL_Rect& screen) const 271 { return mini_map_.location(screen); } unit_image_location(const SDL_Rect & screen) const272 const SDL_Rect& unit_image_location(const SDL_Rect& screen) const 273 { return unit_image_.location(screen); } palette_location(const SDL_Rect & screen) const274 const SDL_Rect& palette_location(const SDL_Rect& screen) const 275 { return palette_.location(screen); } 276 277 static void set_known_themes(const config* cfg); 278 static std::vector<theme_info> get_known_themes(); 279 border() const280 const border_t& border() const { return border_; } 281 theme_reset_event()282 events::generic_event& theme_reset_event() { return theme_reset_event_; } 283 284 private: 285 theme::object& find_element(const std::string& id); 286 void add_object(const config& cfg); 287 void remove_object(const std::string& id); 288 void set_object_location(theme::object& element, std::string rect_str, std::string ref_id); 289 290 //notify observers that the theme has been rebuilt completely 291 //atm this is used for replay_controller to add replay controls to the standard theme 292 events::generic_event theme_reset_event_; 293 294 static std::map<std::string, config> known_themes; 295 std::string cur_theme; 296 config cfg_; 297 std::vector<panel> panels_; 298 std::vector<label> labels_; 299 std::vector<menu> menus_; 300 std::vector<action> actions_; 301 std::vector<slider> sliders_; 302 303 menu context_; 304 action action_context_; 305 306 std::map<std::string, std::unique_ptr<status_item>> status_; 307 308 object main_map_, mini_map_, unit_image_, palette_; 309 310 border_t border_; 311 312 SDL_Rect screen_dimensions_; 313 }; 314