00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "gui/widgets/settings.hpp"
00019
00020 #include "filesystem.hpp"
00021 #include "gettext.hpp"
00022 #include "gui/widgets/helper.hpp"
00023 #include "log.hpp"
00024 #include "serialization/parser.hpp"
00025 #include "serialization/preprocessor.hpp"
00026 #include "util.hpp"
00027 #include "video.hpp"
00028 #include "wml_exception.hpp"
00029
00030 #include <cassert>
00031
00032 #define DBG_G LOG_STREAM_INDENT(debug, gui)
00033 #define LOG_G LOG_STREAM_INDENT(info, gui)
00034 #define WRN_G LOG_STREAM_INDENT(warn, gui)
00035 #define ERR_G LOG_STREAM_INDENT(err, gui)
00036
00037 #define DBG_G_D LOG_STREAM_INDENT(debug, gui_draw)
00038 #define LOG_G_D LOG_STREAM_INDENT(info, gui_draw)
00039 #define WRN_G_D LOG_STREAM_INDENT(warn, gui_draw)
00040 #define ERR_G_D LOG_STREAM_INDENT(err, gui_draw)
00041
00042 #define DBG_G_E LOG_STREAM_INDENT(debug, gui_event)
00043 #define LOG_G_E LOG_STREAM_INDENT(info, gui_event)
00044 #define WRN_G_E LOG_STREAM_INDENT(warn, gui_event)
00045 #define ERR_G_E LOG_STREAM_INDENT(err, gui_event)
00046
00047 #define DBG_G_P LOG_STREAM_INDENT(debug, gui_parse)
00048 #define LOG_G_P LOG_STREAM_INDENT(info, gui_parse)
00049 #define WRN_G_P LOG_STREAM_INDENT(warn, gui_parse)
00050 #define ERR_G_P LOG_STREAM_INDENT(err, gui_parse)
00051
00052 namespace gui2 {
00053
00054 namespace settings {
00055 unsigned screen_width = 0;
00056 unsigned screen_height = 0;
00057
00058 unsigned popup_show_delay = 0;
00059 unsigned popup_show_time = 0;
00060 unsigned help_show_time = 0;
00061 unsigned double_click_time = 0;
00062
00063 }
00064
00065 namespace {
00066
00067
00068 std::map<std::string, twindow_builder> windows;
00069
00070
00071 std::map<std::string, tgui_definition> guis;
00072
00073
00074 std::map<std::string, tgui_definition>::const_iterator current_gui = guis.end();
00075
00076
00077
00078 std::vector<std::string> window_type_list(DUMMY);
00079 }
00080
00081 static void fill_window_types()
00082 {
00083 window_type_list[ADDON_CONNECT] = "addon_connect";
00084 window_type_list[LANGUAGE_SELECTION] = "language_selection";
00085 window_type_list[MP_METHOD_SELECTION] = "mp_method_selection";
00086 }
00087
00088 const std::string& get_id(const twindow_type window_type)
00089 {
00090 assert(window_type >= 0 && window_type < DUMMY);
00091
00092 return window_type_list[window_type];
00093 }
00094
00095 void load_settings()
00096 {
00097 LOG_G << "Setting: init gui.\n";
00098
00099
00100 fill_window_types();
00101
00102 const SDL_Rect rect = screen_area();
00103 settings::screen_width = rect.w;
00104 settings::screen_height = rect.h;
00105
00106
00107 config cfg;
00108 const std::string& filename = "data/gui/default.cfg";
00109 try {
00110 scoped_istream stream = preprocess_file(filename);
00111 read(cfg, *stream);
00112 } catch(config::error&) {
00113 ERR_G_P << "Setting: could not read file '" << filename << "'.\n";
00114 }
00115
00116
00117 const config::child_list& gui_cfgs = cfg.get_children("gui");
00118 for(std::vector<config*>::const_iterator itor = gui_cfgs.begin();
00119 itor != gui_cfgs.end(); ++itor) {
00120
00121 std::pair<std::string, tgui_definition> child;
00122 child.first = child.second.read(**itor);
00123 guis.insert(child);
00124 }
00125
00126 VALIDATE(guis.find("default") != guis.end(), _ ("No default gui defined."));
00127
00128 current_gui = guis.find("default");
00129 current_gui->second.activate();
00130 }
00131
00132 const std::string& tgui_definition::read(const config& cfg)
00133 {
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195 id = cfg["id"];
00196 description = cfg["description"];
00197
00198 VALIDATE(!id.empty(), missing_mandatory_wml_key("gui", "id"));
00199 VALIDATE(!description.empty(), missing_mandatory_wml_key("gui", "description"));
00200
00201 DBG_G_P << "Parsing gui " << id << '\n';
00202
00203
00204 load_definitions<tbutton_definition>("button", cfg.get_children("button_definition"));
00205 load_definitions<tlabel_definition>("label", cfg.get_children("label_definition"));
00206 load_definitions<tlistbox_definition>("listbox", cfg.get_children("listbox_definition"));
00207 load_definitions<tpanel_definition>("panel", cfg.get_children("panel_definition"));
00208 load_definitions<tspacer_definition>("spacer", cfg.get_children("spacer_definition"));
00209 load_definitions<ttext_box_definition>("text_box", cfg.get_children("text_box_definition"));
00210 load_definitions<ttoggle_button_definition>("toggle_button", cfg.get_children("toggle_button_definition"));
00211 load_definitions<ttooltip_definition>("tooltip", cfg.get_children("tooltip_definition"));
00212 load_definitions<tvertical_scrollbar_definition>
00213 ("vertical_scrollbar", cfg.get_children("vertical_scrollbar_definition"));
00214 load_definitions<twindow_definition>("window", cfg.get_children("window_definition"));
00215
00216
00217 const config::child_list& window_instance_cfgs = cfg.get_children("window");
00218 for(std::vector<config*>::const_iterator itor = window_instance_cfgs.begin();
00219 itor != window_instance_cfgs.end(); ++itor) {
00220
00221 std::pair<std::string, twindow_builder> child;
00222 child.first = child.second.read(**itor);
00223 window_types.insert(child);
00224 }
00225
00226 if(id == "default") {
00227
00228
00229 for(std::vector<std::string>::const_iterator itor = window_type_list.begin();
00230 itor != window_type_list.end(); ++itor) {
00231
00232 VALIDATE(window_types.find(*itor) != window_types.end(), _("Window not defined."));
00233 }
00234 }
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 const config& settings = *cfg.child("settings");
00256
00257 popup_show_delay_ = lexical_cast_default<unsigned>(settings["popup_show_delay"]);
00258 popup_show_time_ = lexical_cast_default<unsigned>(settings["popup_show_time"]);
00259 help_show_time_ = lexical_cast_default<unsigned>(settings["help_show_time"]);
00260 double_click_time_ = lexical_cast_default<unsigned>(settings["double_click_time"]);
00261
00262 VALIDATE(double_click_time_, missing_mandatory_wml_key("settings", "double_click_time"));
00263
00264 return id;
00265 }
00266
00267 void tgui_definition::activate() const
00268 {
00269 settings::popup_show_delay = popup_show_delay_;
00270 settings::popup_show_time = popup_show_time_;
00271 settings::help_show_time = help_show_time_;
00272 settings::double_click_time = double_click_time_;
00273 }
00274
00275 template<class T>
00276 void tgui_definition::load_definitions(
00277 const std::string& definition_type, const config::child_list& definition_list)
00278 {
00279 for(std::vector<config*>::const_iterator itor = definition_list.begin();
00280 itor != definition_list.end(); ++itor) {
00281
00282 T* def = new T(**itor);
00283
00284 control_definition[definition_type].insert(std::make_pair(def->id, def));
00285 }
00286
00287 utils::string_map symbols;
00288 symbols["definition"] = definition_type;
00289 symbols["id"] = "default";
00290 t_string msg(vgettext(
00291 "Widget defintion '$definition' doesn't contain the defintion for '$id'.",
00292 symbols));
00293 VALIDATE(control_definition[definition_type].find("default")
00294 != control_definition[definition_type].end(), msg);
00295 }
00296
00297 tcontrol_definition::tcontrol_definition(const config& cfg) :
00298 id(cfg["id"]),
00299 description(cfg["description"]),
00300 resolutions()
00301 {
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 VALIDATE(!id.empty(), missing_mandatory_wml_key("gui", "id"));
00322 VALIDATE(!description.empty(), missing_mandatory_wml_key("gui", "description"));
00323
00324 }
00325
00326 tresolution_definition_::tresolution_definition_(const config& cfg) :
00327 window_width(lexical_cast_default<unsigned>(cfg["window_width"])),
00328 window_height(lexical_cast_default<unsigned>(cfg["window_height"])),
00329 min_width(lexical_cast_default<unsigned>(cfg["min_width"])),
00330 min_height(lexical_cast_default<unsigned>(cfg["min_height"])),
00331 default_width(lexical_cast_default<unsigned>(cfg["default_width"])),
00332 default_height(lexical_cast_default<unsigned>(cfg["default_height"])),
00333 max_width(lexical_cast_default<unsigned>(cfg["max_width"])),
00334 max_height(lexical_cast_default<unsigned>(cfg["max_height"])),
00335 text_extra_width(lexical_cast_default<unsigned>(cfg["text_extra_width"])),
00336 text_extra_height(lexical_cast_default<unsigned>(cfg["text_extra_height"])),
00337 text_font_size(lexical_cast_default<unsigned>(cfg["text_font_size"])),
00338 text_font_style(decode_font_style(cfg["text_font_style"])),
00339 state()
00340 {
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395 DBG_G_P << "Parsing resolution "
00396 << window_width << ", " << window_height << '\n';
00397 }
00398
00399 template<class T>
00400 void tcontrol_definition::load_resolutions(const config::child_list& resolution_list)
00401 {
00402
00403 VALIDATE(!resolution_list.empty(), _("No resolution defined."));
00404 for(std::vector<config*>::const_iterator itor = resolution_list.begin();
00405 itor != resolution_list.end(); ++itor) {
00406
00407 resolutions.push_back(new T(**itor));
00408 }
00409 }
00410
00411 tstate_definition::tstate_definition(const config* cfg) :
00412 full_redraw(cfg ? utils::string_bool((*cfg)["full_redraw"]) : false),
00413 canvas()
00414 {
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433 const config* draw = cfg ? cfg->child("draw") : 0;
00434
00435 VALIDATE(draw, _("No state or draw section defined."));
00436
00437 canvas.set_cfg(*draw);
00438 }
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454 tbutton_definition::tbutton_definition(const config& cfg) :
00455 tcontrol_definition(cfg)
00456 {
00457 DBG_G_P << "Parsing button " << id << '\n';
00458
00459 load_resolutions<tresolution>(cfg.get_children("resolution"));
00460 }
00461
00462 tbutton_definition::tresolution::tresolution(const config& cfg) :
00463 tresolution_definition_(cfg)
00464 {
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482 state.push_back(tstate_definition(cfg.child("state_enabled")));
00483 state.push_back(tstate_definition(cfg.child("state_disabled")));
00484 state.push_back(tstate_definition(cfg.child("state_pressed")));
00485 state.push_back(tstate_definition(cfg.child("state_focussed")));
00486 }
00487
00488 tlabel_definition::tlabel_definition(const config& cfg) :
00489 tcontrol_definition(cfg)
00490 {
00491 DBG_G_P << "Parsing label " << id << '\n';
00492
00493 load_resolutions<tresolution>(cfg.get_children("resolution"));
00494 }
00495
00496
00497 tlabel_definition::tresolution::tresolution(const config& cfg) :
00498 tresolution_definition_(cfg)
00499 {
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515 state.push_back(tstate_definition(cfg.child("state_enabled")));
00516 state.push_back(tstate_definition(cfg.child("state_disabled")));
00517 }
00518
00519 tlistbox_definition::tlistbox_definition(const config& cfg) :
00520 tcontrol_definition(cfg)
00521 {
00522 DBG_G_P << "Parsing listbox " << id << '\n';
00523
00524 load_resolutions<tresolution>(cfg.get_children("resolution"));
00525 }
00526
00527 tlistbox_definition::tresolution::tresolution(const config& cfg) :
00528 tresolution_definition_(cfg),
00529 scrollbar(0)
00530
00531 {
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583 state.push_back(tstate_definition(cfg.child("state_enabled")));
00584 state.push_back(tstate_definition(cfg.child("state_disabled")));
00585
00586 const config* grid = cfg.child("scrollbar");
00587 VALIDATE(grid, _("No scrollbar defined."));
00588
00589 scrollbar = new tbuilder_grid(*grid);
00590 }
00591
00592 tpanel_definition::tpanel_definition(const config& cfg) :
00593 tcontrol_definition(cfg)
00594 {
00595
00596 DBG_G_P << "Parsing panel " << id << '\n';
00597
00598 load_resolutions<tresolution>(cfg.get_children("resolution"));
00599 }
00600
00601 tpanel_definition::tresolution::tresolution(const config& cfg) :
00602 tresolution_definition_(cfg),
00603 top_border(lexical_cast_default<unsigned>(cfg["top_border"])),
00604 bottom_border(lexical_cast_default<unsigned>(cfg["bottom_border"])),
00605 left_border(lexical_cast_default<unsigned>(cfg["left_border"])),
00606 right_border(lexical_cast_default<unsigned>(cfg["right_border"]))
00607 {
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632 state.push_back(tstate_definition(cfg.child("background")));
00633 state.push_back(tstate_definition(cfg.child("foreground")));
00634 }
00635
00636 tspacer_definition::tspacer_definition(const config& cfg) :
00637 tcontrol_definition(cfg)
00638 {
00639 DBG_G_P << "Parsing spacer " << id << '\n';
00640
00641 load_resolutions<tresolution>(cfg.get_children("resolution"));
00642 }
00643
00644
00645 tspacer_definition::tresolution::tresolution(const config& cfg) :
00646 tresolution_definition_(cfg)
00647 {
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659 }
00660
00661 ttext_box_definition::ttext_box_definition(const config& cfg) :
00662 tcontrol_definition(cfg)
00663 {
00664 DBG_G_P << "Parsing text_box " << id << '\n';
00665
00666 load_resolutions<tresolution>(cfg.get_children("resolution"));
00667 }
00668
00669 ttext_box_definition::tresolution::tresolution(const config& cfg) :
00670 tresolution_definition_(cfg),
00671 text_x_offset(cfg["text_x_offset"]),
00672 text_y_offset(cfg["text_y_offset"])
00673 {
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701 state.push_back(tstate_definition(cfg.child("state_enabled")));
00702 state.push_back(tstate_definition(cfg.child("state_disabled")));
00703 state.push_back(tstate_definition(cfg.child("state_focussed")));
00704 }
00705
00706 ttoggle_button_definition::ttoggle_button_definition(const config& cfg) :
00707 tcontrol_definition(cfg)
00708 {
00709 DBG_G_P << "Parsing toggle button " << id << '\n';
00710
00711 load_resolutions<tresolution>(cfg.get_children("resolution"));
00712 }
00713
00714 ttoggle_button_definition::tresolution::tresolution(const config& cfg) :
00715 tresolution_definition_(cfg)
00716
00717 {
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738 state.push_back(tstate_definition(cfg.child("state_enabled")));
00739 state.push_back(tstate_definition(cfg.child("state_disabled")));
00740 state.push_back(tstate_definition(cfg.child("state_focussed")));
00741
00742 state.push_back(tstate_definition(cfg.child("state_enabled_selected")));
00743 state.push_back(tstate_definition(cfg.child("state_disabled_selected")));
00744 state.push_back(tstate_definition(cfg.child("state_focussed_selected")));
00745 }
00746
00747 ttooltip_definition::ttooltip_definition(const config& cfg) :
00748 tcontrol_definition(cfg)
00749 {
00750 DBG_G_P << "Parsing tooltip " << id << '\n';
00751
00752 load_resolutions<tresolution>(cfg.get_children("resolution"));
00753 }
00754
00755 ttooltip_definition::tresolution::tresolution(const config& cfg) :
00756 tresolution_definition_(cfg)
00757
00758 {
00759
00760
00761
00762
00763
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773 state.push_back(tstate_definition(cfg.child("state_enabled")));
00774 }
00775
00776 tvertical_scrollbar_definition::tvertical_scrollbar_definition(const config& cfg) :
00777 tcontrol_definition(cfg)
00778 {
00779 DBG_G_P << "Parsing vertical scrollbar " << id << '\n';
00780
00781 load_resolutions<tresolution>(cfg.get_children("resolution"));
00782 }
00783
00784 tvertical_scrollbar_definition::tresolution::tresolution(const config& cfg) :
00785 tresolution_definition_(cfg),
00786 minimum_positioner_length(
00787 lexical_cast_default<unsigned>(cfg["minimum_positioner_length"])),
00788 top_offset(lexical_cast_default<unsigned>(cfg["top_offset"])),
00789 bottom_offset(lexical_cast_default<unsigned>(cfg["bottom_offset"]))
00790 {
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 VALIDATE(minimum_positioner_length,
00825 missing_mandatory_wml_key("resolution", "minimum_positioner_length"));
00826
00827
00828 state.push_back(tstate_definition(cfg.child("state_enabled")));
00829 state.push_back(tstate_definition(cfg.child("state_disabled")));
00830 state.push_back(tstate_definition(cfg.child("state_pressed")));
00831 state.push_back(tstate_definition(cfg.child("state_focussed")));
00832 }
00833
00834 twindow_definition::twindow_definition(const config& cfg) :
00835 tpanel_definition(cfg)
00836 {
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848 DBG_G_P << "Parsing window " << id << '\n';
00849 }
00850
00851 tresolution_definition_* get_control(const std::string& control_type, const std::string& definition)
00852 {
00853 const tgui_definition::tcontrol_definition_map::const_iterator
00854 control_definition = current_gui->second.control_definition.find(control_type);
00855
00856 assert(control_definition != current_gui->second.control_definition.end());
00857
00858 std::map<std::string, tcontrol_definition*>::const_iterator
00859 control = control_definition->second.find(definition);
00860
00861 if(control == control_definition->second.end()) {
00862 LOG_G << "Control: type '" << control_type << "' definition '"
00863 << definition << "' not found, falling back to 'default'.\n";
00864 control = control_definition->second.find("default");
00865 assert(control != control_definition->second.end());
00866 }
00867
00868 for(std::vector<tresolution_definition_*>::const_iterator
00869 itor = (*control->second).resolutions.begin(),
00870 end = (*control->second).resolutions.end();
00871 itor != end;
00872 ++itor) {
00873
00874 if(settings::screen_width <= (**itor).window_width &&
00875 settings::screen_height <= (**itor).window_height) {
00876
00877 return *itor;
00878 } else if (itor == end - 1) {
00879 return *itor;
00880 }
00881 }
00882
00883 assert(false);
00884 }
00885
00886 std::vector<twindow_builder::tresolution>::const_iterator get_window_builder(const std::string& type)
00887 {
00888 std::map<std::string, twindow_builder>::const_iterator
00889 window = current_gui->second.window_types.find(type);
00890
00891 if(true) {
00892 assert(window != current_gui->second.window_types.end());
00893 } else {
00894
00895 }
00896
00897 for(std::vector<twindow_builder::tresolution>::const_iterator
00898 itor = window->second.resolutions.begin(),
00899 end = window->second.resolutions.end();
00900 itor != end;
00901 ++itor) {
00902
00903 if(settings::screen_width <= itor->window_width &&
00904 settings::screen_height <= itor->window_height) {
00905
00906 return itor;
00907 } else if (itor == end - 1) {
00908 return itor;
00909 }
00910 }
00911
00912 assert(false);
00913 }
00914
00915 }