00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016 #ifndef GUI_WIDGETS_GENERATOR_PRIVATE_HPP_INCLUDED
00017 #define GUI_WIDGETS_GENERATOR_PRIVATE_HPP_INCLUDED
00018
00019 #include "gui/widgets/generator.hpp"
00020
00021 #include "asserts.hpp"
00022 #include "foreach.hpp"
00023 #include "gui/widgets/grid.hpp"
00024 #include "gui/widgets/selectable.hpp"
00025 #include "gui/widgets/toggle_button.hpp"
00026 #include "gui/widgets/toggle_panel.hpp"
00027
00028 namespace gui2 {
00029
00030
00031
00032
00033 namespace policy {
00034
00035
00036
00037
00038 namespace minimum_selection {
00039
00040
00041 struct tone
00042 : public virtual tgenerator_
00043 {
00044
00045
00046
00047
00048
00049
00050 void set_item_shown(const unsigned index, const bool show);
00051
00052
00053
00054
00055
00056
00057 void create_item(const unsigned index);
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074 bool deselect_item(const unsigned index);
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084 void delete_item(const unsigned index);
00085 };
00086
00087
00088 struct tnone
00089 : public virtual tgenerator_
00090 {
00091
00092
00093 void set_item_shown(const unsigned index, const bool show);
00094
00095
00096 void create_item(const unsigned ) {}
00097
00098
00099 bool deselect_item(const unsigned index)
00100 {
00101 do_deselect_item(index);
00102 return true;
00103 }
00104
00105
00106 void delete_item(const unsigned index)
00107 {
00108 if(is_selected(index)) {
00109 do_deselect_item(index);
00110 }
00111 }
00112 };
00113
00114 }
00115
00116
00117
00118
00119 namespace maximum_selection {
00120
00121
00122 struct tone
00123 : public virtual tgenerator_
00124 {
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 void select_item(const unsigned index)
00135 {
00136 if(get_selected_item_count() == 1) {
00137
00138 do_deselect_item(get_selected_item());
00139
00140 do_select_item(index);
00141 }
00142 }
00143 };
00144
00145
00146 struct tinfinite
00147 : public virtual tgenerator_
00148 {
00149
00150 void select_item(const unsigned index)
00151 {
00152 do_select_item(index);
00153 }
00154 };
00155
00156 }
00157
00158
00159
00160
00161 namespace placement {
00162
00163
00164 struct thorizontal_list
00165 : public virtual tgenerator_
00166 {
00167 thorizontal_list();
00168
00169
00170
00171
00172
00173
00174
00175
00176 void create_item(const unsigned index);
00177
00178
00179
00180
00181
00182
00183
00184
00185 void request_reduce_width(const unsigned ) {}
00186
00187
00188
00189
00190
00191
00192
00193
00194 virtual void request_reduce_height(const unsigned )
00195 {
00196 }
00197
00198
00199
00200
00201
00202
00203 tpoint calculate_best_size() const;
00204
00205
00206
00207
00208
00209
00210
00211 void place(const tpoint& origin, const tpoint& size);
00212
00213
00214
00215
00216
00217
00218 void set_origin(const tpoint& origin);
00219
00220
00221
00222
00223
00224
00225 void set_visible_area(const SDL_Rect& area);
00226
00227
00228 twidget* find_at(const tpoint& coordinate, const bool must_be_active);
00229
00230
00231 const twidget* find_at(const tpoint& coordinate
00232 , const bool must_be_active) const;
00233
00234
00235
00236
00237 void handle_key_up_arrow(SDLMod , bool& )
00238 {
00239
00240 }
00241
00242
00243 void handle_key_down_arrow(SDLMod , bool& )
00244 {
00245
00246 }
00247
00248
00249 void handle_key_left_arrow(SDLMod modifier, bool& handled);
00250
00251
00252 void handle_key_right_arrow(SDLMod modifier, bool& handled);
00253
00254 private:
00255
00256
00257
00258
00259
00260
00261
00262 bool placed_;
00263 };
00264
00265
00266 struct tvertical_list
00267 : public virtual tgenerator_
00268 {
00269 tvertical_list();
00270
00271
00272 void create_item(const unsigned index);
00273
00274
00275 void request_reduce_width(const unsigned ) {}
00276
00277
00278 virtual void request_reduce_height(const unsigned )
00279 {
00280 }
00281
00282
00283 tpoint calculate_best_size() const;
00284
00285
00286 void place(const tpoint& origin, const tpoint& size);
00287
00288
00289 void set_origin(const tpoint& origin);
00290
00291
00292 void set_visible_area(const SDL_Rect& area);
00293
00294
00295 twidget* find_at(const tpoint& coordinate, const bool must_be_active);
00296
00297
00298 const twidget* find_at(const tpoint& coordinate,
00299 const bool must_be_active) const;
00300
00301
00302
00303
00304 void handle_key_up_arrow(SDLMod modifier, bool& handled);
00305
00306
00307 void handle_key_down_arrow(SDLMod modifier, bool& handled);
00308
00309
00310 void handle_key_left_arrow(SDLMod , bool& )
00311 { }
00312
00313
00314 void handle_key_right_arrow(SDLMod , bool& )
00315 { }
00316
00317
00318
00319
00320
00321
00322 private:
00323
00324
00325
00326
00327
00328
00329
00330 bool placed_;
00331 };
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 struct tmatrix
00342 : public virtual tgenerator_
00343 {
00344
00345 void create_item(const unsigned ) { ERROR_LOG(false); }
00346
00347
00348 void request_reduce_width(const unsigned ) {}
00349
00350
00351 virtual void request_reduce_height(const unsigned )
00352 {
00353 }
00354
00355
00356 tpoint calculate_best_size() const
00357 { ERROR_LOG(false); }
00358
00359
00360 void place(const tpoint& , const tpoint& )
00361 { ERROR_LOG(false); }
00362
00363
00364 void set_origin(const tpoint& )
00365 { ERROR_LOG(false); }
00366
00367
00368 void set_visible_area(const SDL_Rect& )
00369 { ERROR_LOG(false); }
00370
00371
00372 twidget* find_at(const tpoint&, const bool) { ERROR_LOG(false); }
00373
00374
00375 const twidget* find_at(const tpoint&, const bool) const
00376 { ERROR_LOG(false); }
00377
00378
00379
00380
00381 void handle_key_up_arrow(SDLMod, bool&)
00382 { ERROR_LOG(false); }
00383
00384
00385 void handle_key_down_arrow(SDLMod, bool&)
00386 { ERROR_LOG(false); }
00387
00388
00389 void handle_key_left_arrow(SDLMod, bool&)
00390 { ERROR_LOG(false); }
00391
00392
00393 void handle_key_right_arrow(SDLMod, bool&)
00394 { ERROR_LOG(false); }
00395 };
00396
00397
00398
00399
00400
00401
00402
00403
00404 struct tindependent
00405 : public virtual tgenerator_
00406 {
00407
00408 void create_item(const unsigned )
00409 {
00410
00411 }
00412
00413
00414 void request_reduce_width(const unsigned maximum_width);
00415
00416
00417 virtual void request_reduce_height(const unsigned maximum_height);
00418
00419
00420 tpoint calculate_best_size() const;
00421
00422
00423 void place(const tpoint& origin, const tpoint& size);
00424
00425
00426 void set_origin(const tpoint& origin);
00427
00428
00429 void set_visible_area(const SDL_Rect& area);
00430
00431
00432 twidget* find_at(const tpoint& coordinate, const bool must_be_active);
00433
00434
00435 const twidget* find_at(const tpoint& coordinate
00436 , const bool must_be_active) const;
00437
00438 twidget* find(const std::string& id, const bool must_be_active);
00439
00440 const twidget* find(const std::string& id, const bool must_be_active) const;
00441
00442
00443
00444
00445 void handle_key_up_arrow(SDLMod, bool&)
00446 {
00447
00448 }
00449
00450
00451 void handle_key_down_arrow(SDLMod, bool&)
00452 {
00453
00454 }
00455
00456
00457 void handle_key_left_arrow(SDLMod, bool&)
00458 {
00459
00460 }
00461
00462
00463 void handle_key_right_arrow(SDLMod, bool&)
00464 {
00465
00466 }
00467 };
00468
00469 }
00470
00471
00472
00473
00474
00475
00476
00477 namespace select_action {
00478
00479
00480 struct tselect
00481 : public virtual tgenerator_
00482 {
00483 void select(tgrid& grid, const bool select);
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494 void init(tgrid* grid
00495 , const std::map<std::string /* widget id */, string_map>& data
00496 , void (*callback)(twidget*));
00497
00498 };
00499
00500
00501 struct tshow
00502 : public virtual tgenerator_
00503 {
00504 void select(tgrid& grid, const bool show)
00505 {
00506 grid.set_visible(show ? twidget::VISIBLE : twidget::HIDDEN);
00507 }
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519 void init(tgrid* grid
00520 , const std::map<std::string /* widget id */, string_map>& data
00521 , void (*callback)(twidget*));
00522 };
00523
00524 }
00525
00526 }
00527
00528
00529
00530
00531
00532
00533
00534 template
00535 < class minimum_selection
00536 , class maximum_selection
00537 , class placement
00538 , class select_action
00539 >
00540 class tgenerator
00541 : public minimum_selection
00542 , public maximum_selection
00543 , public placement
00544 , public select_action
00545 {
00546 public:
00547
00548 tgenerator()
00549 : minimum_selection()
00550 , maximum_selection()
00551 , placement()
00552 , select_action()
00553 , selected_item_count_(0)
00554 , last_selected_item_(-1)
00555 , items_()
00556 {
00557 }
00558
00559 ~tgenerator()
00560 {
00561 clear();
00562 }
00563
00564
00565
00566
00567 void delete_item(const unsigned index)
00568 {
00569 assert(index < items_.size());
00570
00571
00572
00573
00574 if(is_selected(index)) {
00575 select_item(index, false);
00576 }
00577
00578 minimum_selection::delete_item(index);
00579
00580 delete items_[index];
00581 items_.erase(items_.begin() + index);
00582 }
00583
00584
00585 void clear()
00586 {
00587 foreach(titem* item, items_) {
00588 delete item;
00589 }
00590 selected_item_count_ = 0;
00591 }
00592
00593
00594 void select_item(const unsigned index,
00595 const bool select = true)
00596 {
00597 assert(index < items_.size());
00598
00599 if(select && !is_selected(index)) {
00600 maximum_selection::select_item(index);
00601 last_selected_item_ = index;
00602 } else if(is_selected(index)) {
00603 if(!minimum_selection::deselect_item(index)) {
00604
00605
00606 select_action::select(item(index), true);
00607 }
00608 }
00609 }
00610
00611
00612 bool is_selected(const unsigned index) const
00613 {
00614 assert(index < items_.size());
00615 return (*items_[index]).selected;
00616 }
00617
00618
00619 void set_item_shown(const unsigned index, const bool show)
00620 {
00621 assert(index < items_.size());
00622 if(items_[index]->shown != show) {
00623
00624
00625 items_[index]->shown = show;
00626 items_[index]->grid.set_visible(show
00627 ? twidget::VISIBLE
00628 : twidget::INVISIBLE);
00629
00630
00631 minimum_selection::set_item_shown(index, show);
00632 }
00633 }
00634
00635
00636 virtual bool get_item_shown(const unsigned index) const
00637 {
00638 assert(index < items_.size());
00639 return items_[index]->shown;
00640 }
00641
00642
00643
00644 unsigned get_item_count() const
00645 {
00646 return items_.size();
00647 }
00648
00649
00650 unsigned get_selected_item_count() const
00651 {
00652 return selected_item_count_;
00653 }
00654
00655
00656 int get_selected_item() const
00657 {
00658
00659 if(selected_item_count_ == 0) {
00660 return -1;
00661 } else if(last_selected_item_ != -1
00662 && last_selected_item_ < static_cast<int>(items_.size())
00663 && (*items_[last_selected_item_]).selected) {
00664
00665 return last_selected_item_;
00666
00667 } else {
00668 for(size_t i = 0; i < items_.size(); ++i) {
00669 if((*items_[i]).selected) {
00670 return i;
00671 }
00672 }
00673 ERROR_LOG("No item selected.");
00674 }
00675 }
00676
00677
00678 tgrid& item(const unsigned index)
00679 {
00680 assert(index < items_.size());
00681 return items_[index]->grid;
00682 }
00683
00684
00685 const tgrid& item(const unsigned index) const
00686 {
00687 assert(index < items_.size());
00688 return items_[index]->grid;
00689 }
00690
00691
00692
00693 tgrid& create_item(const int index,
00694 tbuilder_grid_const_ptr list_builder,
00695 const string_map& item_data,
00696 void (*callback)(twidget*))
00697 {
00698 std::map<std::string, string_map> data;
00699
00700 data.insert(std::make_pair("", item_data));
00701 return create_item(index, list_builder, data, callback);
00702 }
00703
00704
00705 tgrid& create_item(const int index,
00706 tbuilder_grid_const_ptr list_builder,
00707 const std::map<std::string ,
00708 string_map>& item_data,
00709 void (*callback)(twidget*))
00710 {
00711 assert(list_builder);
00712 assert(index == -1 || static_cast<unsigned>(index) < items_.size());
00713
00714 titem* item = new titem;
00715 list_builder->build(&item->grid);
00716 init(&item->grid, item_data, callback);
00717
00718 const unsigned item_index = index == -1
00719 ? items_.size()
00720 : index;
00721
00722 items_.insert(items_.begin() + item_index, item);
00723 minimum_selection::create_item(item_index);
00724 placement::create_item(item_index);
00725 if(!is_selected(item_index)) {
00726 select_action::select(item->grid, false);
00727 }
00728 return item->grid;
00729 }
00730
00731
00732 virtual void create_items(const int index,
00733 tbuilder_grid_const_ptr list_builder,
00734 const std::vector<std::map<std::string ,
00735 string_map> >& data,
00736 void (*callback)(twidget*))
00737 {
00738 impl_create_items(index, list_builder, data, callback);
00739 }
00740
00741
00742 virtual void create_items(const int index,
00743 tbuilder_grid_const_ptr list_builder,
00744 const std::vector<string_map>& data,
00745 void (*callback)(twidget*))
00746 {
00747 impl_create_items(index, list_builder, data, callback);
00748 }
00749
00750
00751 void layout_init(const bool full_initialization)
00752 {
00753 foreach(titem* item, items_) {
00754 if(item->grid.get_visible() != twidget::INVISIBLE && item->shown) {
00755 item->grid.layout_init(full_initialization);
00756 }
00757 }
00758 }
00759
00760
00761 void request_reduce_width(const unsigned maximum_width)
00762 {
00763 placement::request_reduce_width(maximum_width);
00764 }
00765
00766
00767 void request_reduce_height(const unsigned maximum_height)
00768 {
00769 placement::request_reduce_height(maximum_height);
00770 }
00771
00772
00773 tpoint calculate_best_size() const
00774 {
00775 return placement::calculate_best_size();
00776 }
00777
00778
00779 void place(const tpoint& origin, const tpoint& size)
00780 {
00781
00782 twidget::place(origin, size);
00783
00784 placement::place(origin, size);
00785 }
00786
00787
00788 void set_origin(const tpoint& origin)
00789 {
00790
00791 twidget::set_origin(origin);
00792
00793 placement::set_origin(origin);
00794 }
00795
00796
00797 void set_visible_area(const SDL_Rect& area)
00798 {
00799 placement::set_visible_area(area);
00800 }
00801
00802
00803 void impl_draw_children(surface& frame_buffer)
00804 {
00805 assert(this->get_visible() == twidget::VISIBLE);
00806
00807 foreach(titem* item, items_) {
00808 if(item->grid.get_visible() == twidget::VISIBLE && item->shown) {
00809 item->grid.draw_children(frame_buffer);
00810 }
00811 }
00812 }
00813
00814
00815 void impl_draw_children(surface& frame_buffer, int x_offset, int y_offset)
00816 {
00817 assert(this->get_visible() == twidget::VISIBLE);
00818
00819 foreach(titem* item, items_) {
00820 if(item->grid.get_visible() == twidget::VISIBLE && item->shown) {
00821 item->grid.draw_children(frame_buffer, x_offset, y_offset);
00822 }
00823 }
00824 }
00825
00826
00827 void child_populate_dirty_list(twindow& caller,
00828 const std::vector<twidget*>& call_stack)
00829 {
00830 foreach(titem* item, items_) {
00831 std::vector<twidget*> child_call_stack = call_stack;
00832 item->grid.populate_dirty_list(caller, child_call_stack);
00833 }
00834 }
00835
00836
00837 twidget* find_at(
00838 const tpoint& coordinate, const bool must_be_active)
00839 {
00840 return placement::find_at(coordinate, must_be_active);
00841 }
00842
00843
00844 const twidget* find_at(
00845 const tpoint& coordinate, const bool must_be_active) const
00846 {
00847 return placement::find_at(coordinate, must_be_active);
00848 }
00849
00850
00851 bool disable_click_dismiss() const
00852 {
00853 foreach(titem* item, items_) {
00854 if(item->grid.disable_click_dismiss()) {
00855 return true;
00856 }
00857 }
00858 return false;
00859 }
00860
00861
00862
00863
00864
00865
00866 virtual iterator::twalker_* create_walker() { return NULL; }
00867
00868
00869
00870
00871 void handle_key_up_arrow(SDLMod modifier, bool& handled)
00872 {
00873 placement::handle_key_up_arrow(modifier, handled);
00874 }
00875
00876
00877 void handle_key_down_arrow(SDLMod modifier, bool& handled)
00878 {
00879 placement::handle_key_down_arrow(modifier, handled);
00880 }
00881
00882
00883 void handle_key_left_arrow(SDLMod modifier, bool& handled)
00884 {
00885 placement::handle_key_left_arrow(modifier, handled);
00886 }
00887
00888
00889 void handle_key_right_arrow(SDLMod modifier, bool& handled)
00890 {
00891 placement::handle_key_right_arrow(modifier, handled);
00892 }
00893
00894 protected:
00895
00896
00897 void do_select_item(const unsigned index)
00898 {
00899 assert(index < items_.size());
00900
00901 ++selected_item_count_;
00902 set_item_selected(index, true);
00903 }
00904
00905
00906 void do_deselect_item(const unsigned index)
00907 {
00908 assert(index < items_.size());
00909
00910 --selected_item_count_;
00911 set_item_selected(index, false);
00912 }
00913
00914 private:
00915
00916
00917 struct titem {
00918
00919 titem()
00920 : grid()
00921 , selected(false)
00922 , shown(true)
00923 {
00924 }
00925
00926
00927 tgrid grid;
00928
00929
00930 bool selected;
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941 bool shown;
00942 };
00943
00944
00945 unsigned selected_item_count_;
00946
00947
00948 int last_selected_item_;
00949
00950
00951 std::vector<titem*> items_;
00952
00953
00954
00955
00956
00957
00958
00959 void set_item_selected(const unsigned index, const bool selected)
00960 {
00961 assert(index < items_.size());
00962
00963 (*items_[index]).selected = selected;
00964 select_action::select((*items_[index]).grid, selected);
00965 }
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982 template<class T>
00983 void impl_create_items(const int index,
00984 tbuilder_grid_const_ptr list_builder,
00985 const std::vector<T>& data,
00986 void (*callback)(twidget*))
00987 {
00988 int i = index;
00989 foreach(const T& item_data, data) {
00990 create_item(i, list_builder, item_data, callback);
00991 if(i != -1) {
00992 ++i;
00993 }
00994 }
00995 }
00996
00997
00998
00999
01000
01001
01002
01003
01004
01005
01006
01007
01008
01009 void init(tgrid* grid,
01010 const std::map<std::string /* widget id */, string_map>& data,
01011 void (*callback)(twidget*))
01012 {
01013 assert(grid);
01014 grid->set_parent(this);
01015
01016 select_action::init(grid, data, callback);
01017 }
01018 };
01019
01020 }
01021
01022 #endif
01023