00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "global.hpp"
00019
00020 #define GETTEXT_DOMAIN "wesnoth-lib"
00021
00022 #include "cursor.hpp"
00023 #include "display.hpp"
00024 #include "game_preferences.hpp"
00025 #include "gettext.hpp"
00026 #include "hotkeys.hpp"
00027 #include "log.hpp"
00028 #include "marked-up_text.hpp"
00029 #include "preferences_display.hpp"
00030 #include "construct_dialog.hpp"
00031 #include "show_dialog.hpp"
00032 #include "video.hpp"
00033 #include "wml_separators.hpp"
00034 #include "widgets/button.hpp"
00035 #include "widgets/label.hpp"
00036 #include "widgets/menu.hpp"
00037 #include "widgets/slider.hpp"
00038 #include "widgets/textbox.hpp"
00039 #include "theme.hpp"
00040
00041 #include <vector>
00042 #include <string>
00043
00044 namespace preferences {
00045
00046 display* disp = NULL;
00047
00048 display_manager::display_manager(display* d)
00049 {
00050 disp = d;
00051
00052 load_hotkeys();
00053
00054 set_grid(grid());
00055 set_turbo(turbo());
00056 set_turbo_speed(turbo_speed());
00057 set_fullscreen(fullscreen());
00058 set_gamma(gamma());
00059 set_colour_cursors(utils::string_bool(preferences::get("colour_cursors")));
00060 }
00061
00062 display_manager::~display_manager()
00063 {
00064 disp = NULL;
00065 }
00066
00067 void set_fullscreen(bool ison)
00068 {
00069 _set_fullscreen(ison);
00070
00071 if(disp != NULL) {
00072 const std::pair<int,int>& res = resolution();
00073 CVideo& video = disp->video();
00074 if(video.isFullScreen() != ison) {
00075 const int flags = ison ? FULL_SCREEN : 0;
00076 const int bpp = video.modePossible(res.first,res.second,16,flags);
00077 if(bpp > 0) {
00078 video.setMode(res.first,res.second,bpp,flags);
00079 disp->redraw_everything();
00080 } else if(video.modePossible(1024,768,16,flags)) {
00081 set_resolution(std::pair<int,int>(1024,768));
00082 } else {
00083 gui::message_dialog(*disp,"",_("The video mode could not be changed. Your window manager must be set to 16 bits per pixel to run the game in windowed mode. Your display must support 1024x768x16 to run the game full screen.")).show();
00084 }
00085
00086 set_colour_cursors(utils::string_bool(preferences::get("colour_cursors")));
00087 }
00088 }
00089 }
00090
00091 void set_resolution(const std::pair<int,int>& resolution)
00092 {
00093 std::pair<int,int> res = resolution;
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104 bool write_resolution = true;
00105
00106 if(disp != NULL) {
00107 CVideo& video = disp->video();
00108 const int flags = fullscreen() ? FULL_SCREEN : 0;
00109 const int bpp = video.modePossible(res.first,res.second,16,flags);
00110 if(bpp != 0) {
00111 video.setMode(res.first,res.second,bpp,flags);
00112 disp->redraw_everything();
00113
00114 } else {
00115 write_resolution = false;
00116 gui::message_dialog(*disp,"",_("The video mode could not be changed. Your window manager must be set to 16 bits per pixel to run the game in windowed mode. Your display must support 1024x768x16 to run the game full screen.")).show();
00117 }
00118 }
00119
00120 if(write_resolution) {
00121 const std::string postfix = fullscreen() ? "resolution" : "windowsize";
00122 preferences::set('x' + postfix, lexical_cast<std::string>(res.first));
00123 preferences::set('y' + postfix, lexical_cast<std::string>(res.second));
00124 }
00125 }
00126
00127 void set_turbo(bool ison)
00128 {
00129 _set_turbo(ison);
00130
00131 if(disp != NULL) {
00132 disp->set_turbo(ison);
00133 }
00134 }
00135
00136 void set_turbo_speed(double speed)
00137 {
00138 save_turbo_speed(speed);
00139
00140 if(disp != NULL) {
00141 disp->set_turbo_speed(speed);
00142 }
00143 }
00144
00145 void set_adjust_gamma(bool val)
00146 {
00147
00148 if(val == false && adjust_gamma()) {
00149 CVideo& video = disp->video();
00150 video.setGamma(1.0);
00151 }
00152
00153 _set_adjust_gamma(val);
00154 }
00155
00156 void set_gamma(int gamma)
00157 {
00158 _set_gamma(gamma);
00159
00160 if(adjust_gamma()) {
00161 CVideo& video = disp->video();
00162 video.setGamma(static_cast<float>(gamma) / 100);
00163 }
00164 }
00165
00166 void set_grid(bool ison)
00167 {
00168 _set_grid(ison);
00169
00170 if(disp != NULL) {
00171 disp->set_grid(ison);
00172 }
00173 }
00174
00175 void set_colour_cursors(bool value)
00176 {
00177 _set_colour_cursors(value);
00178
00179 cursor::set();
00180 }
00181
00182 void set_idle_anim(bool ison) {
00183 _set_idle_anim(ison);
00184 if(disp != NULL) {
00185 disp->set_idle_anim(ison);
00186 }
00187 }
00188
00189 void set_idle_anim_rate(int rate) {
00190 _set_idle_anim_rate(rate);
00191 if(disp != NULL) {
00192 disp->set_idle_anim_rate(rate);
00193 }
00194 }
00195
00196 namespace {
00197 class escape_handler : public events::handler {
00198 public:
00199 escape_handler() : escape_pressed_(false) {}
00200 bool escape_pressed() { return escape_pressed_; }
00201 void handle_event(const SDL_Event &event) { escape_pressed_ |= (event.type == SDL_KEYDOWN)
00202 && (reinterpret_cast<const SDL_KeyboardEvent&>(event).keysym.sym == SDLK_ESCAPE); }
00203 private:
00204 bool escape_pressed_;
00205 };
00206 }
00207
00208 void show_hotkeys_dialog (display & disp, config *save_config)
00209 {
00210 log_scope ("show_hotkeys_dialog");
00211
00212 const events::event_context dialog_events_context;
00213
00214 const int centerx = disp.w()/2;
00215 const int centery = disp.h()/2;
00216 #ifdef USE_TINY_GUI
00217 const int width = 300;
00218
00219 const int height = 220;
00220 #else
00221 const int width = 700;
00222 const int height = 500;
00223 #endif
00224 const int xpos = centerx - width/2;
00225 const int ypos = centery - height/2;
00226
00227 gui::button close_button (disp.video(), _("Close Window"));
00228 std::vector<gui::button*> buttons;
00229 buttons.push_back(&close_button);
00230
00231 gui::dialog_frame f(disp.video(),_("Hotkey Settings"),gui::dialog_frame::default_style,true,&buttons);
00232 f.layout(xpos,ypos,width,height);
00233 f.draw();
00234
00235 SDL_Rect clip_rect = { 0, 0, disp.w (), disp.h () };
00236 SDL_Rect text_size = font::draw_text(NULL, clip_rect, font::SIZE_LARGE,
00237 font::NORMAL_COLOUR,_("Press desired Hotkey (Esc cancels)"),
00238 0, 0);
00239
00240 std::vector<std::string> menu_items;
00241
00242 std::vector<hotkey::hotkey_item>& hotkeys = hotkey::get_hotkeys();
00243 for(std::vector<hotkey::hotkey_item>::iterator i = hotkeys.begin(); i != hotkeys.end(); ++i) {
00244 if(i->hidden())
00245 continue;
00246 std::stringstream str,name;
00247 name << i->get_description();
00248 str << name.str();
00249 str << COLUMN_SEPARATOR;
00250
00251 str << font::NULL_MARKUP << i->get_name();
00252 menu_items.push_back(str.str());
00253 }
00254
00255 std::ostringstream heading;
00256 heading << HEADING_PREFIX << _("Action") << COLUMN_SEPARATOR << _("Binding");
00257 menu_items.push_back(heading.str());
00258
00259 gui::menu::basic_sorter sorter;
00260 sorter.set_alpha_sort(0).set_alpha_sort(1);
00261
00262 gui::menu menu_(disp.video(), menu_items, false, height, -1, &sorter, &gui::menu::bluebg_style);
00263 menu_.sort_by(0);
00264 menu_.reset_selection();
00265 menu_.set_width(font::relative_size(400));
00266 menu_.set_location(xpos + font::relative_size(20), ypos);
00267
00268 gui::button change_button (disp.video(), _("Change Hotkey"));
00269 change_button.set_location(xpos + width - change_button.width () - font::relative_size(30),ypos + font::relative_size(30));
00270
00271
00272 gui::button clear_button (disp.video(), _("Clear Hotkey"));
00273 clear_button.set_location(xpos + width - clear_button.width () - font::relative_size(30),ypos + font::relative_size(80));
00274
00275
00276
00277 escape_handler esc_hand;
00278
00279 for(;;) {
00280
00281 if (close_button.pressed() || esc_hand.escape_pressed())
00282 {
00283 if (save_config == NULL) {
00284 save_hotkeys();
00285 } else {
00286 hotkey::save_hotkeys(*save_config);
00287 }
00288 break;
00289 }
00290
00291 if (change_button.pressed () || menu_.double_clicked()) {
00292
00293 SDL_Rect dlgr = {centerx-text_size.w/2 - 30,
00294 centery-text_size.h/2 - 16,
00295 text_size.w+60,
00296 text_size.h+32};
00297 surface_restorer restorer(&disp.video(),dlgr);
00298 gui::dialog_frame mini_frame(disp.video());
00299 mini_frame.layout(centerx-text_size.w/2 - 20,
00300 centery-text_size.h/2 - 6,
00301 text_size.w+40,
00302 text_size.h+12);
00303 mini_frame.draw_background();
00304 mini_frame.draw_border();
00305 font::draw_text (&disp.video(), clip_rect, font::SIZE_LARGE,font::NORMAL_COLOUR,
00306 _("Press desired Hotkey (Esc cancels)"),centerx-text_size.w/2,
00307 centery-text_size.h/2);
00308 disp.update_display();
00309 SDL_Event event;
00310 event.type = 0;
00311 int character=0,keycode=0;
00312 int mod=0;
00313 while (event.type!=SDL_KEYDOWN) SDL_PollEvent(&event);
00314 do {
00315 if (event.type==SDL_KEYDOWN)
00316 {
00317 keycode=event.key.keysym.sym;
00318 character=event.key.keysym.unicode;
00319 mod=event.key.keysym.mod;
00320 };
00321 SDL_PollEvent(&event);
00322 disp.flip();
00323 disp.delay(10);
00324 } while (event.type!=SDL_KEYUP);
00325 restorer.restore();
00326 disp.update_display();
00327
00328 if (keycode == SDLK_ESCAPE && mod == 0) {
00329
00330 } else {
00331 const hotkey::hotkey_item& oldhk = hotkey::get_hotkey(character, keycode, (mod & KMOD_SHIFT) != 0,
00332 (mod & KMOD_CTRL) != 0, (mod & KMOD_ALT) != 0, (mod & KMOD_LMETA) != 0);
00333
00334 hotkey::hotkey_item& newhk = hotkey::get_visible_hotkey(menu_.selection());
00335
00336 if(oldhk.get_id() != newhk.get_id() && !oldhk.null()) {
00337 std::stringstream msg;
00338 msg << " " << oldhk.get_description() << " : " << oldhk.get_name();
00339 gui::message_dialog(disp,_("This Hotkey is already in use."),msg.str()).show();
00340 } else {
00341
00342 newhk.set_key(character, keycode, (mod & KMOD_SHIFT) != 0,
00343 (mod & KMOD_CTRL) != 0, (mod & KMOD_ALT) != 0, (mod & KMOD_LMETA) != 0);
00344
00345 menu_.change_item(menu_.selection(), 1, font::NULL_MARKUP + newhk.get_name());
00346
00347 if ((newhk.get_id() == hotkey::HOTKEY_SCREENSHOT
00348 || newhk.get_id() == hotkey::HOTKEY_MAP_SCREENSHOT)
00349 && (mod & KMOD_CTRL) == 0 && (mod & KMOD_ALT) == 0
00350 && (mod & KMOD_LMETA) == 0) {
00351 gui::message_dialog(disp,"", _("Warning: screenshot hotkeys not combined with Control, Alt or Meta keys.")).show();
00352 }
00353 }
00354 }
00355 }
00356
00357
00358
00359
00360
00361
00362
00363
00364 if (clear_button.pressed()) {
00365
00366 hotkey::hotkey_item& newhk = hotkey::get_visible_hotkey(menu_.selection());
00367 newhk.clear_hotkey();
00368 menu_.change_item(menu_.selection(), 1, font::NULL_MARKUP + newhk.get_name());
00369 }
00370
00371 menu_.process();
00372
00373 events::pump();
00374 events::raise_process_event();
00375 events::raise_draw_event();
00376
00377 disp.update_display();
00378
00379 disp.delay(10);
00380 }
00381 }
00382
00383 bool compare_resolutions(const std::pair<int,int>& lhs, const std::pair<int,int>& rhs)
00384 {
00385 return lhs.first*lhs.second < rhs.first*rhs.second;
00386 }
00387
00388 bool show_video_mode_dialog(display& disp)
00389 {
00390 const resize_lock prevent_resizing;
00391 const events::event_context dialog_events_context;
00392
00393 CVideo& video = disp.video();
00394
00395 SDL_PixelFormat format = *video.getSurface()->format;
00396 format.BitsPerPixel = video.getBpp();
00397
00398 const SDL_Rect* const * modes = SDL_ListModes(&format,FULL_SCREEN);
00399
00400
00401
00402 if(modes == reinterpret_cast<SDL_Rect**>(-1)) {
00403 std::cerr << "Can support any video mode\n";
00404
00405
00406
00407 static const SDL_Rect scr_modes[] = {
00408 { 0, 0, 320, 240 },
00409 { 0, 0, 640, 480 },
00410 { 0, 0, 800, 480 },
00411 { 0, 0, 800, 600 },
00412 { 0, 0, 1024, 768 },
00413 { 0, 0, 1280, 960 },
00414 { 0, 0, 1280, 1024 },
00415 };
00416 static const SDL_Rect * const scr_modes_list[] = {
00417 &scr_modes[0],
00418 &scr_modes[1],
00419 &scr_modes[2],
00420 &scr_modes[3],
00421 &scr_modes[4],
00422 &scr_modes[5],
00423 &scr_modes[6],
00424 NULL
00425 };
00426
00427 modes = scr_modes_list;
00428 } else if(modes == NULL) {
00429 std::cerr << "No modes supported\n";
00430 gui::message_dialog(disp,"",_("There are no alternative video modes available")).show();
00431 return false;
00432 }
00433
00434 std::vector<std::pair<int,int> > resolutions;
00435
00436 for(int i = 0; modes[i] != NULL; ++i) {
00437 if(modes[i]->w >= min_allowed_width && modes[i]->h >= min_allowed_height) {
00438 resolutions.push_back(std::pair<int,int>(modes[i]->w,modes[i]->h));
00439 }
00440 }
00441
00442 const std::pair<int,int> current_res(video.getSurface()->w,video.getSurface()->h);
00443 resolutions.push_back(current_res);
00444
00445 std::sort(resolutions.begin(),resolutions.end(),compare_resolutions);
00446 resolutions.erase(std::unique(resolutions.begin(),resolutions.end()),resolutions.end());
00447
00448 std::vector<std::string> options;
00449 for(std::vector<std::pair<int,int> >::const_iterator j = resolutions.begin(); j != resolutions.end(); ++j) {
00450 std::ostringstream option;
00451 if (*j == current_res)
00452 option << DEFAULT_ITEM;
00453
00454 option << j->first << "x" << j->second;
00455 options.push_back(option.str());
00456 }
00457
00458 const int result = gui::show_dialog(disp,NULL,"",
00459 _("Choose Resolution"),
00460 gui::OK_CANCEL,&options);
00461 if(size_t(result) < resolutions.size() && resolutions[result] != current_res) {
00462 set_resolution(resolutions[result]);
00463 return true;
00464 } else {
00465 return false;
00466 }
00467 }
00468
00469 }
00470