gui/widgets/widget.hpp

Go to the documentation of this file.
00001 /* $Id: widget.hpp 54259 2012-05-20 14:00:17Z mordante $ */
00002 /*
00003    Copyright (C) 2007 - 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_WIDGET_HPP_INCLUDED
00017 #define GUI_WIDGETS_WIDGET_HPP_INCLUDED
00018 
00019 #include "gui/auxiliary/event/dispatcher.hpp"
00020 #include "gui/widgets/event_executor.hpp"
00021 #include "gui/widgets/helper.hpp"
00022 #include "utils/const_clone.tpp"
00023 #include "wml_exception.hpp"
00024 
00025 #include <boost/noncopyable.hpp>
00026 
00027 #include <string>
00028 #include <cassert>
00029 
00030 namespace gui2 {
00031 
00032 class tbuilder_widget;
00033 class tdialog;
00034 class twindow;
00035 
00036 namespace iterator {
00037     class twalker_;
00038 } // namespace iterator
00039 
00040 typedef std::map< std::string, t_string > string_map;
00041 
00042 /**
00043  * Base class for all widgets.
00044  *
00045  * From this abstract all other items should inherit. It contains the minimal
00046  * info needed for a real widget and some pure abstract functions which need to
00047  * be implemented by classes inheriting from this class.
00048  */
00049 class twidget
00050     : private boost::noncopyable
00051     , public virtual tevent_executor
00052     , public virtual event::tdispatcher
00053 {
00054     friend class tdebug_layout_graph;
00055     friend class twindow; // needed for modifying the layout_size.
00056 
00057 public:
00058 
00059     /** @deprecated use the second overload. */
00060     twidget();
00061 
00062     /**
00063      * Constructor.
00064      *
00065      * @param builder             The builder object with the settings for the
00066      *                            object.
00067      */
00068     explicit twidget(const tbuilder_widget& builder);
00069 
00070     virtual ~twidget();
00071 
00072     /***** ***** ***** ***** flags ***** ***** ***** *****/
00073 
00074     /** Visibility settings done by the user. */
00075     enum tvisible {
00076         /**
00077          * The user set the widget visible, that means:
00078          * * widget is visible.
00079          * * find_at always 'sees' the widget (the active flag is tested later).
00080          * * widget (if active) handles events (and sends events to children)
00081          * * widget is drawn (and sends populate_dirty_list to children)
00082          */
00083         VISIBLE,
00084         /**
00085          * The user set the widget hidden, that means:
00086          * * item is invisible but keeps its size.
00087          * * find_at 'sees' the widget if active is false.
00088          * * item doesn't handle events (and doesn't send events to children).
00089          * * item doesn't populate_dirty_list (nor does it send the request
00090          *   to its children).
00091          */
00092         HIDDEN,
00093         /**
00094          * The user set the widget invisible, that means:
00095          * * item is invisible and gridcell has size 0,0.
00096          * * find_at never 'sees' the widget.
00097          * * item doesn't handle events (and doesn't send events to children).
00098          * * item doesn't populate_dirty_list (nor does it send the request
00099          *   to its children).
00100          */
00101         INVISIBLE };
00102 
00103     /**
00104      * Visibility set by the engine.
00105      *
00106      * This state only will be used if the widget is visible, depending on
00107      * this state the widget might not be visible after all.
00108      */
00109     enum tdrawing_action {
00110         /** The widget is fully visible and should redrawn when set dirty. */
00111         DRAWN,
00112         /**
00113          * The widget is partly visible, in order to render it, it's clip
00114          * rect needs to be used.
00115          */
00116         PARTLY_DRAWN,
00117         /** The widget is not visible and should not be drawn if dirty. */
00118         NOT_DRAWN
00119     };
00120 
00121     /***** ***** ***** ***** layout functions ***** ***** ***** *****/
00122 
00123     /**
00124      * How the layout engine works.
00125      *
00126      * Every widget has a member layout_size_ which holds the best size in
00127      * the current layout phase. When the windows starts the layout phase it
00128      * calls layout_init() which resets this value.
00129      *
00130      * Every widget has two function to get the best size. get_best_size() tests
00131      * whether layout_size_ is set and if so returns that value otherwise it
00132      * calls calculate_best_size() so the size can be updated.
00133      *
00134      * During the layout phase some functions can modify layout_size_ so the
00135      * next call to get_best_size() returns the currently best size. This means
00136      * that after the layout phase get_best_size() still returns this value.
00137      */
00138 
00139     /**
00140      * Initializes the layout phase.
00141      *
00142      * Clears the initial best size for the widgets.
00143      *
00144      * @see @ref layout_algorihm for more information.
00145      *
00146      * @param full_initialization For widgets with scrollbars it hides them
00147      *                            unless the mode is
00148      *                            tscrollbar_mode::always_visible. For other
00149      *                            widgets this flag is a NOP.
00150      */
00151     virtual void layout_init(const bool full_initialization);
00152 
00153     /**
00154      * Tries to reduce the width of a widget.
00155      *
00156      * This function tries to do it 'friendly' and only use scrollbars or
00157      * wrapping of the widget.
00158      *
00159      * @see @ref layout_algorihm for more information.
00160      *
00161      * @param maximum_width       The wanted maximum width.
00162      */
00163     virtual void request_reduce_width(const unsigned maximum_width) = 0;
00164 
00165     /**
00166      * Tries to reduce the width of a widget.
00167      *
00168      * This function does it more aggressive and should only be used when
00169      * using scrollbars and wrapping failed.
00170      *
00171      * @todo Make pure virtual.
00172      *
00173      * @see @ref layout_algorihm for more information.
00174      *
00175      * @param maximum_width       The wanted maximum width.
00176      */
00177     virtual void demand_reduce_width(const unsigned /*maximum_width*/) {}
00178 
00179     /**
00180      * Tries to reduce the height of a widget.
00181      *
00182      * This function tries to do it 'friendly' and only use scrollbars.
00183      *
00184      * @todo Make pure virtual.
00185      *
00186      * @see @ref layout_algorihm for more information.
00187      *
00188      * @param maximum_height      The wanted maximum height.
00189      */
00190     virtual void request_reduce_height(const unsigned /*maximum_height*/) {}
00191 
00192     /**
00193      * Tries to reduce the height of a widget.
00194      *
00195      * This function does it more aggressive and should only be used when
00196      * using scrollbars failed.
00197      *
00198      * @todo Make pure virtual.
00199      *
00200      * @see @ref layout_algorihm for more information.
00201      *
00202      * @param maximum_height      The wanted maximum height.
00203      */
00204     virtual void demand_reduce_height(const unsigned /*maximum_height*/) {}
00205 
00206     /**
00207      * Gets the best size for the widget.
00208      *
00209      * During the layout phase a best size will be determined, several stages
00210      * might change the best size. This function will return the currently best
00211      * size as determined during the layout phase.
00212      *
00213      * @returns                      The best size for the widget.
00214      * @retval 0,0                   The best size is 0,0.
00215      */
00216     tpoint get_best_size() const;
00217 
00218 private:
00219     /**
00220      * Calculates the best size.
00221      *
00222      * This function calculates the best size and ignores the current values in
00223      * the layout phase. Note containers can call the get_best_size() of their
00224      * children since it's meant to update itself.
00225      *
00226      * @returns                      The best size for the widget.
00227      * @retval 0,0                   The best size is 0,0.
00228      */
00229     virtual tpoint calculate_best_size() const = 0;
00230 public:
00231 
00232     /**
00233      * Can the widget wrap.
00234      *
00235      * When a widget can wrap it can reduce it's width by increasing it's
00236      * height. When a layout is too wide it should first try to wrap and if
00237      * that fails it should check the vertical scrollbar status. After wrapping
00238      * the height might (probably will) change so the layout engine needs to
00239      * recalculate.
00240      */
00241     virtual bool can_wrap() const { return false; }
00242 
00243     /**
00244      * Places the widget.
00245      *
00246      * This function is normally called by a layout function to do the
00247      * placement of a widget.
00248      *
00249      * @param origin              The position of top left of the widget.
00250      * @param size                The size of the widget.
00251      */
00252     virtual void place(const tpoint& origin, const tpoint& size);
00253 
00254     /**
00255      * Sets the size of the widget.
00256      *
00257      * This version is meant to resize a widget, since the origin isn't
00258      * modified. This can be used if a widget needs to change its size and the
00259      * layout will be fixed later.
00260      *
00261      * @param size                The size of the widget.
00262      */
00263     virtual void set_size(const tpoint& size);
00264 
00265     /***** ***** ***** ***** query ***** ***** ***** *****/
00266 
00267     /**
00268      * Gets the widget at the wanted coordinates.
00269      *
00270      * @param coordinate          The coordinate which should be inside the
00271      *                            widget.
00272      * @param must_be_active      The widget should be active, not all widgets
00273      *                            have an active flag, those who don't ignore
00274      *                            flag.
00275      *
00276      * @returns                   The widget with the id.
00277      * @retval 0                  No widget at the wanted coordinate found (or
00278      *                            not active if must_be_active was set).
00279      */
00280     virtual twidget* find_at(const tpoint& coordinate,
00281             const bool must_be_active);
00282 
00283     /** The const version of find_at. */
00284     virtual const twidget* find_at(const tpoint& coordinate,
00285             const bool must_be_active) const;
00286 
00287     /**
00288      * Gets a widget with the wanted id.
00289      *
00290      * @param id                  The id of the widget to find.
00291      * @param must_be_active      The widget should be active, not all widgets
00292      *                            have an active flag, those who don't ignore
00293      *                            flag.
00294      *
00295      * @returns                   The widget with the id.
00296      * @retval 0                  No widget with the id found (or not active if
00297      *                            must_be_active was set).
00298      */
00299     virtual twidget* find(const std::string& id,
00300             const bool /*must_be_active*/)
00301         { return id_ == id ? this : 0; }
00302 
00303     /** The const version of find. */
00304     virtual const twidget* find(const std::string& id,
00305             const bool /*must_be_active*/) const
00306         { return id_ == id ? this : 0; }
00307 
00308     /**
00309      * Does the widget contain the widget.
00310      *
00311      * Widgets can be containers which have more widgets inside them, this
00312      * function will traverse in those child widgets and tries to find the
00313      * wanted widget.
00314      *
00315      * @param widget              Pointer to the widget to find.
00316      * @returns                   Whether or not the widget was found.
00317      */
00318     virtual bool has_widget(const twidget* widget) const
00319         { return widget == this; }
00320 
00321     /***** ***** ***** ***** query parents ***** ***** ***** *****/
00322 
00323     /**
00324      * Get the parent window.
00325      *
00326      * @returns                   Pointer to parent window.
00327      * @retval 0                  No parent window found.
00328      */
00329     twindow* get_window();
00330 
00331     /** The const version of get_window(). */
00332     const twindow* get_window() const;
00333 
00334     /**
00335      * Returns the toplevel dialog.
00336      *
00337      * A window is most of the time created by a dialog, this function returns
00338      * that dialog.
00339      *
00340      * @deprecated The function was used to install callbacks to member
00341      * functions of the dialog. Once all widgets are converted to signals this
00342      * function will be removed.
00343      *
00344      * @returns                   The toplevel dialog.
00345      * @retval 0                  No toplevel window or the toplevel window is
00346      *                            not owned by a dialog.
00347      */
00348     tdialog* dialog();
00349 
00350     /***** ***** ***** Misc. ***** ****** *****/
00351 
00352     /** Does the widget disable easy close? */
00353     virtual bool disable_click_dismiss() const = 0;
00354 
00355     /** Creates a new walker object on the heap. */
00356     virtual iterator::twalker_* create_walker() = 0;
00357 
00358     /***** ***** ***** setters / getters for members ***** ****** *****/
00359 
00360     twidget* parent() { return parent_; }
00361     void set_parent(twidget* parent) { parent_ = parent; }
00362 
00363     const std::string& id() const { return id_; }
00364     void set_id(const std::string& id);
00365 
00366     unsigned get_width() const { return w_; }
00367     unsigned get_height() const { return h_; }
00368 
00369     /** Returns the size of the widget. */
00370     tpoint get_size() const { return tpoint(w_, h_); }
00371 
00372     /** Returns the screen origin of the widget. */
00373     tpoint get_origin() const { return tpoint(x_, y_); }
00374 
00375     /** Gets the sizes in one rect structure. */
00376     SDL_Rect get_rect() const
00377         { return create_rect(get_origin(), get_size()); }
00378 
00379     /**
00380      * Gets the dirty rect of the widget.
00381      *
00382      * Depending on the drawing action it returns the rect this widget dirties
00383      * while redrawing.
00384      *
00385      * @returns                   The dirty rect.
00386      */
00387     SDL_Rect get_dirty_rect() const;
00388 
00389     /**
00390      * Sets the origin of the widget.
00391      *
00392      * This function can be used to move the widget without dirting it.
00393      *
00394      * @param origin              The new origin.
00395      */
00396     virtual void set_origin(const tpoint& origin)
00397     {
00398         x_ = origin.x;
00399         y_ = origin.y;
00400     }
00401 
00402     /**
00403      * Moves a widget.
00404      *
00405      * This function can be used to move the widget without dirtying it.
00406      *
00407      * @todo Implement the function to all inherited classes.
00408      *
00409      * @param x_offset            The amount of pixels to move the widget in
00410      *                            the x direction.
00411      * @param y_offset            The amount of pixels to move the widget in
00412      *                            the y direction.
00413      */
00414     virtual void move(const int x_offset, const int y_offset);
00415 
00416     int get_x() const { return x_; }
00417 
00418     int get_y() const { return y_; }
00419 
00420     void set_visible(const tvisible visible);
00421     tvisible get_visible() const { return visible_; }
00422 
00423     tdrawing_action get_drawing_action() const;
00424 
00425     /**
00426      * Sets the visible area for a widget.
00427      *
00428      * This function sets the drawing_state_ and the clip_rect_.
00429      *
00430      * @param area                The visible area in screen coordinates.
00431      */
00432     virtual void set_visible_area(const SDL_Rect& area);
00433 
00434     /**
00435      * Sets the widgets dirty state.
00436      *
00437      * @todo test whether nobody redefines the function.
00438      */
00439     void set_dirty(const bool dirty = true)
00440     {
00441         dirty_ = dirty;
00442     }
00443 
00444     /** Returns the dirty state for a widget, final function. */
00445     bool get_dirty() const { return dirty_; }
00446 
00447 #ifndef LOW_MEM
00448     void set_debug_border_mode(const unsigned debug_border_mode)
00449     {
00450         debug_border_mode_ = debug_border_mode;
00451     }
00452 
00453     void set_debug_border_color(const unsigned debug_border_color)
00454     {
00455         debug_border_color_ = debug_border_color;
00456     }
00457 #endif
00458 
00459     /**
00460      * Calculates the blitting rectangle of the widget.
00461      *
00462      * The blitting rectangle is to entire widget rectangle, but offsetted for
00463      * drawing position.
00464      *
00465      * @param x_offset            The x offset when drawn.
00466      * @param y_offset            The y offset when drawn.
00467      *
00468      * @returns                   The drawing rectangle.
00469      */
00470     SDL_Rect calculate_blitting_rectangle(
00471               const int x_offset
00472             , const int y_offset);
00473 
00474     /**
00475      * Calculates the clipping rectangle of the widget.
00476      *
00477      * The clipping rectangle is used then the @ref drawing_action_ is
00478      * @ref PARTLY_DRAWN. Since the drawing can be offsetted it also needs
00479      * offset paramters.
00480      *
00481      * @param x_offset            The x offset when drawn.
00482      * @param y_offset            The y offset when drawn.
00483      *
00484      * @returns                   The clipping rectangle.
00485      */
00486     SDL_Rect calculate_clipping_rectangle(
00487               const int x_offset
00488             , const int y_offset);
00489 
00490     /**
00491      * Draws the background of a widget.
00492      *
00493      * Subclasses should override impl_draw_background instead of changing
00494      * this function.
00495      *
00496      * @param frame_buffer        The surface to draw upon.
00497      * @param x_offset            The x offset in the @p frame_buffer to draw.
00498      * @param y_offset            The y offset in the @p frame_buffer to draw.
00499      */
00500     void draw_background(surface& frame_buffer);
00501     void draw_background(surface& frame_buffer, int x_offset, int y_offset);
00502 
00503     /**
00504      * Draws the children of a widget.
00505      *
00506      * Containers should draw their children when they get this request.
00507      *
00508      * Subclasses should override impl_draw_children instead of changing
00509      * this function.
00510      *
00511      * @param frame_buffer        The surface to draw upon.
00512      * @param x_offset            The x offset in the @p frame_buffer to draw.
00513      * @param y_offset            The y offset in the @p frame_buffer to draw.
00514      */
00515     void draw_children(surface& frame_buffer);
00516     void draw_children(surface& frame_buffer, int x_offset, int y_offset);
00517 
00518     /**
00519      * Draws the foreground of the widgt.
00520      *
00521      * Some widgets eg panel and window have a back and foreground layer this
00522      * function requests the drawing of the foreground.
00523      *
00524      * Subclasses should override impl_draw_foreground instead of changing
00525      * this function.
00526      *
00527      * @param frame_buffer        The surface to draw upon.
00528      * @param x_offset            The x offset in the @p frame_buffer to draw.
00529      * @param y_offset            The y offset in the @p frame_buffer to draw.
00530      */
00531     void draw_foreground(surface& frame_buffer);
00532     void draw_foreground(surface& frame_buffer, int x_offset, int y_offset);
00533 
00534     /**
00535      * Allows a widget to update its children.
00536      *
00537      * Before the window is populating the dirty list the widgets can update
00538      * their content, which allows delayed initialization. This delayed
00539      * initialization is only allowed if the widget resizes itself, not when
00540      * being placed.
00541      */
00542     virtual void layout_children() {}
00543 
00544     /**
00545      * Adds a widget to the dirty list if it is dirty.
00546      *
00547      * See twindow::dirty_list_ for more info on the dirty list.
00548      *
00549      * If the widget is not dirty and has children it should add itself to the
00550      * call_stack and call child_populate_dirty_list with the new call_stack.
00551      *
00552      * @param caller              The parent window, if dirty it should
00553      *                            register itself to this window.
00554      * @param call_stack          The callstack of widgets traversed to reach
00555      *                            this function.
00556      */
00557     void populate_dirty_list(twindow& caller,
00558             std::vector<twidget*>& call_stack);
00559 
00560 private:
00561 
00562     /**
00563      * Tries to add all children of a container to the dirty list.
00564      *
00565      * @note The function is private since everybody should call
00566      * populate_dirty_list instead.
00567      *
00568      * @param caller              The parent window, if dirty it should
00569      *                            register itself to this window.
00570      * @param call_stack          The callstack of widgets traversed to reach
00571      *                            this function.
00572      */
00573     virtual void child_populate_dirty_list(twindow& /*caller*/,
00574             const std::vector<twidget*>& /*call_stack*/) {}
00575 protected:
00576     /***** ***** ***** setters / getters for members ***** ****** *****/
00577 
00578     void set_layout_size(const tpoint& size) { layout_size_ = size; }
00579     const tpoint& layout_size() const { return layout_size_; }
00580 
00581 public:
00582 
00583     void set_linked_group(const std::string& linked_group)
00584     {
00585         linked_group_ = linked_group;
00586     }
00587 
00588 private:
00589 
00590     /**
00591      * The id is the unique name of the widget in a certain context.
00592      *
00593      * This is needed for certain widgets so the engine knows which widget is
00594      * which. Eg it knows which button is pressed and thus which engine action
00595      * is connected to the button. This doesn't mean that the id is unique in a
00596      * window, eg a listbox can have the same id for every row.
00597      */
00598     std::string id_;
00599 
00600     /**
00601      * The parent widget, if the widget has a parent it contains a pointer to
00602      * the parent, else it's set to NULL.
00603      */
00604     twidget* parent_;
00605 
00606     /** The x coordinate of the widget in the screen. */
00607     int x_;
00608 
00609     /** The y coordinate of the widget in the screen. */
00610     int y_;
00611 
00612     /** The width of the widget. */
00613     unsigned w_;
00614 
00615     /** The height of the widget. */
00616     unsigned h_;
00617 
00618     /**
00619      * Is the widget dirty? When a widget is dirty it needs to be redrawn at
00620      * the next drawing cycle, setting it to dirty also need to set it's parent
00621      * dirty so at so point the toplevel parent knows which item to redraw.
00622      *
00623      * NOTE dirtying the parent might be inefficient and this behaviour might be
00624      * optimized later on.
00625      */
00626     bool dirty_;
00627 
00628     /** Field for the status of the visibility. */
00629     tvisible visible_;
00630 
00631     /** Field for the action to do on a drawing request. */
00632     tdrawing_action drawing_action_;
00633 
00634     /** The clip rect is a widget is partly visible. */
00635     SDL_Rect clip_rect_;
00636 
00637     /**
00638      * The best size for the control.
00639      *
00640      * When 0,0 the real best size is returned, but in the layout phase a
00641      * wrapping or a scrollbar might change the best size for that widget.
00642      * This variable holds that best value.
00643      */
00644     tpoint layout_size_;
00645 
00646     /**
00647      * The linked group the widget belongs to.
00648      *
00649      * @todo For now the linked group is initialized when the layout of the
00650      * widget is initialized. The best time to set it would be upon adding the
00651      * widget in the window. Need to look whether it's possible in a clean way.
00652      * Maybe a signal just prior to showing a window where the widget can do
00653      * some of it's on things, would also be nice for widgets that need a
00654      * finalizer function.
00655      */
00656     std::string linked_group_;
00657 
00658 #ifndef LOW_MEM
00659     /**
00660      * Mode for drawing the debug border.
00661      *
00662      * The debug border is a helper border to determine where a widget is
00663      * placed. It's only intended for debugging purposes.
00664      *
00665      * Possible values:
00666      * - 0 no border
00667      * - 1 single pixel border
00668      * - 2 floodfilled rectangle
00669      */
00670     unsigned debug_border_mode_;
00671 
00672     /** The color for the debug border. */
00673     unsigned debug_border_color_;
00674 
00675     void draw_debug_border(surface& frame_buffer);
00676     void draw_debug_border(surface& frame_buffer, int x_offset, int y_offset);
00677 #else
00678     void draw_debug_border(surface&) {}
00679     void draw_debug_border(surface&, int, int) {}
00680 #endif
00681 
00682 #ifdef DEBUG_WINDOW_LAYOUT_GRAPHS
00683     /**
00684      * Debug helper to store last value of get_best_size().
00685      *
00686      * We're mutable so calls can stay const and this is disabled in
00687      * production code.
00688      */
00689     mutable tpoint last_best_size_;
00690 #endif
00691 
00692     /** See draw_background(). */
00693     virtual void impl_draw_background(surface& /*frame_buffer*/) {}
00694     virtual void impl_draw_background(
00695               surface& /*frame_buffer*/
00696             , int /*x_offset*/
00697             , int /*y_offset*/)
00698     {
00699     }
00700 
00701     /** See draw_children. */
00702     virtual void impl_draw_children(surface& /*frame_buffer*/) {}
00703     virtual void impl_draw_children(
00704             surface& /*frame_buffer*/
00705             , int /*x_offset*/
00706             , int /*y_offset*/)
00707     {
00708     }
00709 
00710     /** See draw_foreground. */
00711     virtual void impl_draw_foreground(surface& /*frame_buffer*/) {}
00712     virtual void impl_draw_foreground(
00713               surface& /*frame_buffer*/
00714             , int /*x_offset*/
00715             , int /*y_offset*/)
00716     {
00717     }
00718 
00719     /** (Will be) inherited from event::tdispatcher. */
00720     virtual bool is_at(const tpoint& coordinate) const
00721     {
00722         return is_at(coordinate, true);
00723     }
00724 
00725     /**
00726      * Is the coordinate inside our area.
00727      *
00728      * Helper for find_at so also looks at our visibility.
00729      *
00730      * @param coordinate          The coordinate which should be inside the
00731      *                            widget.
00732      * @param must_be_active      The widget should be active, not all widgets
00733      *                            have an active flag, those who don't ignore
00734      *                            flag.
00735      *
00736      * @returns                   Status.
00737      */
00738     bool is_at(const tpoint& coordinate, const bool must_be_active) const;
00739 };
00740 
00741 /**
00742  * Returns the first parent of a widget with a certain type.
00743  *
00744  * @param widget                  The widget to get the parent from,
00745  * @tparam T                      The class of the widget to return.
00746  *
00747  * @returns                       The parent widget.
00748  */
00749 template<class T> T* get_parent(twidget* widget)
00750 {
00751     T* result;
00752     do {
00753         widget = widget->parent();
00754         result = dynamic_cast<T*>(widget);
00755 
00756     } while (widget && !result);
00757 
00758     assert(result);
00759     return result;
00760 }
00761 
00762 /**
00763  * Gets a widget with the wanted id.
00764  *
00765  * This template function doesn't return a pointer to a generic widget but
00766  * returns the wanted type and tests for its existence if required.
00767  *
00768  * @param widget              The widget test or find a child with the wanted
00769  *                            id.
00770  * @param id                  The id of the widget to find.
00771  * @param must_be_active      The widget should be active, not all widgets
00772  *                            have an active flag, those who don't ignore
00773  *                            flag.
00774  * @param must_exist          The widget should be exist, the function will
00775  *                            fail if the widget doesn't exist or is
00776  *                            inactive and must be active. Upon failure a
00777  *                            wml_error is thrown.
00778  *
00779  * @returns                   The widget with the id.
00780  */
00781 template<class T>
00782 T* find_widget(typename utils::tconst_clone<twidget, T>::pointer widget
00783         , const std::string& id
00784         , const bool must_be_active
00785         , const bool must_exist)
00786 {
00787     T* result =
00788         dynamic_cast<T*>(widget->find(id, must_be_active));
00789     VALIDATE(!must_exist || result, missing_widget(id));
00790 
00791     return result;
00792 }
00793 
00794 /**
00795  * Gets a widget with the wanted id.
00796  *
00797  * This template function doesn't return a reference to a generic widget but
00798  * returns a reference to the wanted type
00799  *
00800  * @param widget              The widget test or find a child with the wanted
00801  *                            id.
00802  * @param id                  The id of the widget to find.
00803  * @param must_be_active      The widget should be active, not all widgets
00804  *                            have an active flag, those who don't ignore
00805  *                            flag.
00806  *
00807  * @returns                   The widget with the id.
00808  */
00809 template<class T>
00810 T& find_widget(typename utils::tconst_clone<twidget, T>::pointer widget
00811         , const std::string& id
00812         , const bool must_be_active)
00813 {
00814     return *find_widget<T>(widget, id, must_be_active, true);
00815 }
00816 
00817 } // namespace gui2
00818 
00819 /**
00820  * Registers a widget.
00821  *
00822  * Call this function to register a widget. Use this macro in the
00823  * implementation, inside the gui2 namespace.
00824  *
00825  * @see @ref gui2::load_widget_definitions for more information.
00826  *
00827  * @note When the type is tfoo_definition, the id "foo" and no special key best
00828  * use RESISTER_WIDGET(foo) instead.
00829  *
00830  * @param type                    Class type of the window to register.
00831  * @param id                      Id of the widget
00832  * @param key                     The id to load if differs from id.
00833  */
00834 #define REGISTER_WIDGET3(                                                  \
00835           type                                                             \
00836         , id                                                               \
00837         , key)                                                             \
00838 namespace {                                                                \
00839                                                                            \
00840     namespace ns_##type {                                                  \
00841                                                                            \
00842         struct tregister_helper {                                          \
00843             tregister_helper()                                             \
00844             {                                                              \
00845                 register_widget(#id, boost::bind(                          \
00846                           load_widget_definitions<type>                    \
00847                         , _1                                               \
00848                         , _2                                               \
00849                         , _3                                               \
00850                         , key));                                           \
00851                                                                            \
00852                 register_builder_widget(#id, boost::bind(                  \
00853                               build_widget<implementation::tbuilder_##id>  \
00854                             , _1));                                        \
00855             }                                                              \
00856         };                                                                 \
00857                                                                            \
00858         static tregister_helper register_helper;                           \
00859     }                                                                      \
00860 }
00861 
00862 /**
00863  * Wrapper for REGISTER_WIDGET3.
00864  *
00865  * "Calls" REGISTER_WIDGET3(tid_definition, id, _4)
00866  */
00867 #define REGISTER_WIDGET(id) REGISTER_WIDGET3(t##id##_definition, id, _4)
00868 
00869 #endif
00870 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

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