15 #define GETTEXT_DOMAIN "wesnoth-lib"
50 alpha_sort_.insert(column);
56 numeric_sort_.insert(column);
62 xp_sort_.insert(column);
68 level_sort_.insert(level_column);
75 id_sort_.insert(column);
82 redirect_sort_.insert(std::pair<int,int>(column,to));
96 const std::map<int,int>::const_iterator redirect = redirect_sort_.find(column);
97 if(redirect != redirect_sort_.end()) {
98 return column_sortable(redirect->second);
101 return alpha_sort_.count(column) == 1 || numeric_sort_.count(column) == 1 ||
102 pos_sort_.count(column) == 1 || id_sort_.count(column) == 1 ||
103 xp_sort_.count(column) == 1 || level_sort_.count(column) == 1;
108 std::vector<std::string> parts =
utils::split(s,
'/', 0);
110 int num = lexical_cast_default<int>(parts[0], 0);
111 int denom = lexical_cast_default<int>(parts[1], 0);
112 return std::make_pair(num, denom);
119 if(xp_frac.second == 0)
120 xp_frac.second = 1000000;
122 return xp_frac.second - xp_frac.first;
127 const std::map<int,int>::const_iterator redirect = redirect_sort_.find(column);
128 if(redirect != redirect_sort_.end()) {
129 return less(redirect->second,row1,row2);
132 if(id_sort_.count(column) == 1) {
133 return row1.
id < row2.
id;
140 if(column >=
int(row1.
fields.size())) {
147 if(alpha_sort_.count(column) == 1) {
148 std::string::const_iterator begin1 = item1.begin(), end1 = item1.end(),
149 begin2 = item2.begin(), end2 = item2.end();
159 }
else if(numeric_sort_.count(column) == 1) {
160 int val_1 = lexical_cast_default<int>(item1, 0);
161 int val_2 = lexical_cast_default<int>(item2, 0);
163 return val_1 > val_2;
164 }
else if(xp_sort_.count(column) == 1) {
166 }
else if(level_sort_.count(column) == 1) {
167 int level_1 = lexical_cast_default<int>(item1, 0);
168 int level_2 = lexical_cast_default<int>(item2, 0);
169 if (level_1 == level_2) {
175 return level_1 > level_2;
178 const std::map<int,std::vector<int> >::const_iterator
itor = pos_sort_.find(column);
179 if(itor != pos_sort_.end()) {
180 const std::vector<int>&
pos = itor->second;
181 if(row1.
id >= pos.size()) {
185 if(row2.
id >= pos.size()) {
189 return pos[row1.
id] < pos[row2.
id];
196 bool click_selects,
int max_height,
int max_width,
197 const sorter* sorter_obj,
style *menu_style,
const bool auto_join)
222 for(std::vector<std::string>::const_iterator
itor = items.begin();
230 const size_t id =
items_.size();
233 items_.push_back(new_item);
236 if(
items_.back().fields.empty()) {
237 items_.back().fields.push_back(
" ");
243 if(first_item.empty() ==
false && first_item[0] ==
DEFAULT_ITEM) {
245 first_item.erase(first_item.begin());
265 bool operator()(
const menu::item&
a,
const menu::item&
b)
const
267 return pred_->less(column_,a,b);
271 const menu::sorter* pred_;
291 if(selectid >= 0 && selectid <
int(
item_pos_.size())) {
300 size_t sz =
items_.size();
302 for(
size_t i = 0;
i != sz; ++
i)
309 size_t sz =
items_.size();
311 for(
size_t n = 0;
n != sz; ++
n) {
322 i->help.push_back(
"");
325 if(items.size() >= 2) {
327 i->help.push_back(items.back());
329 i->help.push_back(
"");
349 h = std::max(h,
height());
356 int w = std::accumulate(widths.begin(), widths.end(), 0);
359 w = std::max(w,
width());
397 if(pos1 < 0 || pos1 >=
int(
item_pos_.size()) ||
408 size_t nb_items =
items_.size();
409 if (index >= nb_items)
419 for(
size_t i = 0;
i != nb_items; ++
i) {
422 if (n2 > index) --n2;
458 if (!keep_viewport ||
selected_ >= items.size()) {
465 }
else if(scrolled_to_max) {
501 std::vector<int> heights;
503 for(n = 0; n !=
items_.size(); ++
n) {
507 std::sort(heights.begin(),heights.end(),std::greater<int>());
509 for(n = 0; n !=
items_.size() && sum < max_height; ++
n) {
513 if(sum > max_height && n > 1)
528 if (new_selected >=
items_.size())
531 bool changed =
false;
541 if(!
silent_ && !silent && changed) {
554 size_t nb_items =
items_.size();
626 if(event ==
nullptr) {
631 if(event->type == SDL_KEYDOWN) {
632 SDLKey key =
event->key.keysym.sym;
660 if(event.type == SDL_KEYDOWN) {
664 }
else if(!
mouse_locked() && ((event.type == SDL_MOUSEBUTTONDOWN &&
665 (event.button.button == SDL_BUTTON_LEFT || event.button.button == SDL_BUTTON_RIGHT)) ||
670 if(event.type == SDL_MOUSEBUTTONDOWN) {
674 x =
reinterpret_cast<size_t>(
event.user.data1);
675 y =
reinterpret_cast<size_t>(
event.user.data2);
702 SDL_PeepEvents(&ev, 1, SDL_PEEKEVENT,
718 }
else if(!
mouse_locked() && event.type == SDL_MOUSEMOTION) {
720 const int item =
hit(event.motion.x,event.motion.y);
721 const bool out = (item == -1);
731 const int heading_item =
hit_heading(event.motion.x,event.motion.y);
785 const bool already_sorted = (column ==
sortby_);
805 SDL_Rect
res = {0,0,0,0};
807 for (std::vector<std::string>::const_iterator it = img_text_items.begin();
808 it != img_text_items.end(); ++it) {
809 if (res.w > 0 || res.h > 0) {
816 const std::string image_name(str.begin()+1,str.end());
819 res.w += img.width();
820 res.h = std::max<int>(img.height(), res.h);
825 const std::string image_name(str.begin()+1,str.end());
829 res.h = std::max<int>(img->h, res.h);
834 const SDL_Rect area = {0,0,10000,10000};
837 res.w += font_size.w;
838 res.h = std::max<int>(font_size.h, res.h);
854 alpha = normal_alpha_;
858 alpha = selected_alpha_;
862 alpha = heading_alpha_;
868 (rgb&0xff0000) >> 16,(rgb&0xff00) >> 8,rgb&0xff,alpha,
871 (rgb&0xff00) >> 8, rgb&0xff,
alpha);
874 (rgb&0xff0000) >> 16,(rgb&0xff00) >> 8,rgb&0xff,alpha,
881 if(rect.w == 0 || rect.h == 0) {
884 draw_row_bg(menu_ref, row_index, rect, type);
886 SDL_Rect minirect = rect;
893 menu_ref.
draw_row(row_index, minirect, type);
900 for(
size_t col = 0; col != row.size(); ++col) {
904 if(col == widths.size()) {
905 widths.push_back(res.w + text_trailing_space);
906 }
else if(static_cast<size_t>(res.w) > widths[col] - text_trailing_space) {
907 widths[col] = res.w + text_trailing_space;
915 pos = (pos == std::string::npos) ? 0 : pos+1;
916 return(item.size() > pos && item.at(pos) ==
IMAGE_PREFIX);
947 int dir = (lang_rtl) ? -1 : 1;
953 for(
size_t i = 0;
i != row.size(); ++
i) {
967 const int last_x = xpos;
968 column.w = widths[
i];
971 for (std::vector<std::string>::const_iterator it = img_text_items.begin();
972 it != img_text_items.end(); ++it) {
975 const std::string image_name(str.begin()+1,str.end());
977 const int remaining_width =
max_width_ < 0 ? area.w :
978 std::min<int>(
max_width_, ((lang_rtl)? xpos - rect.x : rect.x + rect.w - xpos));
979 if(!img.null() && img.width() <= remaining_width
980 && rect.y + img.height() < area.h) {
981 const size_t y = rect.y + (rect.h - img.height())/2;
982 const size_t w = img.width() + 5;
983 const size_t x = xpos + ((lang_rtl) ? widths[
i] - w : 0);
984 video().draw_texture(img, x, y);
991 const bool has_wrap = (str.find_first_of(
"\r\n") != std::string::npos);
997 int style = TTF_STYLE_NORMAL;
999 std::string::const_iterator i_beg = to_show.begin(), i_end = to_show.end(),
1003 to_show.erase(
i - i_beg, i_end - i_beg);
1008 const size_t y = rect.y + (rect.h - text_size.h)/2;
1009 const size_t padding = 2;
1011 video().draw_texture(text_img, (type ==
HEADING_ROW ? xpos+padding : xpos), y);
1013 sdl::timage sort_img = image::get_texture(
"buttons/sliders/slider_arrow_blue.png");
1015 if(!sort_img.null() && sort_img.width() <= widths[
i] && sort_img.height() <= rect.h) {
1016 const size_t sort_x = xpos + widths[
i] - sort_img.width() - padding;
1017 const size_t sort_y = rect.y + rect.h/2 - sort_img.height()/2;
1018 video().draw_texture(sort_img, sort_x, sort_y);
1021 xpos += dir * (text_size.w + 5);
1027 xpos = last_x + widths[
i];
1037 const int last_x = xpos;
1041 for (std::vector<std::string>::const_iterator it = img_text_items.begin();
1042 it != img_text_items.end(); ++it) {
1045 const std::string image_name(str.begin()+1,str.end());
1047 const int remaining_width =
max_width_ < 0 ? area.w :
1048 std::min<int>(
max_width_, ((lang_rtl)? xpos - rect.x : rect.x + rect.w - xpos));
1049 if(img !=
nullptr && img->w <= remaining_width
1050 && rect.y + img->h < area.h) {
1051 const size_t y = rect.y + (rect.h - img->h)/2;
1052 const size_t w = img->w + 5;
1053 const size_t x = xpos + ((lang_rtl) ? widths[
i] - w : 0);
1061 const bool has_wrap = (str.find_first_of(
"\r\n") != std::string::npos);
1067 int style = TTF_STYLE_NORMAL;
1069 std::string::const_iterator i_beg = to_show.begin(), i_end = to_show.end(),
1073 to_show.erase(
i - i_beg, i_end - i_beg);
1078 const size_t y = rect.y + (rect.h - text_size.h)/2;
1079 const size_t padding = 2;
1085 "buttons/sliders/slider_arrow_blue.png~ROTATE(180)");
1086 if(sort_img !=
nullptr && sort_img->w <= widths[
i] && sort_img->h <= rect.h) {
1087 const size_t sort_x = xpos + widths[
i] - sort_img->w - padding;
1088 const size_t sort_y = rect.y + rect.h/2 - sort_img->h/2;
1093 xpos += dir * (text_size.w + 5);
1099 xpos = last_x + widths[
i];
1131 }
else if(*
i >= 0 && *
i <
int(
item_pos_.size())) {
1162 for(
size_t i = 0;
i !=
items_.size(); ++
i) {
1164 if (y >= rect.y && y < rect.y + rect.h)
1175 int j = -1, j_end = widths.size();
1176 for(x -=
location().x; x >= 0; x -= widths[j]) {
1186 const int row =
hit(x, y);
1188 return std::pair<int,int>(-1, -1);
1193 return std::pair<int,int>(-1, -1);
1196 return std::pair<int,int>(
x,
y);
1203 if(y >= loc.y && static_cast<size_t>(y) < loc.y + height) {
1218 if (item < first_item_on_screen ||
1223 const std::map<int,SDL_Rect>::const_iterator
i =
itemRects_.find(item);
1230 if (item != first_item_on_screen) {
1232 y = prev.y + prev.h;
1239 if(res.x > screen_area.w) {
1241 }
else if(res.x + res.w > screen_area.w) {
1242 res.w = screen_area.w - res.x;
1245 if(res.y > screen_area.h) {
1247 }
else if(res.y + res.h > screen_area.h) {
1248 res.h = screen_area.h - res.y;
1253 if (loc.x > 0 && loc.y > 0)
1254 itemRects_.insert(std::pair<int,SDL_Rect>(item,res));
1262 for(std::vector<std::string>::const_iterator
i = item.begin();
i != item.end(); ++
i) {
1264 res = std::max<int>(rect.h,
res);
1284 size_t max_height = 0;
1285 for(
size_t n = 0;
n !=
items_.size(); ++
n) {
1296 const std::pair<int,int> loc(
hit(mousex,mousey),
hit_column(mousex));
1299 }
else if(loc.first == -1) {
1307 if(
size_t(loc.first) <
items_.size()) {
1309 if(
size_t(loc.second) < row.size()) {
1311 if(help.empty() ==
false) {
1324 if(
id >=
items_.size()) {
1333 if(pos >=
items_.size()) {
SDL_Rect text_area(const std::string &text, int size, int style)
Calculate the size of a text (in pixels) if it were to be drawn.
surface get_image(const image::locator &i_locator, TYPE type)
function to get the surface corresponding to an image.
char const IMG_TEXT_SEPARATOR
static std::pair< int, int > parse_fraction(const std::string &s)
void fill_rect(surface &dst, SDL_Rect *dst_rect, const Uint32 color)
Fill a rectangle on a given surface.
GLuint GLuint GLsizei GLenum type
const SDL_Rect empty_rect
REMOVE_EMPTY : remove empty elements.
const std::string menu_select
GLint GLint GLint GLint GLint GLint y
const std::vector< std::string > items
void blit_surface(int x, int y, surface surf, SDL_Rect *srcrect=nullptr, SDL_Rect *clip_rect=nullptr)
const SDL_Color NORMAL_COLOR
static int xp_to_advance(const std::string &s)
unsigned thickness_
The thickness of the line.
GLdouble GLdouble GLdouble b
bool chars_less_insensitive(char a, char b)
char const HELP_STRING_SEPARATOR
void draw_solid_tinted_rectangle(int x, int y, int w, int h, int r, int g, int b, double alpha, surface target)
Fills a specified rectangle area of a surface with a given color and opacity.
bool current_language_rtl()
GLubyte GLubyte GLubyte GLubyte w
GLsizei const GLfloat * value
GLboolean GLboolean GLboolean GLboolean a
GLclampf GLclampf GLclampf alpha
typedef int(WINAPI *PFNWGLRELEASEPBUFFERDCARBPROC)(HPBUFFERARB hPbuffer
std::string::const_iterator parse_markup(std::string::const_iterator i1, std::string::const_iterator i2, int *font_size, SDL_Color *color, int *style)
Parses the markup-tags at the front of a string.
GLenum GLenum GLvoid GLvoid * column
SDL_Rect draw_text(surface &dst, const SDL_Rect &area, int size, const SDL_Color &color, const std::string &txt, int x, int y, bool use_tooltips, int style)
Function to draw text on a surface.
std::vector< std::string > quoted_split(std::string const &val, char c, int flags, char quote)
This function is identical to split(), except it does not split when it otherwise would if the previo...
#define DOUBLE_CLICK_EVENT
bool is_wml_separator(char c)
std::map< std::string, tfilter >::iterator itor
GLfloat GLfloat GLfloat GLfloat h
GLint GLint GLint GLint GLint x
static int sort(lua_State *L)
GLint GLint GLint GLint GLint GLint GLsizei GLsizei height
int set_help_string(const std::string &str)
std::string make_text_ellipsis(const std::string &text, int font_size, int max_width, int style)
If the text exceeds the specified max width, end it with an ellipsis (...)
const std::string button_press
SDL_Rect create_rect(const int x, const int y, const int w, const int h)
Creates an empty SDL_Rect.
#define SDL_EVENTMASK(EVENT)
GLenum GLenum GLvoid * row
char const HEADING_PREFIX
Contains the SDL_Rect helper code.
char const COLUMN_SEPARATOR
std::string del_tags(const std::string &text)
Copy string, but without tags at the beginning.
bool find(E event, F functor)
Tests whether an event handler is available.
void play_UI_sound(const std::string &files)
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.
void update_rect(const SDL_Rect &)
GLsizei const GLcharARB ** string
void clear_help_string(int handle)