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
| Generated by doxygen 1.7.1 on Fri May 25 2012 01:03:00 for The Battle for Wesnoth | Gna! | Forum | Wiki | CIA | devdocs |