widget.hpp

Go to the documentation of this file.
00001 /* $Id: widget.hpp 26681 2008-05-18 06:05:59Z mordante $ */
00002 /*
00003    copyright (C) 2007 - 2008 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 version 2
00008    or at your option any later version.
00009    this program is distributed in the hope that it will be useful,
00010    but without any warranty.
00011 
00012    see the copying file for more details.
00013 */
00014 
00015 #ifndef __GUI_WIDGETS_WIDGET_HPP_INCLUDED__
00016 #define __GUI_WIDGETS_WIDGET_HPP_INCLUDED__
00017 
00018 #include "gui/widgets/helper.hpp"
00019 #include "sdl_utils.hpp"
00020 
00021 #include "SDL.h"
00022 
00023 #include <string>
00024 
00025 namespace gui2 {
00026 
00027 class tevent_handler;
00028 
00029 //! Base class with all possible events, most widgets can ignore most of
00030 //! these, but they are available.
00031 class tevent_executor
00032 {
00033 public:
00034     tevent_executor() :
00035         wants_mouse_hover_(false),
00036         wants_mouse_left_double_click_(false),
00037         wants_mouse_middle_double_click_(false),
00038         wants_mouse_right_double_click_(false)
00039         {}
00040     virtual ~tevent_executor() {}
00041 
00042 // Description of various event generating scenarios
00043 //
00044 // mouse moves on a widget and the focus isn't stolen:
00045 // - mouse enter
00046 //
00047 // mouse on widget clicked without moving
00048 // - mouse down
00049 // - mouse up
00050 // wait for possible double click if widget wants double click
00051 // - mouse click
00052 
00053     virtual void mouse_enter(tevent_handler&) {}
00054     virtual void mouse_move(tevent_handler&) {}
00055     virtual void mouse_hover(tevent_handler&) {}
00056     virtual void mouse_leave(tevent_handler&) {}
00057 
00058     virtual void mouse_left_button_down(tevent_handler&) {}
00059     virtual void mouse_left_button_up(tevent_handler&) {}
00060     virtual void mouse_left_button_click(tevent_handler&) {}
00061     virtual void mouse_left_button_double_click(tevent_handler&) {}
00062 
00063     virtual void mouse_middle_button_down(tevent_handler&) {}
00064     virtual void mouse_middle_button_up(tevent_handler&) {}
00065     virtual void mouse_middle_button_click(tevent_handler&) {}
00066     virtual void mouse_middle_button_double_click(tevent_handler&) {}
00067 
00068     virtual void mouse_right_button_down(tevent_handler&) {}
00069     virtual void mouse_right_button_up(tevent_handler&) {}
00070     virtual void mouse_right_button_click(tevent_handler&) {}
00071     virtual void mouse_right_button_double_click(tevent_handler&) {}
00072 
00073     //! Handled, if there's a keyboard focus it will get the change to
00074     //! handle the key first, if not done it's send to the window.
00075     //! SDLKey the sdl key code needed for special keys
00076     //! SDLMod the keyboard modifiers at moment of pressing
00077     //! Unit16 the unicode for the pressed key
00078     virtual void key_press(tevent_handler&, bool&, SDLKey, SDLMod, Uint16) {} 
00079 
00080     virtual void window_resize(tevent_handler&, const unsigned /* new_width */, 
00081         const unsigned /* new_height */) {}
00082 
00083     //! When F1 is pressed this event is triggered.
00084     virtual void help_key(tevent_handler&) {}
00085 
00086     bool wants_mouse_hover() const { return wants_mouse_hover_; }
00087 
00088     bool wants_mouse_left_double_click() const { return wants_mouse_left_double_click_; }
00089     bool wants_mouse_middle_double_click() const { return wants_mouse_middle_double_click_; }
00090     bool wants_mouse_right_double_click() const { return wants_mouse_right_double_click_; }
00091 
00092     tevent_executor& set_wants_mouse_hover(const bool hover = true) 
00093         { wants_mouse_hover_ = hover; return *this; }
00094 
00095     tevent_executor& set_wants_mouse_left_double_click(const bool click = true) 
00096         { wants_mouse_left_double_click_ = click; return *this; }
00097 
00098     tevent_executor& set_wants_mouse_middle_double_click(const bool click = true) 
00099         { wants_mouse_middle_double_click_ = click; return *this; }
00100 
00101     tevent_executor& set_wants_mouse_right_double_click(const bool click = true) 
00102         { wants_mouse_right_double_click_ = click; return *this; }
00103 
00104 private:
00105     //! If a widget doesn't want a double click we need to send a second
00106     //! click instead of double click.
00107     bool wants_mouse_hover_;
00108     bool wants_mouse_left_double_click_;
00109     bool wants_mouse_middle_double_click_;
00110     bool wants_mouse_right_double_click_;
00111 };
00112 
00113 class twindow;
00114 
00115 //! Base class for all widgets.
00116 //! This is a non visible widget but it does have dimentions and size hints.
00117 class twidget : public virtual tevent_executor
00118 {
00119 public:
00120     twidget() : 
00121         id_(""), 
00122         definition_("default"),
00123         parent_(0),
00124         x_(-1),
00125         y_(-1),
00126         w_(0),
00127         h_(0),
00128         dirty_(true)
00129         {}
00130     virtual ~twidget() {}
00131 
00132     twidget* parent() { return parent_; }
00133     void set_parent(twidget* parent) { parent_ = parent; }
00134 
00135     const std::string& id() const { return id_; }
00136     void set_id(const std::string& id) { id_ = id; }
00137 
00138     const std::string& definition() const { return definition_; }
00139 
00140     //! This should not be changed after the widget is shown, strange things
00141     //! might occur.
00142     virtual void set_definition(const std::string& definition) 
00143         { definition_ = definition; }
00144 
00145     //! Draws a widget.
00146     // FIXME add force as parameter
00147     virtual void draw(surface& /*surface*/) = 0;
00148 
00149     // invisible widgets never hit, only items with a size NOT here
00150     // virtual bool does_hit(const int x, const int y) const { return false; }
00151 
00152 
00153     int get_x() const { return x_; }
00154     int get_y() const { return y_; }
00155     unsigned get_width() const { return w_; }
00156     unsigned get_height() const { return h_; }
00157 
00158     //! Is the widget dirty?
00159     virtual bool dirty() const { return dirty_; }
00160 
00161     //! Gets the minimum size for the object, 0,0 means no size required.
00162     virtual tpoint get_minimum_size() const = 0;    
00163 
00164     //! Gets the best size for the object, 0,0 means no size required.
00165     virtual tpoint get_best_size() const = 0;   
00166 
00167     //! Gets the best size for an object, 0,0 means no limits.
00168     virtual tpoint get_maximum_size() const = 0;    
00169 
00170     //! Sets a predefined size for the object.
00171     virtual void set_size(const SDL_Rect& rect)
00172     {
00173         x_ = rect.x;
00174         y_ = rect.y;
00175         w_ = rect.w;
00176         h_ = rect.h;
00177         dirty_ = true;
00178     }
00179 
00180     /**
00181      * Gets the widget at the wanted coordinates.
00182      *
00183      * @param coordinate          The coordinate which should be inside the
00184      *                            widget.
00185      * @param must_be_active      The widget should be active, not all widgets
00186      *                            have an active flag, those who don't ignore
00187      *                            flag.
00188      * 
00189      * @returns                   The widget with the id.
00190      * @retval 0                  No widget at the wanted coordinate found (or
00191      *                            not active if must_be_active was set).
00192      */
00193     virtual twidget* find_widget(const tpoint& coordinate, 
00194             const bool must_be_active) 
00195     { 
00196         return coordinate.x >= x_ && coordinate.x < (x_ + w_) &&
00197             coordinate.y >= y_ && coordinate.y < (y_ + h_) ? this : 0;
00198     }
00199 
00200     /** The const version of find_widget. */
00201     virtual const twidget* find_widget(const tpoint& coordinate, 
00202             const bool must_be_active) const
00203     { 
00204         return coordinate.x >= x_ && coordinate.x < (x_ + w_) &&
00205             coordinate.y >= y_ && coordinate.y < (y_ + h_) ? this : 0;
00206     }
00207 
00208     /**
00209      * Gets a widget with the wanted id.
00210      *
00211      * @param id                  The id of the widget to find.
00212      * @param must_be_active      The widget should be active, not all widgets
00213      *                            have an active flag, those who don't ignore
00214      *                            flag.
00215      * 
00216      * @returns                   The widget with the id.
00217      * @retval 0                  No widget with the id found (or not active if
00218      *                            must_be_active was set).
00219      */
00220     virtual twidget* find_widget(const std::string& id, 
00221             const bool must_be_active)
00222         { return id_ == id ? this : 0; }
00223 
00224     /** The const version of find_widget. */
00225     virtual const twidget* find_widget(const std::string& id, 
00226             const bool must_be_active) const
00227         { return id_ == id ? this : 0; }
00228 
00229     /** 
00230      * Does the widget contain the widget.
00231      *
00232      * This makes more sence in container classes.
00233      */
00234     virtual bool has_widget(const twidget* widget) const 
00235         { return widget == this; }
00236 
00237     //! The toplevel item should always be a window if not null is returned
00238     twindow* get_window();
00239 
00240     //! loads the configuration of the widget, mainly used for controls.
00241     virtual void load_config() {} 
00242 
00243     SDL_Rect get_rect() const 
00244         { return ::create_rect( x_, y_, w_, h_ ); }
00245 
00246 
00247     /** 
00248      * If the best size doesn't fit we want to use the best size for normal 
00249      * widgets, and resize those who own a scrollbar. 
00250      */
00251     virtual bool has_vertical_scrollbar() const { return false; }
00252     virtual bool has_horizontal_scrollbar() const { return false; }
00253 
00254 protected:  
00255     virtual void set_dirty(const bool dirty = true) 
00256     { 
00257         dirty_ = dirty; 
00258         if(parent_ && dirty) parent_->set_dirty(true);
00259     }
00260 
00261 private:
00262     //! The id is the unique name of the widget in a certain context. This is
00263     //! needed for certain widgets so the engine knows which widget is which. 
00264     //! Eg it knows which button is pressed and thuswhich engine action is 
00265     //! connected to the button.
00266     std::string id_;
00267 
00268     //! The definition is the id of that widget class. Eg for a button it
00269     //! [button_definition]id. A button can have multiple definitions which all
00270     //! look different but for the engine still is a button.
00271     std::string definition_;
00272 
00273     twidget* parent_;
00274     int x_, y_;
00275     unsigned w_, h_;
00276     bool dirty_;
00277 
00278 };
00279 
00280 /**
00281  * Small abstract helper class.
00282  *
00283  * Parts of the engine inherit this class so we can have generic
00284  * selectable items.
00285  */
00286 class tselectable_ 
00287 {
00288 public:
00289     virtual ~tselectable_() {}
00290 
00291     /** Is the control selected? */
00292     virtual bool is_selected() const = 0;
00293 
00294     /** Select the control */
00295     virtual void set_selected(const bool = true) = 0;
00296 };
00297 
00298 } // namespace gui2
00299 
00300 #endif

Generated by doxygen 1.5.5 on 23 May 2008 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs