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/widgets/generator_private.hpp"
00019
00020 #include "gui/widgets/window.hpp"
00021
00022 namespace gui2 {
00023
00024 namespace policy {
00025
00026
00027
00028 namespace minimum_selection {
00029
00030 void tone::set_item_shown(const unsigned index, const bool show)
00031 {
00032 if(show && get_selected_item_count() == 0) {
00033 do_select_item(index);
00034 } else if(!show && is_selected(index)) {
00035 do_deselect_item(index);
00036
00037 for(unsigned i = index + 1; i < get_item_count(); ++i) {
00038 if(get_item_shown(i)) {
00039 do_select_item(i);
00040 break;
00041 }
00042 }
00043 }
00044 }
00045
00046 void tone::create_item(const unsigned index)
00047 {
00048 if(get_selected_item_count() == 0) {
00049 do_select_item(index);
00050 }
00051 }
00052
00053 bool tone::deselect_item(const unsigned index)
00054 {
00055 if(get_selected_item_count() > 1) {
00056 do_deselect_item(index);
00057 return true;
00058 }
00059 return false;
00060 }
00061
00062 void tone::delete_item(const unsigned index)
00063 {
00064
00065
00066 if(is_selected(index)) {
00067 do_deselect_item(index);
00068
00069 if(get_selected_item_count() == 0) {
00070
00071
00072 const unsigned item_count = get_item_count();
00073 if(item_count > 1) {
00074
00075 if(index == item_count - 1) {
00076
00077 do_select_item(index - 1);
00078 } else {
00079
00080 do_select_item(index + 1);
00081 }
00082 }
00083 }
00084 }
00085 }
00086
00087 void tnone::set_item_shown(const unsigned index, const bool show)
00088 {
00089 if(!show && is_selected(index)) {
00090 do_deselect_item(index);
00091 }
00092 }
00093
00094 }
00095
00096
00097
00098 namespace placement {
00099
00100 thorizontal_list::thorizontal_list()
00101 : placed_(false)
00102 {
00103 }
00104
00105 void thorizontal_list::create_item(const unsigned )
00106 {
00107 if(!placed_) {
00108 return;
00109 }
00110
00111
00112 assert(false);
00113 }
00114
00115 tpoint thorizontal_list::calculate_best_size() const
00116 {
00117
00118 tpoint result(0, 0);
00119 for(size_t i = 0; i < get_item_count(); ++i) {
00120
00121 const tgrid& grid = item(i);
00122 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00123 continue;
00124 }
00125
00126 const tpoint best_size = grid.get_best_size();
00127
00128 result.x += best_size.x;
00129
00130 if(best_size.y > result.y) {
00131 result.y = best_size.y;
00132 }
00133 }
00134
00135 return result;
00136 }
00137
00138 void thorizontal_list::place(const tpoint& origin, const tpoint& size)
00139 {
00140
00141
00142
00143
00144
00145
00146
00147
00148 tpoint current_origin = origin;
00149 for(size_t i = 0; i < get_item_count(); ++i) {
00150
00151 tgrid& grid = item(i);
00152 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00153 continue;
00154 }
00155
00156 tpoint best_size = grid.get_best_size();
00157 assert(best_size.y <= size.y);
00158
00159 best_size.y = size.y;
00160
00161 grid.place(current_origin, best_size);
00162
00163 current_origin.x += best_size.x;
00164 }
00165
00166 assert(current_origin.x == origin.x + size.x);
00167 }
00168
00169 void thorizontal_list::set_origin(const tpoint& origin)
00170 {
00171 tpoint current_origin = origin;
00172 for(size_t i = 0; i < get_item_count(); ++i) {
00173
00174 tgrid& grid = item(i);
00175 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00176 continue;
00177 }
00178
00179 grid.set_origin(current_origin);
00180 current_origin.x += grid.get_width();
00181 }
00182 }
00183
00184 void thorizontal_list::set_visible_area(const SDL_Rect& area)
00185 {
00186
00187
00188
00189
00190
00191
00192 for(size_t i = 0; i < get_item_count(); ++i) {
00193
00194 tgrid& grid = item(i);
00195 grid.set_visible_area(area);
00196 }
00197 }
00198
00199 twidget* thorizontal_list::find_at(
00200 const tpoint& coordinate, const bool must_be_active)
00201 {
00202 assert(get_window());
00203
00204 for(size_t i = 0; i < get_item_count(); ++i) {
00205
00206 tgrid& grid = item(i);
00207 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00208 continue;
00209 }
00210
00211 twidget* widget =
00212 grid.find_at(coordinate, must_be_active);
00213
00214 if(widget) {
00215 return widget;
00216 }
00217 }
00218 return NULL;
00219 }
00220
00221 const twidget* thorizontal_list::find_at(const tpoint& coordinate,
00222 const bool must_be_active) const
00223 {
00224 assert(get_window());
00225
00226 for(size_t i = 0; i < get_item_count(); ++i) {
00227
00228 const tgrid& grid = item(i);
00229 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00230 continue;
00231 }
00232
00233 const twidget* widget =
00234 grid.find_at(coordinate, must_be_active);
00235
00236 if(widget) {
00237 return widget;
00238 }
00239 }
00240 return NULL;
00241 }
00242
00243 void thorizontal_list::handle_key_left_arrow(
00244 SDLMod , bool& handled)
00245 {
00246 if(get_selected_item_count() == 0) {
00247 return;
00248 }
00249
00250
00251 handled = true;
00252
00253 for(int i = get_selected_item() - 1; i >= 0; --i) {
00254
00255
00256
00257 tcontrol* control = dynamic_cast<tcontrol*>(item(i).widget(0, 0));
00258 if(control && control->get_active()) {
00259 select_item(i);
00260 return;
00261 }
00262 }
00263 }
00264
00265 void thorizontal_list::handle_key_right_arrow(
00266 SDLMod , bool& handled)
00267 {
00268 if(get_selected_item_count() == 0) {
00269 return;
00270 }
00271
00272
00273 handled = true;
00274
00275 for(size_t i = get_selected_item() + 1; i < get_item_count(); ++i) {
00276
00277 if(item(i).get_visible() == twidget::INVISIBLE
00278 || !get_item_shown(i)) {
00279
00280 continue;
00281 }
00282
00283
00284
00285 tcontrol* control = dynamic_cast<tcontrol*>(item(i).widget(0, 0));
00286 if(control && control->get_active()) {
00287 select_item(i);
00288 return;
00289 }
00290 }
00291 }
00292
00293 tvertical_list::tvertical_list()
00294 : placed_(false)
00295 {
00296 }
00297
00298 void tvertical_list::create_item(const unsigned )
00299 {
00300 if(!placed_) {
00301 return;
00302 }
00303
00304
00305 assert(false);
00306 }
00307
00308 tpoint tvertical_list::calculate_best_size() const
00309 {
00310
00311 tpoint result(0, 0);
00312 for(size_t i = 0; i < get_item_count(); ++i) {
00313
00314 const tgrid& grid = item(i);
00315 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00316 continue;
00317 }
00318
00319 const tpoint best_size = grid.get_best_size();
00320
00321 if(best_size.x > result.x) {
00322 result.x = best_size.x;
00323 }
00324
00325 result.y += best_size.y;
00326 }
00327
00328 return result;
00329 }
00330
00331 void tvertical_list::place(const tpoint& origin, const tpoint& size)
00332 {
00333
00334
00335
00336
00337
00338
00339
00340
00341 tpoint current_origin = origin;
00342 for(size_t i = 0; i < get_item_count(); ++i) {
00343
00344 tgrid& grid = item(i);
00345 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00346 continue;
00347 }
00348
00349 tpoint best_size = grid.get_best_size();
00350 assert(best_size.x <= size.x);
00351
00352 best_size.x = size.x;
00353
00354 grid.place(current_origin, best_size);
00355
00356 current_origin.y += best_size.y;
00357 }
00358
00359 assert(current_origin.y == origin.y + size.y);
00360 }
00361
00362 void tvertical_list::set_origin(const tpoint& origin)
00363 {
00364 tpoint current_origin = origin;
00365 for(size_t i = 0; i < get_item_count(); ++i) {
00366
00367 tgrid& grid = item(i);
00368 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00369 continue;
00370 }
00371
00372 grid.set_origin(current_origin);
00373 current_origin.y += grid.get_height();
00374 }
00375 }
00376
00377 void tvertical_list::set_visible_area(const SDL_Rect& area)
00378 {
00379
00380
00381
00382
00383
00384
00385 for(size_t i = 0; i < get_item_count(); ++i) {
00386
00387 tgrid& grid = item(i);
00388 grid.set_visible_area(area);
00389 }
00390 }
00391
00392 twidget* tvertical_list::find_at(
00393 const tpoint& coordinate, const bool must_be_active)
00394 {
00395 assert(get_window());
00396
00397 for(size_t i = 0; i < get_item_count(); ++i) {
00398
00399 tgrid& grid = item(i);
00400 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00401 continue;
00402 }
00403
00404
00405 twidget* widget =
00406 grid.find_at(coordinate, must_be_active);
00407
00408 if(widget) {
00409 return widget;
00410 }
00411 }
00412 return NULL;
00413 }
00414
00415 const twidget* tvertical_list::find_at(const tpoint& coordinate,
00416 const bool must_be_active) const
00417 {
00418 assert(get_window());
00419
00420 for(size_t i = 0; i < get_item_count(); ++i) {
00421
00422 const tgrid& grid = item(i);
00423 if(grid.get_visible() == twidget::INVISIBLE || !get_item_shown(i)) {
00424 continue;
00425 }
00426
00427 const twidget* widget =
00428 grid.find_at(coordinate, must_be_active);
00429
00430 if(widget) {
00431 return widget;
00432 }
00433 }
00434 return NULL;
00435 }
00436
00437 void tvertical_list::handle_key_up_arrow(SDLMod , bool& handled)
00438 {
00439 if(get_selected_item_count() == 0) {
00440 return;
00441 }
00442
00443
00444 handled = true;
00445
00446 for(int i = get_selected_item() - 1; i >= 0; --i) {
00447
00448
00449
00450 tcontrol* control = dynamic_cast<tcontrol*>(item(i).widget(0, 0));
00451 if(control && control->get_active()) {
00452 select_item(i);
00453 return;
00454 }
00455 }
00456 }
00457
00458 void tvertical_list::handle_key_down_arrow(SDLMod , bool& handled)
00459 {
00460 if(get_selected_item_count() == 0) {
00461 return;
00462 }
00463
00464
00465 handled = true;
00466
00467 for(size_t i = get_selected_item() + 1; i < get_item_count(); ++i) {
00468
00469 if(item(i).get_visible() == twidget::INVISIBLE
00470 || !get_item_shown(i)) {
00471
00472 continue;
00473 }
00474
00475
00476
00477 tcontrol* control = dynamic_cast<tcontrol*>(item(i).widget(0, 0));
00478 if(control && control->get_active()) {
00479 select_item(i);
00480 return;
00481 }
00482 }
00483 }
00484
00485 void tindependent::request_reduce_width(const unsigned maximum_width)
00486 {
00487 for(size_t i = 0; i < get_item_count(); ++i) {
00488
00489 tgrid& grid = item(i);
00490 grid.request_reduce_width(maximum_width);
00491 }
00492 }
00493
00494 void tindependent::request_reduce_height(const unsigned maximum_height)
00495 {
00496 for(size_t i = 0; i < get_item_count(); ++i) {
00497
00498 tgrid& grid = item(i);
00499 grid.request_reduce_height(maximum_height);
00500 }
00501 }
00502
00503 tpoint tindependent::calculate_best_size() const
00504 {
00505
00506
00507
00508
00509 tpoint result(0, 0);
00510 for(size_t i = 0; i < get_item_count(); ++i) {
00511
00512 const tgrid& grid = item(i);
00513
00514 const tpoint best_size = grid.get_best_size();
00515
00516 if(best_size.x > result.x) {
00517 result.x = best_size.x;
00518 }
00519
00520 if(best_size.y > result.y) {
00521 result.y = best_size.y;
00522 }
00523 }
00524
00525 return result;
00526 }
00527
00528 void tindependent::place(const tpoint& origin, const tpoint& size)
00529 {
00530 for(size_t i = 0; i < get_item_count(); ++i) {
00531
00532 tgrid& grid = item(i);
00533 grid.place(origin, size);
00534 }
00535 }
00536
00537 void tindependent::set_origin(const tpoint& origin)
00538 {
00539
00540
00541
00542
00543
00544
00545 for(size_t i = 0; i < get_item_count(); ++i) {
00546
00547 tgrid& grid = item(i);
00548 grid.set_origin(origin);
00549 }
00550 }
00551
00552 twidget* tindependent::find_at(const tpoint& coordinate
00553 , const bool must_be_active)
00554 {
00555 assert(get_window());
00556
00557 const int selected_item = get_selected_item();
00558 if(selected_item < 0) {
00559 return NULL;
00560 }
00561
00562 tgrid& grid = item(selected_item);
00563 return grid.find_at(coordinate, must_be_active);
00564 }
00565
00566 const twidget* tindependent::find_at(const tpoint& coordinate
00567 , const bool must_be_active) const
00568 {
00569 assert(get_window());
00570
00571 const int selected_item = get_selected_item();
00572 if(selected_item < 0) {
00573 return NULL;
00574 }
00575
00576 const tgrid& grid = item(selected_item);
00577 return grid.find_at(coordinate, must_be_active);
00578 }
00579
00580 twidget* tindependent::find(
00581 const std::string& id, const bool must_be_active)
00582 {
00583 for(size_t i = 0; i < get_item_count(); ++i) {
00584 if(is_selected(i)) {
00585 if(twidget* widget = item(i).find(id, must_be_active)) {
00586 return widget;
00587 }
00588 }
00589 }
00590 return NULL;
00591 }
00592
00593 const twidget* tindependent::find(
00594 const std::string& id, const bool must_be_active) const
00595 {
00596 for(size_t i = 0; i < get_item_count(); ++i) {
00597 if(is_selected(i)) {
00598 if(const twidget* widget =
00599 item(i).find(id, must_be_active)) {
00600
00601 return widget;
00602 }
00603 }
00604 }
00605 return NULL;
00606 }
00607
00608 void tindependent::set_visible_area(const SDL_Rect& area)
00609 {
00610
00611
00612
00613
00614
00615
00616 for(size_t i = 0; i < get_item_count(); ++i) {
00617
00618 tgrid& grid = item(i);
00619 grid.set_visible_area(area);
00620 }
00621 }
00622
00623 }
00624
00625
00626
00627 namespace select_action {
00628
00629 void tselect::select(tgrid& grid, const bool select)
00630 {
00631 tselectable_* selectable =
00632 dynamic_cast<tselectable_*>(grid.widget(0, 0));
00633 assert(selectable);
00634
00635 selectable->set_value(select);
00636 }
00637
00638 void tselect::init(tgrid* grid
00639 , const std::map<std::string /* widget id */, string_map>& data
00640 , void (*callback)(twidget*))
00641 {
00642 for(unsigned row = 0; row < grid->get_rows(); ++row) {
00643 for(unsigned col = 0; col < grid->get_cols(); ++col) {
00644 twidget* widget = grid->widget(row, col);
00645 assert(widget);
00646
00647 tgrid* child_grid = dynamic_cast<tgrid*>(widget);
00648 ttoggle_button* btn = dynamic_cast<ttoggle_button*>(widget);
00649 ttoggle_panel* panel = dynamic_cast<ttoggle_panel*>(widget);
00650
00651 if(btn) {
00652 btn->set_callback_state_change(callback);
00653 std::map<std::string, string_map>::const_iterator itor =
00654 data.find(btn->id());
00655
00656 if(itor == data.end()) {
00657 itor = data.find("");
00658 }
00659 if(itor != data.end()) {
00660 btn->set_members(itor->second);
00661 }
00662 } else if(panel) {
00663 panel->set_callback_state_change(callback);
00664 panel->set_child_members(data);
00665 } else if(child_grid) {
00666 init(child_grid, data, callback);
00667 } else {
00668 VALIDATE(false, "Only toggle buttons and panels are allowed as the cells of a list definition.");
00669 }
00670 }
00671 }
00672 }
00673
00674 void tshow::init(tgrid* grid
00675 , const std::map<std::string /* widget id */, string_map>& data
00676 , void (*callback)(twidget*))
00677 {
00678 assert(!callback);
00679
00680 typedef std::pair<std::string, string_map> hack;
00681 foreach(const hack& item, data) {
00682 if(item.first.empty()) {
00683 for(unsigned row = 0; row < grid->get_rows(); ++row) {
00684 for(unsigned col = 0; col < grid->get_cols(); ++col) {
00685 if(tcontrol* control =
00686 dynamic_cast<tcontrol*>(grid->widget(row, col))) {
00687
00688 control->set_members(item.second);
00689 }
00690 }
00691 }
00692 } else {
00693 tcontrol* control = dynamic_cast<
00694 tcontrol*>(grid->find(item.first, false));
00695 if(control) {
00696 control->set_members(item.second);
00697 }
00698 }
00699 }
00700 }
00701
00702 }
00703
00704 }
00705
00706
00707
00708 #ifdef GENERATE_PLACEMENT
00709 char compile_assert[0];
00710 #else
00711 #define GENERATE_PLACEMENT \
00712 switch(placement) { \
00713 case tgenerator_::horizontal_list : \
00714 result = new tgenerator \
00715 < minimum \
00716 , maximum \
00717 , policy::placement::thorizontal_list \
00718 , select \
00719 >; \
00720 break; \
00721 case tgenerator_::vertical_list : \
00722 result = new tgenerator \
00723 < minimum \
00724 , maximum \
00725 , policy::placement::tvertical_list \
00726 , select \
00727 >; \
00728 break; \
00729 case tgenerator_::grid : \
00730 result = new tgenerator \
00731 < minimum \
00732 , maximum \
00733 , policy::placement::tmatrix \
00734 , select \
00735 >; \
00736 break; \
00737 case tgenerator_::independent : \
00738 result = new tgenerator \
00739 < minimum \
00740 , maximum \
00741 , policy::placement::tindependent \
00742 , select \
00743 >; \
00744 break; \
00745 default: \
00746 assert(false); \
00747 }
00748 #endif
00749
00750 #ifdef GENERATE_SELECT
00751 char compile_assert[0];
00752 #else
00753 #define GENERATE_SELECT \
00754 if(select) { \
00755 typedef policy::select_action::tselect select; \
00756 GENERATE_PLACEMENT \
00757 } else { \
00758 typedef policy::select_action::tshow select; \
00759 GENERATE_PLACEMENT \
00760 }
00761 #endif
00762
00763 #ifdef GENERATE_MAXIMUM
00764 char compile_assert[0];
00765 #else
00766 #define GENERATE_MAXIMUM \
00767 if(has_maximum) { \
00768 typedef policy::maximum_selection::tone maximum; \
00769 GENERATE_SELECT \
00770 } else { \
00771 typedef policy::maximum_selection::tinfinite maximum; \
00772 GENERATE_SELECT \
00773 }
00774 #endif
00775
00776 #ifdef GENERATE_BODY
00777 char compile_assert[0];
00778 #else
00779 #define GENERATE_BODY \
00780 if(has_minimum) { \
00781 typedef policy::minimum_selection::tone minimum; \
00782 GENERATE_MAXIMUM \
00783 } else { \
00784 typedef policy::minimum_selection::tnone minimum; \
00785 GENERATE_MAXIMUM \
00786 }
00787 #endif
00788
00789 tgenerator_* tgenerator_::build(
00790 const bool has_minimum, const bool has_maximum,
00791 const tplacement placement, const bool select)
00792 {
00793 tgenerator_* result = NULL;
00794 GENERATE_BODY;
00795 return result;
00796 }
00797
00798
00799 #if 0
00800 namespace {
00801
00802 void pointer_test()
00803 {
00804
00805 tgenerator_ *a = tgenerator_::build(
00806 true, true, tgenerator_::horizontal_list, true);
00807
00808 tgenerator_ *b = tgenerator_::build(
00809 true, false, tgenerator_::horizontal_list, true);
00810
00811 tgenerator_ *c = tgenerator_::build(
00812 false, true, tgenerator_::horizontal_list, true);
00813
00814 tgenerator_ *d = tgenerator_::build(
00815 false, false, tgenerator_::horizontal_list, true);
00816
00817 a->clear();
00818 b->clear();
00819 c->clear();
00820 d->clear();
00821
00822 delete a;
00823 delete b;
00824 delete c;
00825 delete d;
00826 }
00827
00828 void direct_test()
00829 {
00830 tgenerator
00831 < policy::minimum_selection::tone
00832 , policy::maximum_selection::tone
00833 , policy::placement::tvertical_list
00834 , policy::select_action::tselect
00835 > a;
00836
00837 tgenerator
00838 < policy::minimum_selection::tone
00839 , policy::maximum_selection::tinfinite
00840 , policy::placement::tvertical_list
00841 , policy::select_action::tselect
00842 > b;
00843
00844 tgenerator
00845 < policy::minimum_selection::tnone
00846 , policy::maximum_selection::tone
00847 , policy::placement::tvertical_list
00848 , policy::select_action::tselect
00849 > c;
00850
00851 tgenerator
00852 < policy::minimum_selection::tnone
00853 , policy::maximum_selection::tinfinite
00854 , policy::placement::tvertical_list
00855 , policy::select_action::tselect
00856 > d;
00857
00858 a.clear();
00859 b.clear();
00860 c.clear();
00861 d.clear();
00862
00863 }
00864
00865 }
00866 #endif
00867
00868 }
00869