00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifdef GUI2_EXPERIMENTAL_LISTBOX
00017
00018 #define GETTEXT_DOMAIN "wesnoth-lib"
00019
00020 #include "gui/widgets/list.hpp"
00021
00022 #include "foreach.hpp"
00023 #include "gui/auxiliary/log.hpp"
00024 #include "gui/auxiliary/widget_definition/listbox.hpp"
00025 #include "gui/auxiliary/window_builder/listbox.hpp"
00026 #include "gui/widgets/selectable.hpp"
00027 #include "gui/widgets/settings.hpp"
00028 #include "gui/widgets/window.hpp"
00029
00030 #include <boost/bind.hpp>
00031
00032 #define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
00033 #define LOG_HEADER LOG_SCOPE_HEADER + ':'
00034
00035 namespace gui2 {
00036
00037 #ifdef GUI2_EXPERIMENTAL_LISTBOX
00038 REGISTER_WIDGET(listbox)
00039 #endif
00040
00041 tlist::tlist(const bool has_minimum
00042 , const bool has_maximum
00043 , const tgenerator_::tplacement placement
00044 , const bool select
00045 , const tbuilder_grid_const_ptr list_builder)
00046 : tcontainer_(2)
00047 , state_(ENABLED)
00048 , generator_(NULL)
00049 , list_builder_(list_builder)
00050 , need_layout_(false)
00051 {
00052 assert(list_builder);
00053
00054 generator_ = tgenerator_::build(
00055 has_minimum, has_maximum, placement, select);
00056 assert(generator_);
00057
00058 connect_signal<event::LEFT_BUTTON_DOWN>(
00059 boost::bind(
00060 &tlist::signal_handler_left_button_down
00061 , this
00062 , _2)
00063 , event::tdispatcher::back_pre_child);
00064
00065 connect_signal<event::SDL_KEY_DOWN>(
00066 boost::bind(
00067 &tlist::signal_handler_sdl_key_down
00068 , this
00069 , _2
00070 , _3
00071 , _5
00072 , _6));
00073
00074 connect_signal<event::SDL_KEY_DOWN>(
00075 boost::bind(
00076 &tlist::signal_handler_sdl_key_down
00077 , this
00078 , _2
00079 , _3
00080 , _5
00081 , _6)
00082 , event::tdispatcher::back_pre_child);
00083 }
00084
00085 void tlist::add_row(const string_map& item, const int index)
00086 {
00087 std::map<std::string, string_map> data;
00088
00089 data.insert(std::make_pair("", item));
00090 add_row(data, index);
00091 }
00092
00093 void tlist::add_row(
00094 const std::map<std::string /* widget id */, string_map>& data
00095 , const int index)
00096 {
00097 assert(generator_);
00098 tgrid& grid =
00099 generator_->create_item(index, list_builder_, data, NULL);
00100
00101 tselectable_* selectable =
00102 find_widget<tselectable_>(&grid, "_toggle", false, false);
00103
00104 if(selectable) {
00105 dynamic_cast<twidget&>(*selectable).
00106 connect_signal<event::LEFT_BUTTON_CLICK>(
00107 boost::bind(
00108 &tlist::signal_handler_pre_child_left_button_click
00109 , this
00110 , &grid
00111 , _2
00112 , _3
00113 , _4)
00114 , event::tdispatcher::back_pre_child);
00115
00116
00117 dynamic_cast<twidget&>(*selectable).
00118 connect_signal<event::LEFT_BUTTON_CLICK>(
00119 boost::bind(
00120 &tlist::signal_handler_left_button_click
00121 , this
00122 , &grid
00123 , _2)
00124 , event::tdispatcher::back_post_child);
00125
00126
00127 dynamic_cast<twidget&>(*selectable).
00128 connect_signal<event::LEFT_BUTTON_CLICK>(
00129 boost::bind(
00130 &tlist::signal_handler_left_button_click
00131 , this
00132 , &grid
00133 , _2)
00134 , event::tdispatcher::back_child);
00135 }
00136 }
00137
00138 void tlist::append_rows(const std::vector<string_map>& items)
00139 {
00140 foreach(const string_map& item, items) {
00141 add_row(item);
00142 }
00143 }
00144
00145 void tlist::remove_row(const unsigned row, unsigned count)
00146 {
00147 assert(generator_);
00148
00149 if(row >= get_item_count()) {
00150 return;
00151 }
00152
00153 if(!count || count > get_item_count()) {
00154 count = get_item_count();
00155 }
00156
00157 unsigned height_reduced = 0;
00158 for(; count; --count) {
00159 if(generator_->item(row).get_visible() != INVISIBLE) {
00160 height_reduced += generator_->item(row).get_height();
00161 }
00162 generator_->delete_item(row);
00163 }
00164
00165 if(height_reduced != 0) {
00166
00167 }
00168 }
00169
00170 void tlist::clear()
00171 {
00172
00173
00174 remove_row(0, 0);
00175 }
00176
00177 unsigned tlist::get_item_count() const
00178 {
00179 assert(generator_);
00180 return generator_->get_item_count();
00181 }
00182
00183 void tlist::set_row_active(const unsigned row, const bool active)
00184 {
00185 assert(generator_);
00186 generator_->item(row).set_active(active);
00187 }
00188
00189 void tlist::set_row_shown(const unsigned row, const bool shown)
00190 {
00191 assert(generator_);
00192
00193 twindow *window = get_window();
00194 assert(window);
00195
00196 const int selected_row = get_selected_row();
00197
00198 bool resize_needed;
00199 {
00200 twindow::tinvalidate_layout_blocker invalidate_layout_blocker(*window);
00201
00202 generator_->set_item_shown(row, shown);
00203 generator_->place(generator_->get_origin()
00204 , generator_->calculate_best_size());
00205
00206 }
00207
00208 if(resize_needed) {
00209 window->invalidate_layout();
00210 } else {
00211
00212 set_dirty();
00213 }
00214
00215 if(selected_row != get_selected_row()) {
00216 fire(event::NOTIFY_MODIFIED, *this, NULL);
00217 }
00218 }
00219
00220 void tlist::set_row_shown(const std::vector<bool>& shown)
00221 {
00222 assert(generator_);
00223 assert(shown.size() == get_item_count());
00224
00225 twindow *window = get_window();
00226 assert(window);
00227
00228 const int selected_row = get_selected_row();
00229
00230 bool resize_needed;
00231 {
00232 twindow::tinvalidate_layout_blocker invalidate_layout_blocker(*window);
00233
00234 for(size_t i = 0; i < shown.size(); ++i) {
00235 generator_->set_item_shown(i, shown[i]);
00236 }
00237 generator_->place(generator_->get_origin()
00238 , generator_->calculate_best_size());
00239
00240 }
00241
00242 if(resize_needed) {
00243 window->invalidate_layout();
00244 } else {
00245
00246 set_dirty();
00247 }
00248
00249 if(selected_row != get_selected_row()) {
00250 fire(event::NOTIFY_MODIFIED, *this, NULL);
00251 }
00252 }
00253
00254 const tgrid* tlist::get_row_grid(const unsigned row) const
00255 {
00256 assert(generator_);
00257
00258 return &generator_->item(row);
00259 }
00260
00261 tgrid* tlist::get_row_grid(const unsigned row)
00262 {
00263 assert(generator_);
00264 return &generator_->item(row);
00265 }
00266
00267 bool tlist::select_row(const unsigned row, const bool select)
00268 {
00269 assert(generator_);
00270
00271 generator_->select_item(row, select);
00272
00273 return true;
00274 }
00275
00276 int tlist::get_selected_row() const
00277 {
00278 assert(generator_);
00279
00280 return generator_->get_selected_item();
00281 }
00282
00283 void tlist::place(const tpoint& origin, const tpoint& size)
00284 {
00285
00286 tcontainer_::place(origin, size);
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 const int selected_item = generator_->get_selected_item();
00297 if(selected_item != -1) {
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307 }
00308 }
00309 #if 0
00310 void tlist::resize_content(
00311 const int width_modification
00312 , const int height_modification)
00313 {
00314 DBG_GUI_L << LOG_HEADER << " current size " << content_grid()->get_size()
00315 << " width_modification " << width_modification
00316 << " height_modification " << height_modification
00317 << ".\n";
00318
00319 if(content_resize_request(width_modification, height_modification)) {
00320
00321
00322 tpoint size = content_grid()->get_size();
00323 size.x += width_modification;
00324 size.y += height_modification;
00325
00326
00327 content_grid()->set_size(size);
00328
00329
00330 need_layout_ = true;
00331
00332 if(width_modification < 0 || height_modification < 0) {
00333 set_dirty();
00334 }
00335 DBG_GUI_L << LOG_HEADER << " succeeded.\n";
00336 } else {
00337 DBG_GUI_L << LOG_HEADER << " failed.\n";
00338 }
00339 }
00340 #endif
00341
00342 void tlist::init()
00343 {
00344 init_grid(cast<tlistbox_definition::tresolution>(config()).grid);
00345
00346 set_single_child(
00347 find_widget<tgrid>(&grid(), "_list_grid", false)
00348 , generator_);
00349
00350
00351
00352
00353
00354 tgrid* g = find_widget<tgrid>(&grid(), "_header_grid", false, false);
00355 if(g) g->set_visible(twidget::INVISIBLE);
00356
00357 g = find_widget<tgrid>(&grid(), "_footer_grid", false, false);
00358 if(g) g->set_visible(twidget::INVISIBLE);
00359
00360 g = find_widget<tgrid>(&grid(), "_vertical_scrollbar_grid", false, false);
00361 if(g) g->set_visible(twidget::INVISIBLE);
00362
00363 g = find_widget<tgrid>(&grid(), "_horizontal_scrollbar_grid", false, false);
00364 if(g) g->set_visible(twidget::INVISIBLE);
00365
00366 }
00367
00368 void tlist::layout_children(const bool force)
00369 {
00370 if(need_layout_ || force) {
00371 grid().place(grid().get_origin(), grid().get_size());
00372
00373
00374
00375
00376 need_layout_ = false;
00377 set_dirty();
00378 }
00379 }
00380
00381 const std::string& tlist::get_control_type() const
00382 {
00383 static const std::string type = "list";
00384 return type;
00385 }
00386
00387 void tlist::signal_handler_left_button_down(const event::tevent event)
00388 {
00389 DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
00390
00391 assert(get_window());
00392 get_window()->keyboard_capture(this);
00393 }
00394
00395 void tlist::signal_handler_pre_child_left_button_click(
00396 tgrid* grid
00397 , const event::tevent event
00398 , bool& handled
00399 , bool& halt)
00400 {
00401 DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
00402
00403 assert(grid);
00404 assert(generator_);
00405
00406 for(size_t i = 0; i < generator_->get_item_count(); ++i) {
00407 if(&generator_->item(i) == grid) {
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421 if(generator_->is_selected(i)) {
00422 halt = true;
00423 handled = true;
00424 }
00425 return;
00426 }
00427 }
00428 assert(false);
00429 }
00430
00431 void tlist::signal_handler_left_button_click(
00432 tgrid* grid
00433 , const event::tevent event)
00434 {
00435 DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
00436 assert(grid);
00437 assert(generator_);
00438
00439
00440 for(size_t i = 0; i < generator_->get_item_count(); ++i) {
00441 if(&generator_->item(i) == grid) {
00442 generator_->select_item(i);
00443 fire(event::NOTIFY_MODIFIED, *this, NULL);
00444 }
00445 }
00446 }
00447
00448 void tlist::signal_handler_sdl_key_down(const event::tevent event
00449 , bool& handled
00450 , const SDLKey key
00451 , SDLMod modifier)
00452 {
00453 DBG_GUI_E << LOG_HEADER << ' ' << event << ".\n";
00454
00455 if(handled) {
00456 return;
00457 }
00458
00459 switch(key) {
00460 case SDLK_UP :
00461 generator_->handle_key_up_arrow(modifier, handled);
00462 break;
00463 case SDLK_DOWN :
00464 generator_->handle_key_down_arrow(modifier, handled);
00465 break;
00466 case SDLK_LEFT :
00467 generator_->handle_key_left_arrow(modifier, handled);
00468 break;
00469 case SDLK_RIGHT :
00470 generator_->handle_key_right_arrow(modifier, handled);
00471 break;
00472 default : ;
00473
00474 }
00475 if(handled) {
00476 fire(event::NOTIFY_MODIFIED, *this, NULL);
00477 }
00478 }
00479
00480 }
00481
00482 #endif