gui/widgets/generator_private.hpp

Go to the documentation of this file.
00001 /* $Id: generator_private.hpp 54007 2012-04-28 19:16:10Z mordante $ */
00002 /*
00003    Copyright (C) 2008 - 2012 by Mark de Wever <koraq@xs4all.nl>
00004    Part of the Battle for Wesnoth Project http://www.wesnoth.org/
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (at your option) any later version.
00010    This program is distributed in the hope that it will be useful,
00011    but WITHOUT ANY WARRANTY.
00012 
00013    See the COPYING file for more details.
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  * Contains the policies for the tgenerator class.
00032  */
00033 namespace policy {
00034 
00035 /***** ***** ***** ***** Minimum selection ***** ***** ***** *****/
00036 
00037 /** Contains the policy for the minimum number of selected items. */
00038 namespace minimum_selection {
00039 
00040 /** Must select at least one item. */
00041 struct tone
00042     : public virtual tgenerator_
00043 {
00044     /**
00045      * Called when an item is shown or hidden.
00046      *
00047      * @param index               The item to show or hide.
00048      * @param show                If true shows the item, else hides it.
00049      */
00050     void set_item_shown(const unsigned index, const bool show);
00051 
00052     /**
00053      * Called when an item is created.
00054      *
00055      * @param index               The index of the new item.
00056      */
00057     void create_item(const unsigned index);
00058 
00059     /**
00060      * Called when the users wants to deselect an item.
00061      *
00062      * If the item can be deselected this function should call
00063      * do_deselect_item() to make the deslection happen. If not allowed no
00064      * action needs to be taken.
00065      *
00066      * @param index               The index of the item to deselect.
00067      *
00068      * @returns                   Whether the item was deselected, some
00069      *                            actions might happen automatically upon
00070      *                            deselecting, so if this function returns
00071      *                            false the caller should make sure the
00072      *                            select state is restored.
00073      */
00074     bool deselect_item(const unsigned index);
00075 
00076     /**
00077      * Called just before an item is deleted.
00078      *
00079      * This function can if needed select another items to try to obey the
00080      * policy.
00081      *
00082      * @param index              The index of the item to be deleted.
00083      */
00084     void delete_item(const unsigned index);
00085 };
00086 
00087 /** No minimum selection. */
00088 struct tnone
00089     : public virtual tgenerator_
00090 {
00091 
00092     /** See @ref minimum_selection::tone::set_item_shown(). */
00093     void set_item_shown(const unsigned index, const bool show);
00094 
00095     /** See @ref minimum_selection::tone::create_item() */
00096     void create_item(const unsigned /*index*/) {}
00097 
00098     /** See @ref minimum_selection::tone::deselect_item() */
00099     bool deselect_item(const unsigned index)
00100     {
00101         do_deselect_item(index);
00102         return true;
00103     }
00104 
00105     /** See @ref minimum_selection::tone::delete_item() */
00106     void delete_item(const unsigned index)
00107     {
00108         if(is_selected(index)) {
00109             do_deselect_item(index);
00110         }
00111     }
00112 };
00113 
00114 } // namespace minimum_selection
00115 
00116 /***** ***** ***** ***** Maximum selection ***** ***** ***** *****/
00117 
00118 /** Contains the policy for the maximum number of selected items. */
00119 namespace maximum_selection {
00120 
00121 /** May select only one item. */
00122 struct tone
00123     : public virtual tgenerator_
00124 {
00125     /**
00126      * Called when an item is selected.
00127      *
00128      * This function can deselect other items to obey the policy. This
00129      * function should always call do_select_item() so the new item does get
00130      * selected.
00131      *
00132      * @param index               The item to select.
00133      */
00134     void select_item(const unsigned index)
00135     {
00136         if(get_selected_item_count() == 1) {
00137             // deselect current.
00138             do_deselect_item(get_selected_item());
00139             // select new.
00140             do_select_item(index);
00141         }
00142     }
00143 };
00144 
00145 /** No maximum amount of items to select. */
00146 struct tinfinite
00147     : public virtual tgenerator_
00148 {
00149     /** See tone::select_item(). */
00150     void select_item(const unsigned index)
00151     {
00152         do_select_item(index);
00153     }
00154 };
00155 
00156 } // namespace maximum_selection
00157 
00158 /***** ***** ***** ***** Placement ***** ***** ***** *****/
00159 
00160 /** Controls how new items are placed. */
00161 namespace placement {
00162 
00163 /** Places the items in a horizontal row. */
00164 struct thorizontal_list
00165     : public virtual tgenerator_
00166 {
00167     thorizontal_list();
00168 
00169     /**
00170      * Called when an item is created.
00171      *
00172      * This function should place the new item.
00173      *
00174      * @param index                  The index of the new item.
00175      */
00176     void create_item(const unsigned index);
00177 
00178     /**
00179      * Tries to reduce the width for the generator.
00180      *
00181      * @see @ref layout_algorihm for more information.
00182      *
00183      * @param maximum_width       The wanted maximum width.
00184      */
00185     void request_reduce_width(const unsigned /*maximum_width*/) {}
00186 
00187     /**
00188      * Tries to reduce the height for the generator.
00189      *
00190      * @see @ref layout_algorihm for more information.
00191      *
00192      * @param maximum_height      The wanted maximum height.
00193      */
00194     virtual void request_reduce_height(const unsigned /*maximum_height*/)
00195     {
00196     }
00197 
00198     /**
00199      * Calculates the best size for the generator.
00200      *
00201      * @return                    The best size,
00202      */
00203     tpoint calculate_best_size() const;
00204 
00205     /**
00206      * Sets the size of the generator.
00207      *
00208      * @param origin              The origin of the generator.
00209      * @param size                The size of the generator.
00210      */
00211     void place(const tpoint& origin, const tpoint& size);
00212 
00213     /**
00214      * Sets the origin of the generator.
00215      *
00216      * @param origin              The origin of the generator.
00217      */
00218     void set_origin(const tpoint& origin);
00219 
00220     /**
00221      * Sets the visible area of the generator.
00222      *
00223      * @param area                The visible area.
00224      */
00225     void set_visible_area(const SDL_Rect& area);
00226 
00227     /** Inherited from tgenerator_. */
00228     twidget* find_at(const tpoint& coordinate, const bool must_be_active);
00229 
00230     /** Inherited from tgenerator_. */
00231     const twidget* find_at(const tpoint& coordinate
00232             , const bool must_be_active) const;
00233 
00234     /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
00235 
00236     /** Inherited from tgenerator_. */
00237     void handle_key_up_arrow(SDLMod /*modifier*/, bool& /*handled*/)
00238     {
00239         /* do nothing */
00240     }
00241 
00242     /** Inherited from tgenerator_. */
00243     void handle_key_down_arrow(SDLMod /*modifier*/, bool& /*handled*/)
00244     {
00245         /* do nothing */
00246     }
00247 
00248     /** Inherited from tgenerator_. */
00249     void handle_key_left_arrow(SDLMod modifier, bool& handled);
00250 
00251     /** Inherited from tgenerator_. */
00252     void handle_key_right_arrow(SDLMod modifier, bool& handled);
00253 
00254 private:
00255     /**
00256      * Has the grid already been placed?
00257      *
00258      * If the grid is placed it's no problem set the location of the new
00259      * item,it hasn't been placed, there's no information about its location
00260      * so do nothing.
00261      */
00262     bool placed_;
00263 };
00264 
00265 /** Places the items in a vertical column. */
00266 struct tvertical_list
00267     : public virtual tgenerator_
00268 {
00269     tvertical_list();
00270 
00271     /** See thorizontal_list::create_item(). */
00272     void create_item(const unsigned index);
00273 
00274     /** See thorizontal_list::request_reduce_width. */
00275     void request_reduce_width(const unsigned /*maximum_width*/) {}
00276 
00277     /** See thorizontal_list::request_reduce_height. */
00278     virtual void request_reduce_height(const unsigned /*maximum_height*/)
00279     {
00280     }
00281 
00282     /** See thorizontal_list::calculate_best_size(). */
00283     tpoint calculate_best_size() const;
00284 
00285     /** See thorizontal_list::place(). */
00286     void place(const tpoint& origin, const tpoint& size);
00287 
00288     /** See thorizontal_list::set_origin(). */
00289     void set_origin(const tpoint& origin);
00290 
00291     /** See thorizontal_list::set_visible_area(). */
00292     void set_visible_area(const SDL_Rect& area);
00293 
00294     /** See thorizontal_list::find_at(). */
00295     twidget* find_at(const tpoint& coordinate, const bool must_be_active);
00296 
00297     /** See thorizontal_list::find_at(). */
00298     const twidget* find_at(const tpoint& coordinate,
00299             const bool must_be_active) const;
00300 
00301     /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
00302 
00303     /** Inherited from tgenerator_. */
00304     void handle_key_up_arrow(SDLMod modifier, bool& handled);
00305 
00306     /** Inherited from tgenerator_. */
00307     void handle_key_down_arrow(SDLMod modifier, bool& handled);
00308 
00309     /** Inherited from tgenerator_. */
00310     void handle_key_left_arrow(SDLMod /*modifier*/, bool& /*handled*/)
00311         { /* do nothing */ }
00312 
00313     /** Inherited from tgenerator_. */
00314     void handle_key_right_arrow(SDLMod /*modifier*/, bool& /*handled*/)
00315         { /* do nothing */ }
00316 
00317     // FIXME we need a delete handler as well,
00318     // when deleting the last item we need to remove the placed flag.
00319 
00320     // FIXME we also need a clear function, called when
00321     // clear is called.
00322 private:
00323     /**
00324      * Has the grid already been placed?
00325      *
00326      * If the grid is placed it's no problem set the location of the new
00327      * item,it hasn't been placed, there's no information about its location
00328      * so do nothing.
00329      */
00330     bool placed_;
00331 };
00332 
00333 /**
00334  * Places the items in a grid.
00335  *
00336  * The items will be placed in rows and columns. It has to be determined
00337  * whether the number of columns will be fixed or variable.
00338  *
00339  * @todo Implement.
00340  */
00341 struct tmatrix
00342     : public virtual tgenerator_
00343 {
00344     /** See thorizontal_list::create_item(). */
00345     void create_item(const unsigned /*index*/) { ERROR_LOG(false); }
00346 
00347     /** See thorizontal_list::request_reduce_width. */
00348     void request_reduce_width(const unsigned /*maximum_width*/) {}
00349 
00350     /** See thorizontal_list::request_reduce_height. */
00351     virtual void request_reduce_height(const unsigned /*maximum_height*/)
00352     {
00353     }
00354 
00355     /** See thorizontal_list::calculate_best_size(). */
00356     tpoint calculate_best_size() const
00357         { ERROR_LOG(false); }
00358 
00359     /** See thorizontal_list::place(). */
00360     void place(const tpoint& /*origin*/, const tpoint& /*size*/)
00361         { ERROR_LOG(false); }
00362 
00363     /** See thorizontal_list::set_origin(). */
00364     void set_origin(const tpoint& /*origin*/)
00365         { ERROR_LOG(false); }
00366 
00367     /** See thorizontal_list::set_visible_area(). */
00368     void set_visible_area(const SDL_Rect& /*area*/)
00369         { ERROR_LOG(false); }
00370 
00371     /** See thorizontal_list::find_at(). */
00372     twidget* find_at(const tpoint&, const bool) { ERROR_LOG(false); }
00373 
00374     /** See thorizontal_list::find_at(). */
00375     const twidget* find_at(const tpoint&, const bool) const
00376         { ERROR_LOG(false); }
00377 
00378     /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
00379 
00380     /** Inherited from tgenerator_. */
00381     void handle_key_up_arrow(SDLMod, bool&)
00382         { ERROR_LOG(false); }
00383 
00384     /** Inherited from tgenerator_. */
00385     void handle_key_down_arrow(SDLMod, bool&)
00386         { ERROR_LOG(false); }
00387 
00388     /** Inherited from tgenerator_. */
00389     void handle_key_left_arrow(SDLMod, bool&)
00390         { ERROR_LOG(false); }
00391 
00392     /** Inherited from tgenerator_. */
00393     void handle_key_right_arrow(SDLMod, bool&)
00394         { ERROR_LOG(false); }
00395 };
00396 
00397 /**
00398  * Places the items independent of eachother.
00399  *
00400  * This is mainly meant for when only one item is shown at the same time.
00401  *
00402  * @todo Implement.
00403  */
00404 struct tindependent
00405     : public virtual tgenerator_
00406 {
00407     /** See thorizontal_list::create_item(). */
00408     void create_item(const unsigned /*index*/)
00409     {
00410         /* DO NOTHING */
00411     }
00412 
00413     /** See thorizontal_list::request_reduce_width. */
00414     void request_reduce_width(const unsigned maximum_width);
00415 
00416     /** See thorizontal_list::request_reduce_height. */
00417     virtual void request_reduce_height(const unsigned maximum_height);
00418 
00419     /** See thorizontal_list::calculate_best_size(). */
00420     tpoint calculate_best_size() const;
00421 
00422     /** See thorizontal_list::place(). */
00423     void place(const tpoint& origin, const tpoint& size);
00424 
00425     /** See thorizontal_list::set_origin(). */
00426     void set_origin(const tpoint& origin);
00427 
00428     /** See thorizontal_list::set_visible_area(). */
00429     void set_visible_area(const SDL_Rect& area);
00430 
00431     /** See thorizontal_list::find_at(). */
00432     twidget* find_at(const tpoint& coordinate, const bool must_be_active);
00433 
00434     /** See thorizontal_list::find_at(). */
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     /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
00443 
00444     /** Inherited from tgenerator_. */
00445     void handle_key_up_arrow(SDLMod, bool&)
00446     {
00447         /* DO NOTHING */
00448     }
00449 
00450     /** Inherited from tgenerator_. */
00451     void handle_key_down_arrow(SDLMod, bool&)
00452     {
00453         /* DO NOTHING */
00454     }
00455 
00456     /** Inherited from tgenerator_. */
00457     void handle_key_left_arrow(SDLMod, bool&)
00458     {
00459         /* DO NOTHING */
00460     }
00461 
00462     /** Inherited from tgenerator_. */
00463     void handle_key_right_arrow(SDLMod, bool&)
00464     {
00465         /* DO NOTHING */
00466     }
00467 };
00468 
00469 } // namespace placement
00470 
00471 /***** ***** ***** ***** Select action ***** ***** ***** *****/
00472 
00473 /**
00474  * Contains the policy for which action to take when an item is selected or
00475  * deselected.
00476  */
00477 namespace select_action {
00478 
00479 /** Select the item, this requires the grid to contain a tselectable_. */
00480 struct tselect
00481     : public virtual tgenerator_
00482 {
00483     void select(tgrid& grid, const bool select);
00484 
00485     /**
00486      * Helper function to initialize a grid.
00487      *
00488      * @param grid                The grid to initialize.
00489      * @param data                The data to initialize the parameters of
00490      *                            the new item.
00491      * @param callback            The callback function to call when an item
00492      *                            in the grid is (de)selected.
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 /** Show the item. */
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      * Helper function to initialize a grid.
00511      *
00512      * @param grid                The grid to initialize.
00513      * @param data                The data to initialize the parameters of
00514      *                            the new item. No widgets with id == "" are
00515      *                            allowed.
00516      * @param callback            The callback function is not used and
00517      *                            should be NULL.
00518      */
00519     void init(tgrid* grid
00520             , const std::map<std::string /* widget id */, string_map>& data
00521             , void (*callback)(twidget*));
00522 };
00523 
00524 } // namespace select_action
00525 
00526 } // namespace policy
00527 /***** ***** ***** ***** tgenerator ***** ***** ***** *****/
00528 
00529 /**
00530  * Basic template class to generate new items.
00531  *
00532  * The class is policy based so the behaviour can be selected.
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     /***** ***** ***** inherited ***** ****** *****/
00565 
00566     /** Inherited from tgenerator_. */
00567     void delete_item(const unsigned index)
00568     {
00569         assert(index < items_.size());
00570 
00571         // Might be other parts of the engine want to know about the
00572         // deselection, if minimum fails it gets another chance later on,
00573         // since it deletes the item.
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     /** Inherited from tgenerator_. */
00585     void clear()
00586     {
00587         foreach(titem* item, items_) {
00588             delete item;
00589         }
00590         selected_item_count_ = 0;
00591     }
00592 
00593     /** Inherited from tgenerator_. */
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                 // Some items might have deseleted themselves so
00605                 // make sure they do get selected again.
00606                 select_action::select(item(index), true);
00607             }
00608         }
00609     }
00610 
00611     /** Inherited from tgenerator_. */
00612     bool is_selected(const unsigned index) const
00613     {
00614         assert(index < items_.size());
00615         return (*items_[index]).selected;
00616     }
00617 
00618     /** Inherited from tgenerator_. */
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             /*** Set the proper visible state. ***/
00625             items_[index]->shown = show;
00626             items_[index]->grid.set_visible(show
00627                     ? twidget::VISIBLE
00628                     : twidget::INVISIBLE);
00629 
00630             /*** Update the selection. ***/
00631             minimum_selection::set_item_shown(index, show);
00632         }
00633     }
00634 
00635     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
00644     unsigned get_item_count() const
00645     {
00646         return items_.size();
00647     }
00648 
00649     /** Inherited from tgenerator_. */
00650     unsigned get_selected_item_count() const
00651     {
00652         return selected_item_count_;
00653     }
00654 
00655     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
00678     tgrid& item(const unsigned index)
00679     {
00680         assert(index < items_.size());
00681         return items_[index]->grid;
00682     }
00683 
00684     /** Inherited from tgenerator_. */
00685     const tgrid& item(const unsigned index) const
00686     {
00687         assert(index < items_.size());
00688         return items_[index]->grid;
00689     }
00690 
00691 
00692     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
00705     tgrid& create_item(const int index,
00706             tbuilder_grid_const_ptr list_builder,
00707             const std::map<std::string /* widget id */,
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     /** Inherited from tgenerator_. */
00732     virtual void create_items(const int index,
00733             tbuilder_grid_const_ptr list_builder,
00734             const std::vector<std::map<std::string /*widget id*/,
00735             string_map> >& data,
00736             void (*callback)(twidget*))
00737     {
00738         impl_create_items(index, list_builder, data, callback);
00739     }
00740 
00741     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
00761     void request_reduce_width(const unsigned maximum_width)
00762     {
00763         placement::request_reduce_width(maximum_width);
00764     }
00765 
00766     /** Inherited from tgenerator_. */
00767     void request_reduce_height(const unsigned maximum_height)
00768     {
00769         placement::request_reduce_height(maximum_height);
00770     }
00771 
00772     /** Inherited from tgenerator_. */
00773     tpoint calculate_best_size() const
00774     {
00775         return placement::calculate_best_size();
00776     }
00777 
00778     /** Inherited from tgenerator_. */
00779     void place(const tpoint& origin, const tpoint& size)
00780     {
00781         // Inherited, so we get useful debug info.
00782         twidget::place(origin, size);
00783 
00784         placement::place(origin, size);
00785     }
00786 
00787     /** Inherited from tgenerator_. */
00788     void set_origin(const tpoint& origin)
00789     {
00790         // Inherited.
00791         twidget::set_origin(origin);
00792 
00793         placement::set_origin(origin);
00794     }
00795 
00796     /** Inherited from tgenerator_. */
00797     void set_visible_area(const SDL_Rect& area)
00798     {
00799         placement::set_visible_area(area);
00800     }
00801 
00802     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
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     /** Inherited from widget. */
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      * Inherited from twidget.
00863      *
00864      * @todo Implement properly.
00865      */
00866     virtual iterator::twalker_* create_walker() { return NULL; }
00867 
00868     /***** ***** ***** ***** keyboard functions ***** ***** ***** *****/
00869 
00870     /** Inherited from tgenerator_. */
00871     void handle_key_up_arrow(SDLMod modifier, bool& handled)
00872     {
00873         placement::handle_key_up_arrow(modifier, handled);
00874     }
00875 
00876     /** Inherited from tgenerator_. */
00877     void handle_key_down_arrow(SDLMod modifier, bool& handled)
00878     {
00879         placement::handle_key_down_arrow(modifier, handled);
00880     }
00881 
00882     /** Inherited from tgenerator_. */
00883     void handle_key_left_arrow(SDLMod modifier, bool& handled)
00884     {
00885         placement::handle_key_left_arrow(modifier, handled);
00886     }
00887 
00888     /** Inherited from tgenerator_. */
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     /** Inherited from tgenerator_. */
00897     void do_select_item(const unsigned index) //fixme rename to impl
00898     {
00899         assert(index < items_.size());
00900 
00901         ++selected_item_count_;
00902         set_item_selected(index, true);
00903     }
00904 
00905     /** Inherited from tgenerator_. */
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     /** Definition of an item. */
00917     struct titem {
00918 
00919         titem()
00920             : grid()
00921             , selected(false)
00922             , shown(true)
00923         {
00924         }
00925 
00926         /** The grid containing the widgets. */
00927         tgrid grid;
00928 
00929         /** Is the item selected or not. */
00930         bool selected;
00931 
00932         /**
00933          * Is the row shown or not.
00934          *
00935          * This flag is used the help to set the visible flag, it's preferred to
00936          * test this flag for external functions.
00937          *
00938          * @todo functions now test for visible and shown, that can use some
00939          * polishing.
00940          */
00941         bool shown;
00942     };
00943 
00944     /** The number of selected items. */
00945     unsigned selected_item_count_;
00946 
00947     /** The last item selected. */
00948     int last_selected_item_;
00949 
00950     /** The items in the generator. */
00951     std::vector<titem*> items_;
00952 
00953     /**
00954      * Sets the selected state of an item.
00955      *
00956      * @param index               The item to modify.
00957      * @param selected            Select or deselect.
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      * Helper function for create_items().
00969      *
00970      * @tparam T                  Type of the data, this should be one of the
00971      *                            valid parameters for create_item().
00972      *
00973      * @param index               The item before which to add the new item,
00974      *                            0 == begin, -1 == end.
00975      * @param list_builder        A grid builder that's will build the
00976      *                            contents of the new item.
00977      * @param data                The data to initialize the parameters of
00978      *                            the new item.
00979      * @param callback            The callback function to call when an item
00980      *                            in the grid is (de)selected.
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      * Helper function to initialize a grid.
00999      *
01000      * The actual part is implemented in select_action, see those
01001      * implementations for more information.
01002      *
01003      * @param grid                The grid to initialize.
01004      * @param data                The data to initialize the parameters of
01005      *                            the new item.
01006      * @param callback            The callback function to call when an item
01007      *                            in the grid is (de)selected.
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 } // namespace gui2
01021 
01022 #endif
01023 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Fri May 25 2012 01:02:59 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs