/////////////////////////////////////////////////////////////////////////////// // // Copyright (C) 2008-2012 Artyom Beilis (Tonkikh) // // See accompanying file COPYING.TXT file for licensing details. // /////////////////////////////////////////////////////////////////////////////// #ifndef CPPCMS_FORM_H #define CPPCMS_FORM_H #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace cppcms { namespace http { class file; } namespace widgets { class base_widget; } /// /// \brief This struct holds various flags to control the HTML generation. /// struct form_flags { /// /// This enum represents the HTML/XHTML switch. /// typedef enum { as_html = 0, ///< render form/widget as ordinary HTML as_xhtml= 1, ///< render form/widget as XHTML } html_type; /// /// This enum represents the style for the widgets generation. /// typedef enum { as_p = 0 , ///< Render each widget using paragraphs as_table= 1 , ///< Render each widget using table as_ul = 2 , ///< Render each widget using unordered list as_dl = 3 , ///< Render each widget using definitions list as_space= 4 ///< Render each widget using simple blank space separators } html_list_type; /// /// This special flag is used to partially generate a widget's HTML. /// typedef enum { first_part = 0, ///< Render part 1: HTML attributes can be inserted after it. second_part = 1 ///< Render part 2: complete part 1. } widget_part_type; }; /// /// \brief This class represents the context required to generate the widgets' HTML. /// class CPPCMS_API form_context : public form_flags { public: /// /// Default constructor. /// form_context(); /// /// Copy-constructor. /// form_context(form_context const &other); /// /// Assignment. /// form_context const &operator = (form_context const &other); /// /// Create a rendering context. /// /// \param output the std::ostream output to write HTML to. /// \param ht flags represents the type of HTML that should be generated. /// \param hlt flag defines the style of widgets generation. /// form_context( std::ostream &output, html_type ht = form_flags::as_html, html_list_type hlt=form_flags::as_p); /// /// Destructor. /// ~form_context(); /// /// Set the HTML/XHTML flag. /// void html(html_type t); /// /// Set the widgets rendering style. /// void html_list(html_list_type t); /// /// Set the flag for the partial rendering of the widget. /// void widget_part(widget_part_type t); /// /// Set the output stream. /// void out(std::ostream &out); /// /// Set the HTML/XHTML flag. The default is \a as_html. /// html_type html() const; /// /// Get the widget rendering style. The default is \a as_p. /// html_list_type html_list() const; /// /// Get the part of the widget that should be generated. See \a widget_part_type. The default is \a first_part. /// widget_part_type widget_part() const; /// /// Get the output stream. /// std::ostream &out() const; private: uint32_t html_type_; uint32_t html_list_type_; uint32_t widget_part_type_; std::ostream *output_; CPPCMS_UNUSED_MEMBER uint32_t reserved_1; CPPCMS_UNUSED_MEMBER uint32_t reserved_2; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This class is the base class for any form or form widget used in CppCMS. /// /// It provides basic, abstract operations that every widget or form should implement. /// class CPPCMS_API base_form : public form_flags { public: /// /// Render the widget to the output set in \a cppcms::form_context::out() /// according to the control flags set in \a cppcms::form_flags. /// Usually this function is called directly by the template rendering functions. /// virtual void render(form_context &context) = 0; /// /// Load the form information from the provided http::context \a context. /// A user can call this function to load all information from the raw POST/GET /// data into the internal widget representation. /// virtual void load(http::context &context) = 0; /// /// Validate the form according to defined rules. If all checks are OK, /// true is returned. If some widget or form fails, false is returned. /// virtual bool validate() = 0; /// /// Clear the form from all user provided data. /// virtual void clear() = 0; /// /// Set the parent of this form. Used internally. You should not use it. /// virtual void parent(base_form *subform) = 0; /// /// Get the parent of this form. If this is the topmost form, NULL is returned. /// virtual base_form *parent() = 0; base_form(); virtual ~base_form(); }; /// /// \brief The \a form is a container used to collect other widgets and forms into a single unit. /// /// Generally various widgets and forms are combined into a single form in order to simplify their rendering /// and validation of the forms that include more than one widget. /// class CPPCMS_API form : public booster::noncopyable, public base_form { public: form(); virtual ~form(); /// /// Render all the widgets and sub-forms to the \a output, using /// the flags defined in the \a context. /// virtual void render(form_context &context); /// /// Load all the widget information from http::context \a cont. /// virtual void load(http::context &cont); /// /// Validate all subforms and widgets. If at least one of them fails, /// false is returned. Otherwise, true is returned. /// virtual bool validate(); /// /// Clear all subforms and widgets from all loaded data. /// virtual void clear(); /// /// Add \a subform to form. The ownership is not transferred to /// the parent. /// void add(form &subform); /// /// Add \a subform to form. The ownership is transferred to /// the parent and the subform will be destroyed together with /// the parent. /// void attach(form *subform); /// /// Add \a widget to form. The ownership is not transferred to /// to the parent. /// void add(widgets::base_widget &widget); /// /// Add \a widget to form. The ownership is transferred to /// the parent and the widget will be destroyed together with /// the parent. /// void attach(widgets::base_widget *widget); /// /// \deprecated Use add(form &) instead /// /// Shortcut to \a add. /// CPPCMS_DEPRECATED inline form &operator + (form &f) { add(f); return *this; } /// /// \deprecated Use add(widgets::base_widget &) instead /// /// Shortcut to \a add. /// CPPCMS_DEPRECATED inline form &operator + (widgets::base_widget &f) { add(f); return *this; } /// /// Set the parent of this form. It is used internally; you should not use it. It is called /// when the form is added or attached to another form. /// virtual void parent(base_form *subform); /// /// Get the parent of this form. If this is the topmost form, NULL is returned. /// It is assumed that the parent is always a form. /// virtual form *parent(); /// /// \brief Input iterator used to iterate over all the widgets in a form. /// /// This class is mainly used by templates to render widgets. It /// recursively iterates over all the widgets and subforms. /// /// \note it iterates over widgets only and never \ref /// form objects. /// /// \code /// iterator p=f.begin(); /// if(p!=f.end()) /// if p!=f.end() --> *p is derived from widgets::base_widget. /// \endcode /// class CPPCMS_API iterator : public std::iterator { public: /// /// End iterator. /// iterator(); /// /// Create a widget iterator. /// iterator(form &); /// /// Destructor. /// ~iterator(); /// /// Copy the iterator. This operation is not cheap. /// iterator(iterator const &other); /// /// Assign the iterator. This operation is not cheap. /// iterator const &operator = (iterator const &other); /// /// Return the underlying widget. Condition: *this!=iterator(). /// widgets::base_widget *operator->() const { return get(); } /// /// Return the underlying widget. Condition: *this!=iterator(). /// widgets::base_widget &operator*() const { return *get(); } /// /// Check if two iterators point to the same element. /// bool operator==(iterator const &other) const { return equal(other); } /// /// Check if two iterators point to different elements. /// bool operator!=(iterator const &other) const { return !equal(other); } /// /// Post increment operator. It forwards the iterator to the next widget. /// Note it does not point to the higher level form container. /// /// Note: it is preferable to use ++i rather than i++ as copying iterators is not cheap. /// iterator operator++(int /*unused*/) { iterator tmp(*this); next(); return tmp; } /// /// Increment operator. It forwards the iterator to the next widget. /// Note it does not point to the higher level form container. /// iterator &operator++() { next(); return *this; } private: friend class form; bool equal(iterator const &other) const; void zero(); void next(); widgets::base_widget *get() const; std::stack return_positions_; form *current_; unsigned offset_; struct _data; booster::copy_ptr<_data> d; }; /// /// Returns the iterator to the first widget. /// iterator begin(); /// /// Returns the end of the range iterator. /// iterator end(); private: friend class iterator; struct _data; // Widget and ownership - true means I own it. typedef std::pair widget_type; std::vector elements_; form *parent_; booster::hold_ptr<_data> d; }; /// /// \brief This namespace includes all the widgets (i.e. parts of HTML forms) supported by cppcms. /// namespace widgets { /// /// \brief this class is the base class of all renderable widgets which /// can be used with CppCMS form system. /// /// All cppcms widgets are derived from this class. Users who want to create /// their own custom widgets must derive them from this class. /// class CPPCMS_API base_widget : public base_form, public booster::noncopyable { public: /// /// Default constructor. /// base_widget(); virtual ~base_widget(); /// /// Check if a value has been assigned to the widget. It is usually true /// when the user has assigned a value to the widget or when the widget is loaded. /// /// If there is a reasonable default value for the widget /// then set() should be true. For widgets like file or numeric /// where explicit parsing is required, the set() value would indicate /// that user provided some value (i.e. uploaded a file or entered a number). /// bool set(); /// /// After having executed the validation process, each widget can be tested for validity. /// bool valid(); /// /// Get the HTML \a id attribute. /// std::string id(); /// /// Get the HTML \a name attribute. /// std::string name(); /// /// Get the short message that would be displayed near the widget. /// locale::message message(); /// /// Check if a message is set. /// bool has_message(); /// /// Get the error message that would be displayed near the widget /// if the widget validation failed. /// locale::message error_message(); /// /// Check if an error message is set. /// bool has_error_message(); /// /// Get the eventual long description of the wigget. /// locale::message help(); /// /// Check if a help message is set. /// bool has_help(); /// /// Get the HTML \c disabled attribute. /// bool disabled(); /// /// Set/Unset the HTML \c disabled attribute. /// void disabled(bool); /// /// Get the HTML \c readonly attribute. /// /// \ver{v1_2} bool readonly(); /// /// Set/Unset the HTML \c readonly attribute. /// /// \ver{v1_2} void readonly(bool); /// /// Get the general user defined attribute string that can be added to the widget. /// std::string attributes_string(); /// /// Set the existence of content for the widget. By default the widget is not set. /// By convention, trying to fetch a value from a widget that is "unset" will throw an exception. /// Call set(true) to change the state to "set" and call set(false) to change it to "unset". /// void set(bool); /// /// Set th validity state of the widget. By default the widget is valid. If it fails to pass /// the validation, its validity state is changed by calling this function. /// /// Note: a widget may be "unset" and still be valid. Conversely, it may be set but be not-valid. /// void valid(bool); /// /// Set the HTML \c id attribute of the widget. /// void id(std::string); /// /// Set the HTML \c name attribute of the widget. Note: if this attribute /// is not set, the widget will not be able to be loaded from the POST/GET /// data. /// void name(std::string); /// /// Set a short description for the widget. Generally, it is a good idea to /// define this value. /// /// The short message can also be set using the base_widget constructor. /// void message(std::string); /// /// Set a short translatable description for the widget. Generally, it is a good idea to /// define this value. /// /// The short message can also be set using the base_widget constructor. /// void message(locale::message const &); /// /// Set the error message that is displayed for invalid widgets. /// /// If it is not set, a simple "*" is shown instead. /// void error_message(std::string); /// /// Set the translatable error message that is displayed for invalid widgets. /// /// If it is not set, a simple "*" is shown instead. /// void error_message(locale::message const &); /// /// Set a longer help message that describes this widget. /// void help(std::string); /// /// Set a translatable help message that describes this widget. /// void help(locale::message const &msg); /// /// Set general HTML attributes that are not directly supported /// For example: /// /// \code /// my_widget.attributes_string("style='direction:rtl' onclick='return foo()'"); /// \endcode /// /// This string is inserted as-is just after render_input_start. /// void attributes_string(std::string v); /// /// Render the full widget together with error messages and decorations as paragraphs /// or table elements to the output set in \a cppcms::form_context::out(). /// virtual void render(form_context &context); /// /// This is a virtual member function that should be implemented by each widget. /// It executes the actual rendering of the HTML form. /// virtual void render_input(form_context &context) = 0; /// /// Clear the form. It also calls set(false). /// virtual void clear(); /// /// Validate the form. If not overridden, it sets the widget to \a valid. /// virtual bool validate(); /// /// Render standard common attributes like \a id, \a name, \a disabled, etc. /// virtual void render_attributes(form_context &context); /// /// Set the parent of this widget. It is used internally; you should not use it. It is called /// when the form is added or attached to another form. /// virtual void parent(base_form *subform); /// /// Get the parent of this form. If this is the topmost form, NULL is returned. /// It is assumed that the parent is always a form. /// virtual form *parent(); /// /// This function should be called before actual loading /// of widgets, it performs cross widgets validation /// and causes automatic generation of undefined names /// void pre_load(http::context &); protected: /// /// This function should be called by overloadeding the load/render methods /// before the loading/rendering starts. /// void auto_generate(form_context *context = 0); private: void generate(int position,form_context *context = 0); std::string id_; std::string name_; locale::message message_; locale::message error_message_; locale::message help_; std::string attr_; form *parent_; uint32_t is_valid_ : 1; uint32_t is_set_ : 1; uint32_t is_disabled_ : 1; uint32_t is_readonly_ : 1; uint32_t is_generation_done_ : 1; uint32_t has_message_ : 1; uint32_t has_error_ : 1; uint32_t has_help_ : 1; CPPCMS_UNUSED_MEMBER uint32_t reserverd_ : 24; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This widget is used as base for text input fields. /// /// This widget is used as the base class for other widgets that are used for /// text input like: \ref text, \ref textarea, etc. /// /// This widget does much more than reading simple text data from the POST /// or GET form. It also performs charset validation. /// class CPPCMS_API base_text : virtual public base_widget { public: base_text(); virtual ~base_text(); /// /// Get the string that contains the input value of the widget. /// std::string value(); /// /// Set the widget content to the value \a v before rendering. /// void value(std::string v); /// /// Inform the validator that this text widget should contain some text. /// It is similar to limits(1,-1). /// void non_empty(); /// /// Set the minimum and maximum limits of the text size. Note: max == -1 indicates that there /// is no maximum limit; min==0 indicates that there is no minimum limit. /// /// Note: these numbers represent the length in Unicode code points (even if the encoding /// is not Unicode). If the character set validation is disabled, then these numbers represent /// the number of octets in the string. /// void limits(int min,int max); /// /// Get the minimum and maximum size limits, /// std::pair limits(); /// /// Inform the validator whether it should check the validity of the charset. /// The default is enabled (true). /// /// Generally you should not use this option to disable the charset validation /// unless you want to load some raw data as /// form input, or the character set is different from the one defined in the locale. /// void validate_charset(bool ); /// /// Return true if the charset validation is enabled. /// bool validate_charset(); /// /// Validate the widget content according to the rules and to the charset encoding. /// /// Notes: /// /// - The charset validation is very efficient for variable length UTF-8 encoding as well as /// for most popular fixed length encodings like ISO-8859-*, windows-125* and koi8*. /// For other encodings, character set conversion is used for the actual validation. /// - Special characters (that are not allowed in HTML) are assumed to be forbidden, even if they are /// valid code points (like NUL = 0 or DEL=127). /// virtual bool validate(); /// /// Load the widget for http::context. It uses the locale given in the context to /// validate the text. /// virtual void load(http::context &); private: std::string value_; int low_; int high_; bool validate_charset_; size_t code_points_; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This class represents a basic widget that generates HTML form elements /// the widgets that use the HTML tag. /// /// It allows you to create your own widgets more easily. It does most of job required to /// generate the HTML. The user is only required to generate the actual value like /// value="10.34" as with a numeric widget. /// class CPPCMS_API base_html_input : virtual public base_widget { public: /// /// Create a new instance. \a type is the HTML type tag of the input element, for example "text" or /// "password". /// base_html_input(std::string const &type); /// /// Virtual destructor. /// virtual ~base_html_input(); /// /// This function generates the actual HTML. It calls render_value where needed. /// virtual void render_input(form_context &context); protected: /// /// Write the actual value of the HTML tag. Derived classes must implement this. /// virtual void render_value(form_context &context) = 0; private: struct _data; booster::hold_ptr<_data> d; std::string type_; }; /// /// \brief This class represents an HTML form input element of type text. /// class CPPCMS_API text : public base_html_input, public base_text { public: /// /// Create a text field widget. /// text(); /// /// This constructor is provided for use by derived classes where it is required /// to change the type of the widget, like text, password, etc. /// text(std::string const &type); ~text(); /// /// Set the HTML size attribute of the widget. /// void size(int n); /// /// Get the HTML size attribute size of the widget. It returns -1 if it is undefined. /// int size(); virtual void render_attributes(form_context &context); virtual void render_value(form_context &context); private: int size_; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This widget represents a hidden input form element. It is used to provide /// information invisible to the user. /// /// I has the same properties as a text widget has but it does not render any HTML /// for message(), help() and other informational types. /// /// When you render the form in templates, it is a good idea to render it separately /// to make sure that no invalid HTML is created. /// class CPPCMS_API hidden : public text { public: hidden(); ~hidden(); /// /// Render the HTML of the widget. It overrides /// the default HTML rendering as hidden widget /// is never displayed. /// virtual void render(form_context &context); private: struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This text widget behaves similarly to the text widget but uses /// the \c textarea HTML tag rather than the \c input HTML tag. /// class CPPCMS_API textarea : public base_text { public: textarea(); ~textarea(); /// /// Get the number of rows in the textarea. The default is -1 -- undefined. /// int rows(); /// /// Get the number of columns in the textarea. The default is -1 -- undefined. /// int cols(); /// /// Set the number of rows in the textarea. /// void rows(int n); /// /// Set the number of columns in the textarea. /// void cols(int n); virtual void render_input(form_context &context); private: int rows_,cols_; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief Widget for number input. It is a template class that assumes that T is a number. /// /// This class parses the input and checks if it is input text is a valid /// numeric value. If it is valid, the set() would return true /// be true. /// /// If the value was not defined, access to value() will throw an exception. /// template class numeric: public base_html_input { public: numeric() : base_html_input("text"), check_low_(false), check_high_(false), non_empty_(false) { } /// /// Inform the validator that this widget should contain some value. /// void non_empty() { non_empty_=true; } /// /// Get numeric value that was loaded from the POST or /// GET data. /// /// \note if the value was not set (empty field for example) /// then this function will throw. So it is good idea to /// check if \ref set() returns true before using this /// function. /// T value() { if(!set()) throw cppcms_error("Value not loaded"); return value_; } /// /// Set the value of the widget. /// void value(T v) { set(true); value_=v; } /// /// Set the minimum valid value. /// void low(T a) { min_=a; check_low_=true; non_empty(); } /// /// Set the maximum valid value. /// void high(T b) { max_=b; check_high_=true; non_empty(); } /// /// Same as low(a); high(b); /// void range(T a,T b) { low(a); high(b); } /// /// Render the first part of the widget. /// virtual void render_value(form_context &context) { if(set()) context.out()<<"value=\""<second; if(loaded_string_.empty()) return; std::istringstream ss(loaded_string_); ss.imbue(context.locale()); ss>>value_; if(ss.fail() || !ss.eof()) valid(false); else set(true); } } /// /// Validate the widget. /// virtual bool validate() { if(!valid()) return false; if(!set()) { if(non_empty_) { valid(false); return false; } return true; } if(check_low_ && value_ max_) { valid(false); return false; } return true; } private: T min_,max_,value_; bool check_low_; bool check_high_; bool non_empty_; std::string loaded_string_; }; /// /// \brief The password widget is a simple text widget with few, obvious differences. // class CPPCMS_API password: public text { public: password(); ~password(); /// /// Set the equality constraint to another password widget. This password should be /// equal to the one in \a p2. It is usefull when creating new passwords: if the passwords /// are not equal, the validation will fail. /// void check_equal(password &p2); virtual bool validate(); private: struct _data; booster::hold_ptr<_data> d; password *password_to_check_; }; /// /// \brief This class is extending a simple text widget by using additional regular expression validation. /// class CPPCMS_API regex_field : public text { public: regex_field(); /// /// Create a widget using the regular expression \a e. /// regex_field(booster::regex const &e); /// /// Create a widget using the regular expression \a e. /// regex_field(std::string const &e); /// /// Set the regular expression. /// void regex(booster::regex const &e); ~regex_field(); virtual bool validate(); private: booster::regex expression_; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This widget checks that the input is a valid email address. /// class CPPCMS_API email : public regex_field { public: email(); ~email(); private: struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This class represent an HTML checkbox input element. /// class CPPCMS_API checkbox: public base_html_input { public: /// /// The constructor that allows you to specify \c type HTML /// attribute. It is passed to the constructor of the /// \ref base_html_input class. /// checkbox(std::string const &type); /// /// Default constructor. /// checkbox(); virtual ~checkbox(); /// /// Return true if the checkbox was checked (selected). /// bool value(); /// /// Set the state as \a checked. /// void value(bool is_set); /// /// Get the unique identification string of the checkbox. /// std::string identification(); /// /// Set the unique identification string of the checkbox. It is useful when you want to /// have many options with the same name. /// void identification(std::string const &); virtual void render_value(form_context &context); virtual void load(http::context &context); private: struct _data; booster::hold_ptr<_data> d; std::string identification_; bool value_; }; /// /// \brief This widget represents an HTML multiple select form element. /// class CPPCMS_API select_multiple : public base_widget { public: select_multiple(); ~select_multiple(); /// /// Add to the multiple select a new option with the display name \a msg, and specify if it is initially /// selected. The default is \a false. /// void add(std::string const &msg,bool selected=false); /// /// Add to the multiple select a new option with the display name \a msg, and specify if it is initially /// selected (the default is \a false), providing a unique identification string to use as the element's \a id. /// void add(std::string const &msg,std::string const &id,bool selected=false); /// /// Add to the multiple select a new option with the localized display name \a msg, and specify if it is initially /// selected. The default is \a false. /// void add(locale::message const &msg,bool selected=false); /// /// Add to the multiple select a new option with the localized display name \a msg, and specify if it is initially /// selected (the default is \a false), providing a unique identification string to use as the element's \a id. /// void add(locale::message const &msg,std::string const &id,bool selected=false); /// /// Get the mapping of all the selected items according to the order they where added to the multiple select list. /// std::vector selected_map(); /// /// Get all the selected items ids according to the order they where added to the list. If no /// specific id was given, a string like "0", "1"... will be used. /// std::set selected_ids(); /// /// Get the minimum amount of options that can be chosen. The default is \a 0. /// unsigned at_least(); /// /// Set the minimum amount of options that can be chosen. The default is \a 0. /// void at_least(unsigned v); /// /// Get the maximum amount of options that can be chosen. The default is unlimited. /// unsigned at_most(); /// /// Set the maximum amount of options that can be chosen. The default is unlimited. /// void at_most(unsigned v); /// /// Same as at_least(1). /// void non_empty(); /// /// Get the number of rows used to display the widget. The default is \a 0 -- undefined. /// unsigned rows(); /// /// Set the number of rows used to display the widget. The default is \a 0 -- undefined. /// void rows(unsigned n); virtual void render_input(form_context &context); virtual bool validate(); virtual void load(http::context &context); virtual void clear(); private: struct _data; booster::hold_ptr<_data> d; struct element { element(); element(std::string const &v,locale::message const &msg,bool sel); element(std::string const &v,std::string const &msg,bool sel); uint32_t selected : 1; uint32_t need_translation : 1; uint32_t original_select : 1; CPPCMS_UNUSED_MEMBER uint32_t reserved : 29; std::string id; std::string str_option; locale::message tr_option; friend std::ostream &operator<<(std::ostream &out,element const &el); }; std::vector elements_; unsigned low_; unsigned high_; unsigned rows_; }; /// /// \brief This is the base class for "select" like widgets which include dropdown lists /// and radio button sets. /// class CPPCMS_API select_base : public base_widget { public: select_base(); virtual ~select_base(); /// /// Add a new entry to the selection list. /// void add(std::string const &string); /// /// Add to the selection list a new entry with the unique identification string \a id. /// void add(std::string const &string,std::string const &id); /// /// Add a new localized entry to the selection list. /// void add(locale::message const &msg); /// /// Add to the selection list a new localized entry with the unique identification string \a id. /// void add(locale::message const &msg,std::string const &id); /// /// Return the number of the selected entry in the list. Entries are numbered starting from 0. -1 indicates that nothing /// was selected. /// int selected(); /// /// Return the identification string of the selected entry in the list. An empty string indicates that /// nothing was selected. /// std::string selected_id(); /// /// Select the entry numbered \a no. /// void selected(int no); /// /// Select the entry with the identification string \a id. /// void selected_id(std::string id); /// /// Require that one item in the list should be selected (for the validation). /// void non_empty(); virtual void render_input(form_context &context) = 0; virtual bool validate(); virtual void load(http::context &context); virtual void clear(); protected: struct CPPCMS_API element { element(); element(std::string const &v,locale::message const &msg); element(std::string const &v,std::string const &msg); element(element const &); element const &operator=(element const &); ~element(); uint32_t need_translation : 1; CPPCMS_UNUSED_MEMBER uint32_t reserved : 31; std::string id; std::string str_option; locale::message tr_option; private: struct _data; booster::copy_ptr<_data> d; }; std::vector elements_; private: struct _data; booster::hold_ptr<_data> d; int selected_; int default_selected_; uint32_t non_empty_ : 1; CPPCMS_UNUSED_MEMBER uint32_t reserverd : 32; }; /// /// \brief The widget that uses a drop-down list for selection. /// class CPPCMS_API select : public select_base { public: select(); virtual ~select(); virtual void render_input(form_context &context); private: struct _data; booster::hold_ptr<_data> d; }; /// /// \brief The widget that uses a set of radio buttons.. /// class CPPCMS_API radio : public select_base { public: radio(); virtual ~radio(); virtual void render_input(form_context &context); /// /// Return the rendering order /// bool vertical(); /// /// Set rendering order of the list one behind other (default) /// or in same line. /// /// Baiscally it defines whether the radio buttons should /// appear in row (false) or in column (true). /// void vertical(bool); private: uint32_t vertical_ : 1; CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 31; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief This class represents a file upload form entry. /// /// If the file was not uploaded, set() will be false and /// an attempt to access the member function value() will throw. /// class CPPCMS_API file : public base_html_input { public: /// /// Ensure that a file is uploaded (for the validation). /// void non_empty(); /// /// Set the minimum and maximum limits for the file size. Note: max == -1 indicates that there /// is no maximum limit; min==0 indicates that there is no minimum limit. /// /// void limits(int min,int max); /// /// Get the minimum and maximum size limits. /// std::pair limits(); /// /// Set the filename validation pattern. For example ".*\\.(jpg|jpeg|png)". /// /// Please, note that it is a good idea to check magic numbers as well /// and not rely on file name only. /// /// See add_valid_magic() function /// void filename(booster::regex const &fn); /// /// Get the regular expression for the filename validation. /// booster::regex filename(); /// /// Validate or not the filename's charset. The default is \a true. /// void validate_filename_charset(bool); /// /// Get the validation option for the filename's charset. /// bool validate_filename_charset(); /// /// Get the uploaded file. This throws cppcms_error if set() == false, i.e. if no file /// was uploaded. /// booster::shared_ptr value(); /// /// Set the required file mime type. /// void mime(std::string const &); /// /// Set the regular expression to validate the mime type. /// void mime(booster::regex const &expr); /// /// Add a string that represents a valid magic number that shoud exist on begging of file. /// /// By default no tests are performed. /// void add_valid_magic(std::string const &); virtual void load(http::context &context); virtual void render_value(form_context &context); virtual bool validate(); file(); ~file(); private: int size_min_; int size_max_; std::vector magics_; std::string mime_string_; booster::regex mime_regex_; booster::regex filename_regex_; uint32_t check_charset_ : 1; uint32_t check_non_empty_ : 1; CPPCMS_UNUSED_MEMBER uint32_t reserved_ : 30; booster::shared_ptr file_; struct _data; booster::hold_ptr<_data> d; }; /// /// \brief Submit button widget. /// class CPPCMS_API submit : public base_html_input { public: submit(); ~submit(); /// /// Return true if this specific button was pressed. /// bool value(); /// /// Set the text on the button. /// void value(std::string val); /// /// Set the text on the button. /// void value(locale::message const &msg); virtual void render_value(form_context &context); virtual void load(http::context &context); private: struct _data; booster::hold_ptr<_data> d; bool pressed_; locale::message value_; }; } // widgets } //cppcms #endif // CPPCMS_FORM_H