gui/dialogs/dialog.hpp

Go to the documentation of this file.
00001 /* $Id: dialog.hpp 52533 2012-01-07 02:35:17Z shadowmaster $ */
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_DIALOGS_DIALOG_HPP_INCLUDED
00017 #define GUI_DIALOGS_DIALOG_HPP_INCLUDED
00018 
00019 #include "gui/dialogs/field-fwd.hpp"
00020 
00021 #include <string>
00022 #include <vector>
00023 
00024 class CVideo;
00025 
00026 namespace gui2 {
00027 
00028 /**
00029  * Registers a window.
00030  *
00031  * This function registers a window. The registration is used to validate
00032  * whether the config for the window exists when starting Wesnoth.
00033  *
00034  * @note Most of the time you want to call @ref REGISTER_DIALOG instead of this
00035  * function. It also directly adds the code for the dialog's id function.
00036  *
00037  * @param id                      Id of the window, multiple dialogs can use
00038  *                                the same window so the id doesn't need to be
00039  *                                unique.
00040  */
00041 #define REGISTER_WINDOW(                                                   \
00042           id)                                                              \
00043 namespace {                                                                \
00044                                                                            \
00045     namespace ns_##id {                                                    \
00046                                                                            \
00047         struct tregister_helper {                                          \
00048             tregister_helper()                                             \
00049             {                                                              \
00050                 register_window(#id);                                      \
00051             }                                                              \
00052         };                                                                 \
00053                                                                            \
00054         tregister_helper register_helper;                                  \
00055     }                                                                      \
00056 }
00057 
00058 /**
00059  * Registers a window for a dialog.
00060  *
00061  * Call this function to register a window. In the header of the class it adds
00062  * the following code:
00063  *@code
00064  *  // Inherited from tdialog, implemented by REGISTER_DIALOG.
00065  *  virtual const std::string& id() const;
00066  *@endcode
00067  * Then use this macro in the implementation, inside the gui2 namespace.
00068  *
00069  * @note When the @p id is "foo" and the type tfoo it's easier to use
00070  * REGISTER_DIALOG(foo).
00071  *
00072  * @param type                    Class type of the window to register.
00073  * @param id                      Id of the window, multiple dialogs can use
00074  *                                the same window so the id doesn't need to be
00075  *                                unique.
00076  */
00077 #define REGISTER_DIALOG2(                                                  \
00078           type                                                             \
00079         , id)                                                              \
00080                                                                            \
00081 REGISTER_WINDOW(id)                                                        \
00082                                                                            \
00083 const std::string&                                                         \
00084 type::window_id() const                                                    \
00085 {                                                                          \
00086     static const std::string result(#id);                                  \
00087     return result;                                                         \
00088 }
00089 
00090 /**
00091  * Wrapper for REGISTER_DIALOG2.
00092  *
00093  * "Calls" REGISTER_DIALOG2(twindow_id, window_id)
00094  */
00095 #define REGISTER_DIALOG(window_id) REGISTER_DIALOG2(t##window_id, window_id)
00096 
00097 /**
00098  * Abstract base class for all dialogs.
00099  *
00100  * A dialog shows a certain window instance to the user. The subclasses of this
00101  * class will hold the parameters used for a certain window, eg a server
00102  * connection dialog will hold the name of the selected server as parameter that
00103  * way the caller doesn't need to know about the 'contents' of the window.
00104  *
00105  * @par Usage
00106  *
00107  * Simple dialogs that are shown to query user information it is recommended to
00108  * add a static member called @p execute. The parameters to the function are:
00109  * - references to in + out parameters by reference
00110  * - references to the in parameters
00111  * - the parameters for @ref tdialog::show.
00112  *
00113  * The 'in + out parameters' are used as initial value and final value when the
00114  * OK button is pressed. The 'in parameters' are just extra parameters for
00115  * showing.
00116  *
00117  * When a function only has 'in parameters' it should return a void value and
00118  * the function should be called @p display, if it has 'in + out parameters' it
00119  * must return a bool value. This value indicates whether or not the OK button
00120  * was pressed to close the dialog. See @ref teditor_new_map::execute for an
00121  * example.
00122  */
00123 class tdialog
00124 {
00125     /**
00126      * Special helper function to get the id of the window.
00127      *
00128      * This is used in the unit tests, but these implementation details
00129      * shouldn't be used in the normal code.
00130      */
00131     friend std::string unit_test_mark_as_tested(const tdialog& dialog);
00132 
00133 public:
00134     tdialog() :
00135         retval_(0),
00136         always_save_fields_(false),
00137         fields_(),
00138         focus_(),
00139         restore_(true)
00140     {}
00141 
00142     virtual ~tdialog();
00143 
00144     /**
00145      * Shows the window.
00146      *
00147      * @param video               The video which contains the surface to draw
00148      *                            upon.
00149      * @param auto_close_time     The time in ms after which the dialog will
00150      *                            automatically close, if 0 it doesn't close.
00151      *                            @note the timeout is a minimum time and
00152      *                            there's no quarantee about how fast it closes
00153      *                            after the minimum.
00154      *
00155      * @returns                   Whether the final retval_ == twindow::OK
00156      */
00157     bool show(CVideo& video, const unsigned auto_close_time = 0);
00158 
00159 
00160     /***** ***** ***** setters / getters for members ***** ****** *****/
00161 
00162     int get_retval() const { return retval_; }
00163 
00164     void set_always_save_fields(const bool always_save_fields)
00165     {
00166         always_save_fields_ = always_save_fields;
00167     }
00168 
00169     void set_restore(const bool restore) { restore_ = restore; }
00170 
00171 protected:
00172 
00173     /**
00174      * Creates a new boolean field.
00175      *
00176      * The field created is owned by tdialog, the returned pointer can be used
00177      * in the child classes as access to a field.
00178      *
00179      * @param id                  Id of the widget, same value as in WML.
00180      * @param mandatory            Is the widget mandatory or mandatory.
00181      * @param callback_load_value The callback function to set the initial value
00182      *                            of the widget.
00183      * @param callback_save_value The callback function to write the resulting
00184      *                            value of the widget. Saving will only happen
00185      *                            if the widget is enabled and the window closed
00186      *                            with ok.
00187      * @param callback_change     When the value of the widget changes this
00188      *                            callback is called.
00189      *
00190      * @returns                   Pointer to the created widget.
00191      */
00192     tfield_bool* register_bool(const std::string& id
00193             , const bool mandatory
00194             , bool (*callback_load_value) () = NULL
00195             , void (*callback_save_value) (const bool value) = NULL
00196             , void (*callback_change) (twidget* widget) = NULL);
00197 
00198     /**
00199      * Creates a new boolean field.
00200      *
00201      * The field created is owned by tdialog, the returned pointer can be used
00202      * in the child classes as access to a field.
00203      *
00204      * @param id                  Id of the widget, same value as in WML.
00205      * @param mandatory            Is the widget mandatory or mandatory.
00206      * @param linked_variable     The variable the widget is linked to. See
00207      *                            @ref tfield::tfield for more information.
00208      * @param callback_change     When the value of the widget changes this
00209      *                            callback is called.
00210      *
00211      * @returns                   Pointer to the created widget.
00212      */
00213     tfield_bool* register_bool(const std::string& id
00214             , const bool mandatory
00215             , bool& linked_variable
00216             , void (*callback_change) (twidget* widget) = NULL);
00217 
00218     /**
00219      * Creates a new integer field.
00220      *
00221      * See @ref register_bool for more info.
00222      */
00223     tfield_integer* register_integer(const std::string& id
00224             , const bool mandatory
00225             , int (*callback_load_value) () = NULL
00226             , void (*callback_save_value) (const int value) = NULL);
00227 
00228     /**
00229      * Creates a new integer field.
00230      *
00231      * See @ref register_bool for more info.
00232      */
00233     tfield_integer* register_integer(const std::string& id
00234             , const bool mandatory
00235             , int& linked_variable);
00236     /**
00237      * Creates a new text field.
00238      *
00239      * See @ref register_bool for more info.
00240      */
00241     tfield_text* register_text(const std::string& id
00242             , const bool mandatory
00243             , std::string (*callback_load_value) () = NULL
00244             , void (*callback_save_value) (const std::string& value) = NULL
00245             , const bool capture_focus = false);
00246 
00247     /**
00248      * Creates a new text field.
00249      *
00250      * See @ref register_bool for more info.
00251      */
00252     tfield_text* register_text(const std::string& id
00253             , const bool mandatory
00254             , std::string& linked_variable
00255             , const bool capture_focus = false);
00256 
00257     /**
00258      * Registers a new control as a label.
00259      *
00260      * The label is used for a control to set the 'label' since it calls the
00261      * @ref tcontrol::set_label it can also be used for the @ref timage since
00262      * there this sets the filename. (The @p use_markup makes no sense in an
00263      * image but that's a detail.)
00264      *
00265      * @note In general it's prefered a widget sets its markup flag in WML, but
00266      * some generice windows (like messages) may need different versions
00267      * depending on where used.
00268      *
00269      * @param id                  Id of the widget, same value as in WML.
00270      * @param mandatory           Is the widget mandatory or optional.
00271      * @param text                The text for the label.
00272      * @param use_markup          Whether or not use markup for the label.
00273      */
00274     tfield_label* register_label(const std::string& id
00275             , const bool mandatory
00276             , const std::string& text
00277             , const bool use_markup = false);
00278 
00279     /** Registers a new control as image. */
00280     tfield_label* register_image(const std::string& id
00281             , const bool mandatory
00282             , const std::string& filename)
00283     {
00284         return register_label(id, mandatory, filename);
00285     }
00286 
00287 private:
00288     /** Returns the window exit status, 0 means not shown. */
00289     int retval_;
00290 
00291     /**
00292      * Always save the fields upon closing.
00293      *
00294      * Normally fields are only saved when the twindow::OK button is pressed.
00295      * With this flag set is always saves. Be careful with the flag since it
00296      * also updates upon canceling, which can be a problem when the field sets
00297      * a preference.
00298      */
00299     bool always_save_fields_;
00300 
00301     /**
00302      * Contains the automatically managed fields.
00303      *
00304      * Since the fields are automatically managed and there are no search
00305      * functions defined we don't offer access to the vector. If access is
00306      * needed the creator should store a copy of the pointer.
00307      */
00308     std::vector<tfield_*> fields_;
00309 
00310     /**
00311      * Contains the widget that should get the focus when the window is shown.
00312      */
00313     std::string focus_;
00314 
00315     /**
00316      * Restore the screen after showing?
00317      *
00318      * Most windows should restore the display after showing so this value
00319      * defaults to true. Toplevel windows (like the titlescreen don't want this
00320      * behaviour so they can change it in pre_show().
00321      */
00322     bool restore_;
00323 
00324     /** The id of the window to build. */
00325     virtual const std::string& window_id() const = 0;
00326 
00327     /**
00328      * Builds the window.
00329      *
00330      * Every dialog shows it's own kind of window, this function should return
00331      * the window to show.
00332      *
00333      * @param video               The video which contains the surface to draw
00334      *                            upon.
00335      * @returns                   The window to show.
00336      */
00337     twindow* build_window(CVideo& video) const;
00338 
00339     /**
00340      * Actions to be taken directly after the window is build.
00341      *
00342      * At this point the registered fields are not yet registered.
00343      *
00344      * @param video               The video which contains the surface to draw
00345      *                            upon.
00346      * @param window              The window just created.
00347      */
00348     virtual void post_build(CVideo& /*video*/, twindow& /*window*/) {}
00349 
00350     /**
00351      * Actions to be taken before showing the window.
00352      *
00353      * At this point the registered fields are registered and initialized with
00354      * their initial values.
00355      *
00356      * @param video               The video which contains the surface to draw
00357      *                            upon.
00358      * @param window              The window to be shown.
00359      */
00360     virtual void pre_show(CVideo& /*video*/, twindow& /*window*/) {}
00361 
00362     /**
00363      * Actions to be taken after the window has been shown.
00364      *
00365      * At this point the registered fields already stored their values (if the
00366      * OK has been pressed).
00367      *
00368      * @param window              The window which has been shown.
00369      */
00370     virtual void post_show(twindow& /*window*/) {}
00371 
00372     /**
00373      * Initializes all fields in the dialog and set the keyboard focus.
00374      *
00375      * @param window              The window which has been shown.
00376      */
00377     virtual void init_fields(twindow& window);
00378 
00379     /**
00380      * When the dialog is closed with the OK status saves all fields.
00381      *
00382      * Saving only happens if a callback handler is installed.
00383      *
00384      * @param window              The window which has been shown.
00385      * @param save_fields         Does the value in the fields need to be saved?
00386      */
00387     virtual void finalize_fields(twindow& window, const bool save_fields);
00388 };
00389 
00390 } // namespace gui2
00391 
00392 #endif
00393 
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines

Generated by doxygen 1.7.1 on Thu May 24 2012 01:02:42 for The Battle for Wesnoth
Gna! | Forum | Wiki | CIA | devdocs