00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #define GETTEXT_DOMAIN "wesnoth-lib"
00016
00017 #include "gui/dialogs/mp_change_control.hpp"
00018
00019 #include "gui/dialogs/helper.hpp"
00020 #include "gui/widgets/button.hpp"
00021 #ifdef GUI2_EXPERIMENTAL_LISTBOX
00022 #include "gui/widgets/list.hpp"
00023 #else
00024 #include "gui/widgets/listbox.hpp"
00025 #endif
00026 #include "gui/widgets/settings.hpp"
00027 #include "gui/widgets/window.hpp"
00028
00029 #include "formula_string_utils.hpp"
00030 #include "game_display.hpp"
00031 #include "game_preferences.hpp"
00032 #include "log.hpp"
00033 #include "marked-up_text.hpp"
00034 #include "resources.hpp"
00035 #include "team.hpp"
00036
00037 #include <vector>
00038 #include <boost/bind.hpp>
00039 #include <boost/shared_ptr.hpp>
00040
00041 static lg::log_domain log_gui("gui/dialogs/mp_change_control");
00042 #define ERR_GUI LOG_STREAM(err, log_gui)
00043 #define WRN_GUI LOG_STREAM(warn, log_gui)
00044 #define LOG_GUI LOG_STREAM(info, log_gui)
00045 #define DBG_GUI LOG_STREAM(debug, log_gui)
00046
00047 namespace gui2 {
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 template <class D, class V, void (V::*fptr)(twindow&)>
00069 void dialog_view_callback(twidget* caller)
00070 {
00071 D* dialog = dynamic_cast<D*>(caller->dialog());
00072 assert(dialog);
00073 twindow* window = dynamic_cast<twindow*>(caller->get_window());
00074 assert(window);
00075 (*(dialog->get_view()).*fptr)(*window);
00076 }
00077
00078
00079
00080
00081
00082 class tmp_change_control::model {
00083 public:
00084 model()
00085 : sides_list(NULL)
00086 , nicks_list(NULL)
00087 , sides()
00088 , nicks()
00089 {
00090 }
00091
00092 tlistbox *sides_list;
00093 tlistbox *nicks_list;
00094
00095
00096
00097 std::vector<int> sides;
00098
00099 std::vector<std::string> nicks;
00100
00101 void clear_sides()
00102 {
00103 DBG_GUI << "Sides list: clearing\n";
00104 sides_list->clear();
00105 sides.clear();
00106 }
00107
00108 void add_side(int side_num, const std::string &label)
00109 {
00110 sides.push_back(side_num);
00111 DBG_GUI << "Sides list: adding item (side_num: \"" << side_num
00112 << "\" label: \"" << label << "\")\n";
00113 std::map<std::string, string_map> data;
00114 string_map item;
00115 item["id"] = std::string("side_")+str_cast(side_num);
00116 item["label"] = label;
00117 item["use_markup"] = "true";
00118 data.insert(std::make_pair("side", item));
00119 sides_list->add_row(data);
00120 }
00121
00122 void clear_nicks()
00123 {
00124 DBG_GUI << "Nicks list: clearing\n";
00125 nicks_list->clear();
00126 nicks.clear();
00127 }
00128
00129 void add_nick(const std::string &nick, const std::string &label)
00130 {
00131 DBG_GUI << "Nicks list: adding item (nick: \"" << nick
00132 << "\" label: \"" << label << "\")\n";
00133 nicks.push_back(nick);
00134 std::map<std::string, string_map> data;
00135 string_map item;
00136 item["id"] = nick;
00137 item["label"] = label;
00138 item["use_markup"] = "true";
00139 data.insert(std::make_pair("nick", item));
00140 nicks_list->add_row(data);
00141 }
00142 };
00143
00144 class side_controller {
00145 public:
00146 side_controller(const std::string& name, tmp_change_control::model &m, int side_number)
00147 : model_(m), name_(name), side_number_(side_number)
00148 {
00149 }
00150
00151 ~side_controller()
00152 {
00153 }
00154
00155 std::string name() const
00156 {
00157 return name_;
00158 }
00159
00160 int side_number() const
00161 {
00162 return side_number_;
00163 }
00164
00165 void show_nicks_list()
00166 {
00167 DBG_GUI << "Nicks list: showing for side " << side_number_ << '\n';
00168
00169 model_.clear_nicks();
00170
00171 std::set<std::string> nicks;
00172 for (std::vector<team>::const_iterator it = resources::teams->begin();
00173 it != resources::teams->end(); ++it)
00174 {
00175 if (!it->is_ai() && it->controller()!=team::team_info::EMPTY && it->current_player().size()>0)
00176 nicks.insert(it->current_player());
00177 }
00178
00179 const std::set<std::string> &observers = resources::screen->observers();
00180
00181 nicks.insert(observers.begin(),observers.end());
00182 nicks.insert(preferences::login());
00183
00184
00185 int i = 0;
00186
00187 foreach (const std::string &nick, nicks)
00188 {
00189 if (side_number_ <= static_cast<int>(resources::teams->size()) &&
00190 resources::teams->at(side_number_-1).current_player() == nick)
00191 {
00192 std::string label_str = "<b>" + nick + "</b>";
00193 model_.add_nick(nick,label_str);
00194 model_.nicks_list->select_row(i);
00195 }
00196 else
00197 model_.add_nick(nick,nick);
00198 ++i;
00199 }
00200 }
00201 void handle_nicks_list_selection()
00202 {
00203 int selected = model_.nicks_list->get_selected_row();
00204 DBG_GUI << "Nicks list: row " << selected
00205 << " selected, it contains " << model_.nicks[selected] << '\n';
00206 }
00207 void update_view_from_model()
00208 {
00209 show_nicks_list();
00210 }
00211
00212 private:
00213 tmp_change_control::model &model_;
00214 std::string const name_;
00215 int side_number_;
00216 };
00217
00218
00219
00220
00221
00222
00223
00224 class tmp_change_control::controller {
00225 public:
00226 typedef std::vector< boost::shared_ptr<side_controller> > side_controller_ptr_vector;
00227 controller(model &m)
00228 : model_(m)
00229 , side_controllers_()
00230 {
00231 }
00232
00233 void show_sides_list()
00234 {
00235 DBG_GUI << "Sides list: filling\n";
00236 model_.clear_sides();
00237 int sides = resources::teams ? static_cast<int>((*resources::teams).size()) : 0;
00238 for( int side = 1; side<=sides; ++side)
00239 {
00240 if (!resources::teams->at(side-1).hidden())
00241 {
00242 string_map symbols;
00243 symbols["side"] = str_cast(side);
00244 std::string side_str = vgettext("Side $side", symbols);
00245 side_str = font::span_color(team::get_side_color(side)) + side_str + "</span>";
00246 model_.add_side(side,side_str);
00247 side_controllers_.push_back(boost::shared_ptr<side_controller>(
00248 new side_controller(side_str,model_,side)));
00249 }
00250 }
00251 }
00252
00253 boost::shared_ptr<side_controller> get_side_controller()
00254 {
00255 int selected = model_.sides_list->get_selected_row();
00256 if (selected < 0 || selected >= static_cast<int>(side_controllers_.size()))
00257 return boost::shared_ptr<side_controller>();
00258 else
00259 return side_controllers_.at(selected);
00260 }
00261
00262 void handle_sides_list_item_clicked()
00263 {
00264 int selected = model_.sides_list->get_selected_row();
00265 DBG_GUI << "Sides list: selected row: " << selected
00266 << " for side " << model_.sides[selected] << '\n';
00267 if (get_side_controller())
00268 get_side_controller()->update_view_from_model();
00269 }
00270
00271 void handle_nicks_list_item_clicked()
00272 {
00273 int selected = model_.sides_list->get_selected_row();
00274 DBG_GUI << "Nicks list: selected row: " << selected
00275 << " with nick " << model_.nicks[selected] << '\n';
00276 if (get_side_controller())
00277 get_side_controller()->handle_nicks_list_selection();
00278 }
00279
00280 void update_view_from_model()
00281 {
00282 if (get_side_controller())
00283 get_side_controller()->update_view_from_model();
00284 }
00285
00286 void change_control(events::menu_handler *mh)
00287 {
00288 int selected_side = model_.sides_list->get_selected_row();
00289 int selected_nick = model_.nicks_list->get_selected_row();
00290 DBG_GUI << "Main: changing control of side " << model_.sides[selected_side]
00291 << " to nick " << model_.nicks[selected_nick] << '\n';
00292 if (mh)
00293 mh->request_control_change(model_.sides[selected_side], model_.nicks[selected_nick]);
00294 }
00295
00296 private:
00297 model &model_;
00298 side_controller_ptr_vector side_controllers_;
00299 };
00300
00301
00302
00303
00304
00305
00306 class tmp_change_control::view {
00307 public:
00308 view()
00309 : model_(),controller_(model_)
00310 {
00311 }
00312
00313 void pre_show(CVideo &, twindow &window)
00314 {
00315 model_.clear_sides();
00316 controller_.show_sides_list();
00317 model_.clear_nicks();
00318 controller_.update_view_from_model();
00319 window.invalidate_layout();
00320 }
00321
00322 void handle_sides_list_item_clicked(twindow &window)
00323 {
00324 controller_.handle_sides_list_item_clicked();
00325 window.invalidate_layout();
00326 }
00327
00328 void handle_nicks_list_item_clicked(twindow &window)
00329 {
00330 controller_.handle_nicks_list_item_clicked();
00331 window.invalidate_layout();
00332 }
00333
00334 void bind(twindow &window)
00335 {
00336 DBG_GUI << "Main: Binding widgets and callbacks\n";
00337 model_.sides_list = &find_widget<tlistbox>(&window, "sides_list", false);
00338 model_.nicks_list = &find_widget<tlistbox>(&window, "nicks_list", false);
00339
00340 #ifdef GUI2_EXPERIMENTAL_LISTBOX
00341 connect_signal_notify_modified(*model_.sides_list, boost::bind(
00342 &tmp_change_control::view::handle_sides_list_item_clicked
00343 , this
00344 , boost::ref(window)));
00345
00346 connect_signal_notify_modified(*model_.nicks_list, boost::bind(
00347 &tmp_change_control::view::handle_nicks_list_item_clicked
00348 , this
00349 , boost::ref(window)));
00350 #else
00351 model_.sides_list->set_callback_value_change(
00352 dialog_view_callback<tmp_change_control, tmp_change_control::view, &tmp_change_control::view::handle_sides_list_item_clicked>);
00353
00354 model_.nicks_list->set_callback_value_change(
00355 dialog_view_callback<tmp_change_control, tmp_change_control::view, &tmp_change_control::view::handle_nicks_list_item_clicked>);
00356 #endif
00357 }
00358
00359 void post_show(int retval, events::menu_handler *mh)
00360 {
00361 if (retval == twindow::OK)
00362 {
00363 controller_.change_control(mh);
00364 }
00365 }
00366
00367 private:
00368 model model_;
00369 controller controller_;
00370 };
00371
00372 REGISTER_DIALOG(mp_change_control)
00373
00374 tmp_change_control::tmp_change_control(events::menu_handler *mh)
00375 : menu_handler_(mh), view_()
00376 {
00377 view_ = boost::shared_ptr<view>(new view());
00378 }
00379
00380 boost::shared_ptr<tmp_change_control::view> tmp_change_control::get_view()
00381 {
00382 return view_;
00383 }
00384
00385 void tmp_change_control::pre_show(CVideo& video, twindow& window)
00386 {
00387 view_->bind(window);
00388 view_->pre_show(video,window);
00389 }
00390
00391 void tmp_change_control::post_show(twindow& )
00392 {
00393 view_->post_show(get_retval(), menu_handler_);
00394 }
00395
00396 }