00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "global.hpp"
00018
00019 #include "widgets/menu.hpp"
00020
00021 #include "language.hpp"
00022 #include "font.hpp"
00023 #include "image.hpp"
00024 #include "marked-up_text.hpp"
00025 #include "sdl_utils.hpp"
00026 #include "SDL.h"
00027 #include "SDL_image.h"
00028 #include "util.hpp"
00029 #include "video.hpp"
00030 #include "wml_separators.hpp"
00031 #include "serialization/string_utils.hpp"
00032
00033 #include <algorithm>
00034 #include <cassert>
00035 #include <numeric>
00036
00037 namespace gui {
00038
00039
00040 menu::imgsel_style menu::bluebg_style("misc/selection2", true,
00041 0x000000, 0x000000, 0x333333,
00042 0.35, 0.0, 0.3);
00043 menu::style menu::simple_style;
00044
00045 #ifdef USE_TINY_GUI
00046 menu::style &menu::default_style = menu::simple_style;
00047 #else
00048 menu::style &menu::default_style = menu::bluebg_style;
00049 #endif
00050 menu *empty_menu = NULL;
00051
00052
00053 menu::style::style() : font_size_(font::SIZE_NORMAL),
00054 cell_padding_(font::SIZE_NORMAL * 3/5), thickness_(0),
00055 normal_rgb_(0x000000), selected_rgb_(0x000099), heading_rgb_(0x333333),
00056 normal_alpha_(0.2), selected_alpha_(0.6), heading_alpha_(0.3),
00057 max_img_w_(-1), max_img_h_(-1)
00058 {}
00059
00060 menu::style::~style()
00061 {}
00062 menu::imgsel_style::imgsel_style(const std::string &img_base, bool has_bg,
00063 int normal_rgb, int selected_rgb, int heading_rgb,
00064 double normal_alpha, double selected_alpha, double heading_alpha)
00065 : img_base_(img_base), has_background_(has_bg), initialized_(false), load_failed_(false),
00066 normal_rgb2_(normal_rgb), selected_rgb2_(selected_rgb), heading_rgb2_(heading_rgb),
00067 normal_alpha2_(normal_alpha), selected_alpha2_(selected_alpha), heading_alpha2_(heading_alpha)
00068 {}
00069 menu::imgsel_style::~imgsel_style()
00070 {}
00071
00072 size_t menu::style::get_font_size() const { return font_size_; }
00073 size_t menu::style::get_cell_padding() const { return cell_padding_; }
00074 size_t menu::style::get_thickness() const { return thickness_; }
00075
00076 void menu::style::scale_images(int max_width, int max_height)
00077 {
00078 max_img_w_ = max_width;
00079 max_img_h_ = max_height;
00080 }
00081
00082 surface menu::style::get_item_image(const image::locator& img_loc) const
00083 {
00084 surface surf = image::get_image(img_loc);
00085 if(!surf.null())
00086 {
00087 int scale = 100;
00088 if(max_img_w_ > 0 && surf->w > max_img_w_) {
00089 scale = (max_img_w_ * 100) / surf->w;
00090 }
00091 if(max_img_h_ > 0 && surf->h > max_img_h_) {
00092 scale = minimum<int>(scale, ((max_img_h_ * 100) / surf->h));
00093 }
00094 if(scale != 100)
00095 {
00096 return scale_surface(surf, (scale * surf->w)/100, (scale * surf->h)/100);
00097 }
00098 }
00099 return surf;
00100 }
00101
00102 bool menu::imgsel_style::load_image(const std::string &img_sub)
00103 {
00104 std::string path = img_base_ + "-" + img_sub + ".png";
00105 const surface image = image::get_image(path);
00106 img_map_[img_sub] = image;
00107 return(!image.null());
00108 }
00109
00110 bool menu::imgsel_style::load_images()
00111 {
00112 if(!initialized_)
00113 {
00114
00115 if( load_image("border-botleft")
00116 && load_image("border-botright")
00117 && load_image("border-topleft")
00118 && load_image("border-topright")
00119 && load_image("border-left")
00120 && load_image("border-right")
00121 && load_image("border-top")
00122 && load_image("border-bottom") )
00123 {
00124 thickness_ = minimum(
00125 img_map_["border-top"]->h,
00126 img_map_["border-left"]->w);
00127
00128 if(has_background_ && !load_image("background"))
00129 {
00130 load_failed_ = true;
00131 }
00132 else
00133 {
00134 normal_rgb_ = normal_rgb2_;
00135 normal_alpha_ = normal_alpha2_;
00136 selected_rgb_ = selected_rgb2_;
00137 selected_alpha_ = selected_alpha2_;
00138 heading_rgb_ = heading_rgb2_;
00139 heading_alpha_ = heading_alpha2_;
00140
00141 load_failed_ = false;
00142 }
00143 initialized_ = true;
00144 }
00145 else
00146 {
00147 thickness_ = 0;
00148 initialized_ = true;
00149 load_failed_ = true;
00150 }
00151 }
00152 return (!load_failed_);
00153 }
00154
00155 void menu::imgsel_style::draw_row_bg(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type)
00156 {
00157 if(type == SELECTED_ROW && has_background_ && !load_failed_) {
00158 if(bg_cache_.width != rect.w || bg_cache_.height != rect.h)
00159 {
00160
00161
00162 bg_cache_.surf = scale_surface(img_map_["background"], rect.w, rect.h);
00163 bg_cache_.width = rect.w;
00164 bg_cache_.height = rect.h;
00165 }
00166 SDL_Rect clip = rect;
00167 menu_ref.video().blit_surface(rect.x,rect.y,bg_cache_.surf,NULL,&clip);
00168 }
00169 else {
00170 style::draw_row_bg(menu_ref, row_index, rect, type);
00171 }
00172 }
00173
00174 void menu::imgsel_style::draw_row(menu& menu_ref, const size_t row_index, const SDL_Rect& rect, ROW_TYPE type)
00175 {
00176 if(!load_failed_) {
00177
00178 style::draw_row(menu_ref, row_index, rect, type);
00179
00180 if(type == SELECTED_ROW) {
00181
00182 surface image;
00183 SDL_Rect area;
00184 SDL_Rect clip = rect;
00185 area.x = rect.x;
00186 area.y = rect.y;
00187
00188 image = img_map_["border-top"];
00189 area.x = rect.x;
00190 area.y = rect.y;
00191 do {
00192 menu_ref.video().blit_surface(area.x,area.y,image,NULL,&clip);
00193 area.x += image->w;
00194 } while( area.x < rect.x + rect.w );
00195
00196 image = img_map_["border-left"];
00197 area.x = rect.x;
00198 area.y = rect.y;
00199 do {
00200 menu_ref.video().blit_surface(area.x,area.y,image,NULL,&clip);
00201 area.y += image->h;
00202 } while( area.y < rect.y + rect.h );
00203
00204 image = img_map_["border-right"];
00205 area.x = rect.x + rect.w - thickness_;
00206 area.y = rect.y;
00207 do {
00208 menu_ref.video().blit_surface(area.x,area.y,image,NULL,&clip);
00209 area.y += image->h;
00210 } while( area.y < rect.y + rect.h );
00211
00212 image = img_map_["border-bottom"];
00213 area.x = rect.x;
00214 area.y = rect.y + rect.h - thickness_;
00215 do {
00216 menu_ref.video().blit_surface(area.x,area.y,image,NULL,&clip);
00217 area.x += image->w;
00218 } while( area.x < rect.x + rect.w );
00219
00220 image = img_map_["border-topleft"];
00221 area.x = rect.x;
00222 area.y = rect.y;
00223 menu_ref.video().blit_surface(area.x,area.y,image);
00224
00225 image = img_map_["border-topright"];
00226 area.x = rect.x + rect.w - image->w;
00227 area.y = rect.y;
00228 menu_ref.video().blit_surface(area.x,area.y,image);
00229
00230 image = img_map_["border-botleft"];
00231 area.x = rect.x;
00232 area.y = rect.y + rect.h - image->h;
00233 menu_ref.video().blit_surface(area.x,area.y,image);
00234
00235 image = img_map_["border-botright"];
00236 area.x = rect.x + rect.w - image->w;
00237 area.y = rect.y + rect.h - image->h;
00238 menu_ref.video().blit_surface(area.x,area.y,image);
00239 }
00240 } else {
00241
00242 style::draw_row(menu_ref, row_index, rect, type);
00243 }
00244 }
00245
00246 SDL_Rect menu::imgsel_style::item_size(const std::string& item) const
00247 {
00248 SDL_Rect bounds = style::item_size(item);
00249
00250 bounds.w += 2 * thickness_;
00251 bounds.h += 2 * thickness_;
00252
00253 return bounds;
00254 }
00255
00256
00257 }