00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #define GETTEXT_DOMAIN "wesnoth-lib"
00017
00018 #include "gui/dialogs/gamestate_inspector.hpp"
00019
00020 #include "gui/dialogs/helper.hpp"
00021 #include "gui/widgets/button.hpp"
00022 #ifdef GUI2_EXPERIMENTAL_LISTBOX
00023 #include "gui/widgets/list.hpp"
00024 #else
00025 #include "gui/widgets/listbox.hpp"
00026 #endif
00027 #include "gui/widgets/settings.hpp"
00028 #include "gui/widgets/window.hpp"
00029
00030 #include "../../foreach.hpp"
00031 #include "../../gamestatus.hpp"
00032 #include "../../resources.hpp"
00033 #include "../../team.hpp"
00034 #include "../../ai/manager.hpp"
00035
00036 #include <vector>
00037 #include <boost/bind.hpp>
00038 #include <boost/shared_ptr.hpp>
00039
00040 namespace gui2 {
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080 template <class D, class V, void (V::*fptr)(twindow&)>
00081 void dialog_view_callback(twidget* caller)
00082 {
00083 D* dialog = dynamic_cast<D*>(caller->dialog());
00084 assert(dialog);
00085 twindow* window = dynamic_cast<twindow*>(caller->get_window());
00086 assert(window);
00087 (*(dialog->get_view()).*fptr)(*window);
00088 }
00089
00090
00091
00092 class tgamestate_inspector::model {
00093 public:
00094 model(const vconfig &c)
00095 : cfg(c), name(), stuff_list(),stuff_types_list(),inspect(),inspector_name()
00096 {
00097 name = cfg["name"].str();
00098 }
00099
00100 vconfig cfg;
00101 std::string name;
00102
00103 tlistbox *stuff_list;
00104 tlistbox *stuff_types_list;
00105 tcontrol *inspect;
00106 tcontrol *inspector_name;
00107
00108
00109 void clear_stuff_list()
00110 {
00111 stuff_list->clear();
00112 }
00113
00114
00115 void clear_stuff_types_list()
00116 {
00117 stuff_types_list->clear();
00118 }
00119
00120 void add_row_to_stuff_list(const std::string &id, const std::string &label)
00121 {
00122 std::map<std::string, string_map> data;
00123 string_map item;
00124 item["id"] = id;
00125 item["label"] = label;
00126 data.insert(std::make_pair("name", item));
00127 stuff_list->add_row(data);
00128 }
00129
00130
00131 void add_row_to_stuff_types_list(const std::string &id, const std::string &label)
00132 {
00133 std::map<std::string, string_map> data;
00134 string_map item;
00135 item["id"] = id;
00136 item["label"] = label;
00137 data.insert(std::make_pair("typename", item));
00138 stuff_types_list->add_row(data);
00139 }
00140
00141
00142 void set_inspect_window_text(const std::string &s)
00143 {
00144 std::string s_ = s;
00145 if (s_.length()>20000) {
00146 s_.resize(20000);
00147 }
00148 inspect->set_label(s_);
00149 }
00150
00151 };
00152
00153 class single_mode_controller {
00154 public:
00155 single_mode_controller(const std::string& name, tgamestate_inspector::model &m)
00156 :model_(m), name_(name)
00157 {
00158 }
00159 virtual ~single_mode_controller()
00160 {
00161 }
00162
00163 std::string name() const
00164 {
00165 return name_;
00166 }
00167
00168 virtual void show_stuff_list() = 0;
00169 virtual void handle_stuff_list_selection() = 0;
00170 virtual void update_view_from_model() = 0;
00171
00172 protected:
00173 tgamestate_inspector::model &model_;
00174 std::string name_;
00175 };
00176
00177 class variable_mode_controller : public single_mode_controller{
00178 public:
00179 variable_mode_controller(const std::string& name, tgamestate_inspector::model &m)
00180 :single_mode_controller(name,m)
00181 {
00182 }
00183
00184 void show_stuff_list()
00185 {
00186 model_.clear_stuff_list();
00187
00188 const config &vars = resources::state_of_game
00189 ? resources::state_of_game->get_variables()
00190 : config();
00191
00192 foreach( const config::attribute &a, vars.attribute_range()) {
00193 model_.add_row_to_stuff_list(a.first,a.first);
00194 }
00195
00196 foreach( const config::any_child &c, vars.all_children_range()) {
00197 model_.add_row_to_stuff_list("["+c.key+"]","["+c.key+"]");
00198 }
00199
00200 model_.set_inspect_window_text("");
00201
00202 }
00203
00204 void handle_stuff_list_selection()
00205 {
00206 int selected = model_.stuff_list->get_selected_row();
00207 if (selected==-1) {
00208 model_.set_inspect_window_text("");
00209 return;
00210 }
00211
00212 int i = 0;
00213 const config &vars = resources::state_of_game
00214 ? resources::state_of_game->get_variables()
00215 : config();
00216
00217 foreach( const config::attribute &a, vars.attribute_range()) {
00218 if (selected==i) {
00219 model_.set_inspect_window_text(a.second);
00220 return;
00221 }
00222 i++;
00223 }
00224
00225 foreach( const config::any_child &c, vars.all_children_range()) {
00226 if (selected==i) {
00227 model_.set_inspect_window_text(c.cfg.debug());
00228 return;
00229 }
00230 i++;
00231 }
00232 }
00233
00234 virtual void update_view_from_model()
00235 {
00236 show_stuff_list();
00237
00238 }
00239 };
00240
00241
00242
00243 class unit_mode_controller : public single_mode_controller{
00244 public:
00245 unit_mode_controller(const std::string& name, tgamestate_inspector::model &m)
00246 :single_mode_controller(name,m)
00247 {
00248 }
00249
00250 void show_stuff_list()
00251 {
00252 model_.clear_stuff_list();
00253
00254 if(resources::units) {
00255 for(unit_map::iterator i = resources::units->begin()
00256 ; i != resources::units->end()
00257 ; ++i) {
00258
00259 std::stringstream s;
00260 s << '(' << i->get_location();
00261 s << ") side=" << i->side() << ' ';
00262 if (i->can_recruit()) {
00263 s << "LEADER ";
00264 }
00265
00266 s << "id=[" << i->id() << "] " << i->type_id()
00267 << "; L" << i->level()<< "; " << i->experience()
00268 << '/' << i->max_experience() << " xp; "
00269 << i->hitpoints() << '/' << i->max_hitpoints()
00270 << " hp; ";
00271 foreach (const std::string &str, i->get_traits_list()) {
00272 s << str <<" ";
00273 }
00274
00275 std::string key = s.str();
00276 model_.add_row_to_stuff_list(key,key);
00277 }
00278 }
00279
00280 model_.set_inspect_window_text("");
00281
00282 }
00283
00284 void handle_stuff_list_selection()
00285 {
00286 int selected = model_.stuff_list->get_selected_row();
00287 if (selected==-1) {
00288 model_.set_inspect_window_text("");
00289 return;
00290 }
00291
00292 if(resources::units) {
00293 int i = 0;
00294 for(unit_map::iterator u = resources::units->begin()
00295 ; u != resources::units->end()
00296 ; ++u) {
00297 if (selected==i) {
00298 config c_unit;
00299 u->write(c_unit);
00300 model_.set_inspect_window_text(c_unit.debug());
00301 return;
00302 }
00303 i++;
00304 }
00305 }
00306 model_.set_inspect_window_text("");
00307
00308 }
00309
00310 virtual void update_view_from_model()
00311 {
00312 show_stuff_list();
00313
00314 }
00315 };
00316
00317
00318 class team_mode_controller : public single_mode_controller{
00319 public:
00320 team_mode_controller(const std::string& name, tgamestate_inspector::model &m, int side)
00321 :single_mode_controller(name,m), side_(side)
00322 {
00323 }
00324
00325 void show_stuff_list()
00326 {
00327 model_.clear_stuff_list();
00328
00329 model_.add_row_to_stuff_list("overview","overview");
00330 model_.add_row_to_stuff_list("ai overview","ai overview");
00331 model_.add_row_to_stuff_list("ai config full","ai config full");
00332 model_.add_row_to_stuff_list("recall list overview","recall list overview");
00333 model_.add_row_to_stuff_list("recall list full","recall list full");
00334 model_.add_row_to_stuff_list("ai component structure","ai component structure");
00335 model_.add_row_to_stuff_list("unit list overview","unit list overview");
00336 model_.set_inspect_window_text("");
00337
00338 }
00339
00340 void handle_stuff_list_selection()
00341 {
00342 int selected = model_.stuff_list->get_selected_row();
00343 if (selected==-1) {
00344 model_.set_inspect_window_text("");
00345 return;
00346 }
00347
00348 if (selected==0) {
00349 config c = resources::teams
00350 ? resources::teams->at(side_-1).to_config()
00351 : config();
00352 c.clear_children("ai");
00353 c.clear_children("village");
00354 model_.set_inspect_window_text(c.debug());
00355 return;
00356 }
00357
00358 if (selected==1) {
00359 model_.set_inspect_window_text(ai::manager::get_active_ai_overview_for_side(side_));
00360 return;
00361 }
00362
00363 if (selected==2) {
00364 model_.set_inspect_window_text(ai::manager::to_config(side_).debug());
00365 return;
00366 }
00367
00368 if (selected==3) {
00369 const std::vector<unit> recall_list = resources::teams
00370 ? resources::teams->at(side_-1).recall_list()
00371 : std::vector<unit>();
00372
00373 std::stringstream s;
00374 foreach (const unit &u, recall_list) {
00375 s << "id=["<<u.id() << "] "<<u.type_id() << "; L"<<u.level()<<"; " << u.experience() <<"/" << u.max_experience()<< " xp "<< std::endl;
00376 foreach (const std::string &str, u.get_traits_list() ) {
00377 s << "\t" << str<< std::endl;
00378 }
00379 s << std::endl << std::endl;
00380 }
00381 model_.set_inspect_window_text(s.str());
00382 return;
00383 }
00384
00385 if (selected==4) {
00386 const std::vector<unit> recall_list = resources::teams
00387 ? resources::teams->at(side_-1).recall_list()
00388 : std::vector<unit>();
00389
00390 config c;
00391 foreach (const unit &u, recall_list) {
00392 config c_unit;
00393 u.write(c_unit);
00394 c.add_child("unit",c_unit);
00395 }
00396 model_.set_inspect_window_text(c.debug());
00397 return;
00398 }
00399
00400 if (selected==5) {
00401 model_.set_inspect_window_text(ai::manager::get_active_ai_structure_for_side(side_));
00402 return;
00403 }
00404
00405
00406 if (selected==6) {
00407 std::stringstream s;
00408 if(resources::units) {
00409 for(unit_map::iterator i = resources::units->begin()
00410 ; i != resources::units->end()
00411 ; ++i) {
00412 if (i->side()!=side_) {
00413 continue;
00414 }
00415 s << i->get_location();
00416 if (i->can_recruit()) {
00417 s << " LEADER ";
00418 }
00419
00420 s << "id=[" << i->id() << "] " << i->type_id()
00421 << "; L" << i->level()<< "; "
00422 << i->experience() << '/'
00423 << i->max_experience() << " xp; "
00424 << i->hitpoints() << '/'
00425 << i->max_hitpoints()<<" hp.\n";
00426 foreach (const std::string &str, i->get_traits_list() ) {
00427 s << "\t" << str<< std::endl;
00428 }
00429 s << std::endl << std::endl;
00430 }
00431 }
00432 model_.set_inspect_window_text(s.str());
00433 return;
00434 }
00435
00436 }
00437
00438 virtual void update_view_from_model()
00439 {
00440 show_stuff_list();
00441
00442 }
00443 private:
00444 int side_;
00445 };
00446
00447
00448
00449 class tgamestate_inspector::controller {
00450 public:
00451 typedef std::vector< boost::shared_ptr<single_mode_controller> > sm_controller_ptr_vector;
00452 controller(model &m)
00453 : model_(m)
00454 , sm_controllers_()
00455 {
00456 sm_controllers_.push_back(
00457 boost::shared_ptr<single_mode_controller>(new variable_mode_controller("variables",model_)));
00458 sm_controllers_.push_back(
00459 boost::shared_ptr<single_mode_controller>(new unit_mode_controller("units",model_)));
00460
00461 int sides = resources::teams
00462 ? static_cast<int>((*resources::teams).size())
00463 : 0;
00464 for( int side = 1; side<=sides; ++side) {
00465 std::string side_str = str_cast(side);
00466 sm_controllers_.push_back(boost::shared_ptr<single_mode_controller>(
00467 new team_mode_controller(std::string("team ")+side_str,model_,side)));
00468 }
00469 }
00470
00471 boost::shared_ptr<single_mode_controller> get_sm_controller()
00472 {
00473 int selected = model_.stuff_types_list->get_selected_row();
00474 if (selected==-1) {
00475
00476 selected=0;
00477 }
00478 return sm_controllers_.at(selected);
00479 }
00480
00481 void show_stuff_types_list()
00482 {
00483 model_.clear_stuff_types_list();
00484 foreach (boost::shared_ptr<single_mode_controller> sm_controller, sm_controllers_ ) {
00485 model_.add_row_to_stuff_types_list(sm_controller->name(),sm_controller->name());
00486 }
00487 }
00488
00489
00490 void show_title()
00491 {
00492 model_.inspector_name->set_label(model_.name);
00493 }
00494
00495
00496 void update_view_from_model()
00497 {
00498 boost::shared_ptr<single_mode_controller> c = get_sm_controller();
00499
00500 show_title();
00501 c->update_view_from_model();
00502 }
00503
00504
00505 void handle_stuff_list_item_clicked()
00506 {
00507 model_.set_inspect_window_text("");
00508 boost::shared_ptr<single_mode_controller> c = get_sm_controller();
00509 c->handle_stuff_list_selection();
00510 }
00511
00512
00513 void handle_stuff_types_list_item_clicked()
00514 {
00515 model_.clear_stuff_list();
00516 model_.set_inspect_window_text("");
00517 boost::shared_ptr<single_mode_controller> c = get_sm_controller();
00518 c->update_view_from_model();
00519 }
00520
00521
00522 private:
00523 model &model_;
00524 sm_controller_ptr_vector sm_controllers_;
00525 };
00526
00527
00528
00529 class tgamestate_inspector::view {
00530 public:
00531 view(const vconfig &cfg)
00532 : model_(cfg),controller_(model_)
00533 {
00534 }
00535
00536 void pre_show(CVideo& , twindow& window)
00537 {
00538 controller_.show_stuff_types_list();
00539 controller_.update_view_from_model();
00540 window.invalidate_layout();
00541 }
00542
00543
00544 void handle_stuff_list_item_clicked(twindow &window)
00545 {
00546 controller_.handle_stuff_list_item_clicked();
00547 window.invalidate_layout();
00548 }
00549
00550 void handle_stuff_types_list_item_clicked(twindow &window)
00551 {
00552 controller_.handle_stuff_types_list_item_clicked();
00553 window.invalidate_layout();
00554 }
00555
00556
00557 void bind(twindow &window)
00558 {
00559 model_.stuff_list = &find_widget<tlistbox>(&window, "stuff_list", false);
00560 model_.stuff_types_list = &find_widget<tlistbox>(&window, "stuff_types_list", false);
00561 model_.inspect = find_widget<tcontrol>(&window, "inspect", false,true);
00562 model_.inspector_name = &find_widget<tcontrol>(&window, "inspector_name", false);
00563
00564 #ifdef GUI2_EXPERIMENTAL_LISTBOX
00565 connect_signal_notify_modified(*model_.stuff_list, boost::bind(
00566 &tgamestate_inspector::view::handle_stuff_list_item_clicked
00567 , this
00568 , boost::ref(window)));
00569
00570 connect_signal_notify_modified(*model_.stuff_types_list, boost::bind(
00571 &tgamestate_inspector::view::handle_stuff_list_item_clicked
00572 , this
00573 , boost::ref(window)));
00574
00575 #else
00576 model_.stuff_list->set_callback_value_change(
00577 dialog_view_callback<tgamestate_inspector, tgamestate_inspector::view, &tgamestate_inspector::view::handle_stuff_list_item_clicked>);
00578
00579 model_.stuff_types_list->set_callback_value_change(
00580 dialog_view_callback<tgamestate_inspector, tgamestate_inspector::view, &tgamestate_inspector::view::handle_stuff_types_list_item_clicked>);
00581 #endif
00582
00583 }
00584
00585 private:
00586 model model_;
00587 controller controller_;
00588 };
00589
00590
00591 REGISTER_DIALOG(gamestate_inspector)
00592
00593 tgamestate_inspector::tgamestate_inspector(const vconfig &cfg)
00594 : view_()
00595 {
00596
00597 view_ = boost::shared_ptr<view>(new view(cfg));
00598 }
00599
00600 boost::shared_ptr<tgamestate_inspector::view> tgamestate_inspector::get_view()
00601 {
00602 return view_;
00603 }
00604
00605 void tgamestate_inspector::pre_show(CVideo& video, twindow& window)
00606 {
00607 view_->bind(window);
00608 view_->pre_show(video,window);
00609 }
00610
00611 }