ChipMaster's trial hacks on C++CMS starting with v1.2.1. Not sure I'll follow on with the v2 since it looks to be breaking and mostly frivolous.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1264 lines
27 KiB

  1. #ifndef CPPCMS_FORM_H
  2. #define CPPCMS_FORM_H
  3. #include "defs.h"
  4. #include "noncopyable.h"
  5. #include <string>
  6. #include <set>
  7. #include <map>
  8. #include <list>
  9. #include <vector>
  10. #include <stack>
  11. #include <ostream>
  12. #include <sstream>
  13. #include "http_context.h"
  14. #include "http_request.h"
  15. #include "http_response.h"
  16. #include "copy_ptr.h"
  17. #include "cppcms_error.h"
  18. #include "util.h"
  19. #include "regex.h"
  20. #include "localization.h"
  21. namespace cppcms {
  22. namespace widgets {
  23. class base_widget;
  24. }
  25. struct form_flags {
  26. typedef enum {
  27. as_html = 0, ///< render form/widget as ordinary HTML
  28. as_xhtml= 1, ///< render form/widget as XHTML
  29. } html_type;
  30. typedef enum {
  31. as_p = 0 , ///< Render each widget using paragraphs
  32. as_table= 1 , ///< Render each widget using table
  33. as_ul = 2 , ///< Render each widget using unordered list
  34. as_dl = 3 , ///< Render each widget using definitions list
  35. as_space= 4 ///< Render each widget using simple blank space separators
  36. // to be extended
  37. } html_list_type;
  38. typedef enum {
  39. first_part = 0, ///< Render part 1; HTML attributes can be inserted after it
  40. second_part = 1 ///< Render part 2 -- compete part 1.
  41. } widget_part_type;
  42. };
  43. class CPPCMS_API form_context : public form_flags
  44. {
  45. public:
  46. form_context();
  47. form_context(form_context const &other);
  48. form_context const &operator = (form_context const &other);
  49. form_context( std::ostream &output,
  50. html_type ht = form_flags::as_html,
  51. html_list_type hlt=form_flags::as_p);
  52. ~form_context();
  53. void html(html_type t);
  54. void html_list(html_list_type t);
  55. void widget_part(widget_part_type t);
  56. void out(std::ostream &out);
  57. html_type html() const;
  58. html_list_type html_list() const;
  59. widget_part_type widget_part() const;
  60. std::ostream &out() const;
  61. private:
  62. uint32_t html_type_;
  63. uint32_t html_list_type_;
  64. uint32_t widget_part_type_;
  65. std::ostream *output_;
  66. uint32_t reserved_1;
  67. uint32_t reserved_2;
  68. struct data;
  69. util::hold_ptr<data> d;
  70. };
  71. ///
  72. /// \brief This class is base class of any form or form-widget used in CppCMS.
  73. ///
  74. /// It provides abstract basic operations that every widget or form should implement
  75. ///
  76. class CPPCMS_API base_form : public form_flags {
  77. public:
  78. ///
  79. /// Render the widget to std::ostream \a output with control flags \a flags.
  80. /// Usually this function is called directly by template rendering functions
  81. ///
  82. virtual void render(form_context &context) = 0;
  83. ///
  84. /// Load the information of form from the provided http::context \a context.
  85. /// User calls this function for loading all information from the raw POST/GET
  86. /// form to internal widget representation.
  87. ///
  88. virtual void load(http::context &context) = 0;
  89. ///
  90. /// Validate the form according to defined rules. If all checks are OK
  91. /// true is returned. If some widget or form fails, false is returned.
  92. ///
  93. virtual bool validate() = 0;
  94. ///
  95. /// Clear the form from all user provided data.
  96. ///
  97. virtual void clear() = 0;
  98. ///
  99. /// Set parent of this form. Used internaly, should not be used
  100. ///
  101. virtual void parent(base_form *subform) = 0;
  102. ///
  103. /// Get parent of this form. If this is topmost form, NULL is returned
  104. ///
  105. virtual base_form *parent() = 0;
  106. base_form();
  107. virtual ~base_form();
  108. };
  109. ///
  110. /// \brief The \a form is a container that used to collect other widgets and forms to single unit
  111. ///
  112. /// Generally various widgets and forms are combined into single form in order to simplify rendering
  113. /// and validation of forms that include more then one widget
  114. ///
  115. class CPPCMS_API form : public util::noncopyable,
  116. public base_form
  117. {
  118. public:
  119. form();
  120. virtual ~form();
  121. ///
  122. /// Render all widgets and sub-forms to \a output, using
  123. /// base_form \a flags
  124. ///
  125. virtual void render(form_context &context);
  126. ///
  127. /// Load all information from widgets from http::context \a cont
  128. ///
  129. virtual void load(http::context &cont);
  130. ///
  131. /// validate all subforms and widgets. If at least one of them fails,
  132. /// false is returned. Otherwise, true is returned.
  133. ///
  134. virtual bool validate();
  135. ///
  136. /// Clear all subforms and widgets for all loaded data.
  137. ///
  138. virtual void clear();
  139. ///
  140. /// adds \a subform to form, the ownership is not transferred to
  141. /// to the parent
  142. ///
  143. void add(form &subform);
  144. ///
  145. /// add \a subform to form, the ownership is transferred to
  146. /// the parent and subform will be destroyed together with
  147. /// the parent
  148. ///
  149. void attach(form *subform);
  150. ///
  151. /// adds \a widget to form, the ownership is not transferred to
  152. /// to the parent
  153. ///
  154. void add(widgets::base_widget &widget);
  155. ///
  156. /// add \a widget to form, the ownership is transferred to
  157. /// the parent the widget will be destroyed together with
  158. /// the parent form
  159. ///
  160. void attach(widgets::base_widget *widget);
  161. ///
  162. /// Shortcut to \a add
  163. ///
  164. inline form &operator + (form &f)
  165. {
  166. add(f);
  167. return *this;
  168. }
  169. ///
  170. /// Shortcut to \a add
  171. ///
  172. inline form &operator + (widgets::base_widget &f)
  173. {
  174. add(f);
  175. return *this;
  176. }
  177. ///
  178. /// Set parent of this form. Used internaly, should not be used. It is called
  179. /// when the form is added or attached to other form.
  180. ///
  181. virtual void parent(base_form *subform);
  182. ///
  183. /// Get parent of this form. If this is topmost form, NULL is returned
  184. /// It is assumed that the parent is always form.
  185. ///
  186. virtual form *parent();
  187. ///
  188. /// \brief Input iterator that is used to iterate over all widgets of the form
  189. ///
  190. /// This class is mainly used by templates framework for widgets rendering. It
  191. /// walks on all widgets and subforms recursively.
  192. ///
  193. /// Note: it walks over widgets only:
  194. ///
  195. /// \code
  196. /// iterator p=f.begin();
  197. /// if(p!=f.end())
  198. /// if p!=f.end() --> *p is derived from widgets::base_widget.
  199. /// \endcode
  200. ///
  201. class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget>
  202. {
  203. public:
  204. ///
  205. /// End iterator
  206. ///
  207. iterator();
  208. ///
  209. /// Create widgets iterator
  210. ///
  211. iterator(form &);
  212. ~iterator();
  213. iterator(iterator const &other);
  214. iterator const &operator = (iterator const &other);
  215. widgets::base_widget *operator->() const
  216. {
  217. return get();
  218. }
  219. widgets::base_widget &operator*() const
  220. {
  221. return *get();
  222. }
  223. bool operator==(iterator const &other) const
  224. {
  225. return equal(other);
  226. }
  227. bool operator!=(iterator const &other) const
  228. {
  229. return !equal(other);
  230. }
  231. iterator operator++(int unused)
  232. {
  233. iterator tmp(*this);
  234. next();
  235. return tmp;
  236. }
  237. iterator &operator++()
  238. {
  239. next();
  240. return *this;
  241. }
  242. private:
  243. friend class form;
  244. bool equal(iterator const &other) const;
  245. void zero();
  246. void next();
  247. widgets::base_widget *get() const;
  248. std::stack<unsigned> return_positions_;
  249. form *current_;
  250. unsigned offset_;
  251. struct data;
  252. util::copy_ptr<data> d;
  253. };
  254. ///
  255. /// Returns an iterator to the first widget.
  256. ///
  257. iterator begin();
  258. ///
  259. /// Returns the end-iterator for walking over all widgets.
  260. ///
  261. iterator end();
  262. private:
  263. friend class iterator;
  264. struct data;
  265. // Widget and ownership true mine
  266. typedef std::pair<base_form *,bool> widget_type;
  267. std::vector<widget_type> elements_;
  268. form *parent_;
  269. util::hold_ptr<data> d;
  270. };
  271. namespace widgets {
  272. ///
  273. /// \brief this class is the base class of all renderable widgets that can be
  274. /// used together with forms
  275. ///
  276. /// All cppcms widgets are derived from this class. User, who want to create
  277. /// its own custom widgets must derive them from this class
  278. ///
  279. class CPPCMS_API base_widget :
  280. public base_form,
  281. public util::noncopyable
  282. {
  283. public:
  284. ///
  285. /// Default constructor
  286. ///
  287. base_widget();
  288. virtual ~base_widget();
  289. ///
  290. /// Check if a value was assigned to widget. Usually becomes true
  291. /// when user assignees value to widget or the widget is loaded.
  292. ///
  293. bool set();
  294. ///
  295. /// After executing validation, each widget can be tested for validity
  296. ///
  297. bool valid();
  298. ///
  299. /// Get html id attribute
  300. ///
  301. std::string id();
  302. ///
  303. /// Get html name attribute
  304. ///
  305. std::string name();
  306. ///
  307. /// Get short message that would be displayed near the widget
  308. ///
  309. locale::message message();
  310. ///
  311. /// Check if message is set
  312. ///
  313. bool has_message();
  314. ///
  315. /// Get associated error message that would be displayed near the widget
  316. /// if widget validation failed.
  317. ///
  318. locale::message error_message();
  319. ///
  320. /// Check if error message is set
  321. ///
  322. bool has_error_message();
  323. ///
  324. /// Get long description for specific widget
  325. ///
  326. locale::message help();
  327. ///
  328. /// Check if help message is set
  329. ///
  330. bool has_help();
  331. ///
  332. /// Get disabled html attribute
  333. ///
  334. bool disabled();
  335. ///
  336. /// Set/Unset disabled html attribute
  337. ///
  338. void disabled(bool);
  339. ///
  340. /// Get the general user defined attributes string that can be added to widget
  341. ///
  342. std::string attributes_string();
  343. ///
  344. /// Set the existence of content for widget. By default the widget is not set.
  345. /// Any value fetch from "unset" widget by convention should throw an exception
  346. /// Calling set with true -- changes state to "set" and with false to "unset"
  347. ///
  348. void set(bool);
  349. ///
  350. /// Set validity state of widget. By default the widget is valid. When it
  351. /// passes validation its validity state is changed by calling this function
  352. ///
  353. /// Note: widget maybe not-set but still valid and it may be set but not-valid
  354. ///
  355. void valid(bool);
  356. ///
  357. /// Set html id attribute of the widget
  358. ///
  359. void id(std::string);
  360. ///
  361. /// Set html name attribute of the widget. Note: if this attribute
  362. /// is not set, the widget would not be able to be loaded from POST/GET
  363. /// data.
  364. ///
  365. void name(std::string);
  366. ///
  367. /// Set short description for the widget. Generally it is good idea to
  368. /// define this value.
  369. ///
  370. /// Short message can be also set using base_widget constructor
  371. ///
  372. void message(std::string);
  373. ///
  374. /// Set short translatable description for the widget. Generally it is good idea to
  375. /// define this value.
  376. ///
  377. /// Short message can be also set using base_widget constructor
  378. ///
  379. void message(locale::message const &);
  380. ///
  381. /// Set error message that is displayed for invalid widgets.
  382. ///
  383. /// If it is not set, simple "*" is shown
  384. ///
  385. void error_message(std::string);
  386. ///
  387. /// Set translatable error message that is displayed for invalid widgets.
  388. ///
  389. /// If it is not set, simple "*" is shown
  390. ///
  391. void error_message(locale::message const &);
  392. ///
  393. /// Set longer help message that describes this widget
  394. ///
  395. void help(std::string);
  396. ///
  397. /// Set translatable help message that describes this widget
  398. ///
  399. void help(locale::message const &msg);
  400. ///
  401. /// Set general html attributes that are not supported
  402. /// directly. For example:
  403. ///
  404. /// \code
  405. /// my_widget.attributes_string("style='direction:rtl' onclick='return foo()'");
  406. /// \endcode
  407. ///
  408. /// This string is inserted as-is just behind render_input_start
  409. ///
  410. void attributes_string(std::string v);
  411. ///
  412. /// Render full widget with error messages and decorations as paragraphs
  413. /// or table elements to \a output
  414. ///
  415. virtual void render(form_context &context);
  416. ///
  417. /// This is a virtual member function that should be implemented by each widget
  418. /// It executes actual rendering of the input HTML form
  419. ///
  420. virtual void render_input(form_context &context) = 0;
  421. ///
  422. /// Clean the form. Calls set(false) as well
  423. ///
  424. virtual void clear();
  425. ///
  426. /// Validate form. If not overridden it sets widget to valid
  427. ///
  428. virtual bool validate();
  429. ///
  430. /// Render standard common attributes like id, name, disabled etc.
  431. ///
  432. virtual void render_attributes(form_context &context);
  433. ///
  434. /// Set parent of this widget. Used internaly, should not be used. It is called
  435. /// when the form is added or attached to other form.
  436. ///
  437. virtual void parent(base_form *subform);
  438. ///
  439. /// Get parent of this form. If this is topmost form, NULL is returned
  440. /// Note widget is assumed to be assigned to forms only
  441. ///
  442. virtual form *parent();
  443. protected:
  444. ///
  445. /// This function should be called by overloaded load/render methods
  446. /// before rendering/loading starts
  447. ///
  448. void auto_generate(form_context *context = 0);
  449. private:
  450. void generate(int position,form_context *context = 0);
  451. std::string id_;
  452. std::string name_;
  453. locale::message message_;
  454. locale::message error_message_;
  455. locale::message help_;
  456. std::string attr_;
  457. form *parent_;
  458. uint32_t is_valid_ : 1;
  459. uint32_t is_set_ : 1;
  460. uint32_t is_disabled_ : 1;
  461. uint32_t is_generation_done_ : 1;
  462. uint32_t has_message_ : 1;
  463. uint32_t has_error_ : 1;
  464. uint32_t has_help_ : 1;
  465. uint32_t reserverd_ : 25;
  466. struct data;
  467. util::hold_ptr<data> d;
  468. };
  469. ///
  470. /// \brief this is the widget that is used as base for text input field representation
  471. ///
  472. /// This widget is used as base class for other widgets that are used for
  473. /// text input like: text, textarea, etc.
  474. ///
  475. /// This widget does much more then reading simple filed data from the POST
  476. /// or GET form, it performs charset validation and if required conversion
  477. /// to and from Unicode charset to locale charset.
  478. ///
  479. class CPPCMS_API base_text : virtual public base_widget {
  480. public:
  481. base_text();
  482. virtual ~base_text();
  483. ///
  484. /// Get the string that contains input value of the widget.
  485. ///
  486. std::string value();
  487. ///
  488. /// Set the widget content before rendering, the value \a v
  489. ///
  490. void value(std::string v);
  491. ///
  492. /// Acknowledge the validator that this text widget should contain some text.
  493. /// similar to limits(1,-1)
  494. ///
  495. void non_empty();
  496. ///
  497. /// Set minimum and maximum limits for text size. Note max == -1 indicates that there
  498. /// is no maximal limit, min==0 indicates that there is no minimal limit.
  499. ///
  500. /// Note: these numbers represent the length in Unicode code points (even if the encoding
  501. /// is not Unicode). If character set validation is disabled, then these number represent
  502. /// the number of octets in the string.
  503. ///
  504. void limits(int min,int max);
  505. ///
  506. /// Get minimal and maximal size limits,
  507. ///
  508. std::pair<int,int> limits();
  509. ///
  510. /// Acknowledge the validator if it should not check the validity of the charset.
  511. /// Default -- enabled
  512. ///
  513. /// Generally you should not use this option unless you want to load some raw data as
  514. /// form input, or the character set is different from the defined in locale.
  515. ///
  516. void validate_charset(bool );
  517. ///
  518. /// Returns true if charset validation is enabled.
  519. ///
  520. bool validate_charset();
  521. ///
  522. /// Validate the widget content according to rules and charset encoding.
  523. ///
  524. /// Notes:
  525. ///
  526. /// - The charset validation is very efficient for variable length UTF-8 encoding,
  527. /// and most popular fixed length ISO-8859-*, windows-125* and koi8* encodings, for other
  528. /// encodings iconv conversion is used for actual validation.
  529. /// - Special characters (that not allowed in HTML) are assumed as forbidden, even if they are
  530. /// valid code points (like NUL = 0 or DEL=127).
  531. ///
  532. virtual bool validate();
  533. ///
  534. /// Load the widget for http::context. It used the locale given in the context for
  535. /// validation of text.
  536. ///
  537. virtual void load(http::context &);
  538. private:
  539. std::string value_;
  540. int low_;
  541. int high_;
  542. bool validate_charset_;
  543. size_t code_points_;
  544. struct data;
  545. util::hold_ptr<data> d;
  546. };
  547. class CPPCMS_API base_html_input : virtual public base_widget {
  548. public:
  549. base_html_input(std::string const &type);
  550. virtual ~base_html_input();
  551. virtual void render_input(form_context &context);
  552. protected:
  553. virtual void render_value(form_context &context) = 0;
  554. private:
  555. struct data;
  556. util::hold_ptr<data> d;
  557. std::string type_;
  558. };
  559. ///
  560. /// \brief This class represents html input of type text
  561. ///
  562. class CPPCMS_API text : public base_html_input, public base_text
  563. {
  564. public:
  565. ///
  566. /// Create text field widget
  567. ///
  568. text();
  569. ///
  570. /// This constructor is provided for use by derived classes where it is required
  571. /// to change the type of widget, like text, password, etc.
  572. ///
  573. text(std::string const &type);
  574. ~text();
  575. ///
  576. /// Set html attribute size of the widget
  577. ///
  578. void size(int n);
  579. ///
  580. /// Get html attribute size of the widget, -1 undefined
  581. ///
  582. int size();
  583. virtual void render_attributes(form_context &context);
  584. virtual void render_value(form_context &context);
  585. private:
  586. int size_;
  587. struct data;
  588. util::hold_ptr<data> d;
  589. };
  590. class CPPCMS_API textarea : public base_text
  591. {
  592. public:
  593. textarea();
  594. ~textarea();
  595. ///
  596. /// Get number of rows in textarea -- default -1 -- undefined
  597. ///
  598. int rows();
  599. ///
  600. /// Get number of columns in textarea -- default -1 -- undefined
  601. ///
  602. int cols();
  603. ///
  604. /// Set number of rows in textarea
  605. ///
  606. void rows(int n);
  607. ///
  608. /// Set number of columns in textarea
  609. ///
  610. void cols(int n);
  611. virtual void render_input(form_context &context);
  612. private:
  613. int rows_,cols_;
  614. struct data;
  615. util::hold_ptr<data> d;
  616. };
  617. ///
  618. /// \brief Widget for number input. It is template class that assumes that T is number
  619. ///
  620. template<typename T>
  621. class numeric: public base_html_input {
  622. public:
  623. numeric() :
  624. base_html_input("text"),
  625. check_low_(false),
  626. check_high_(false),
  627. non_empty_(false)
  628. {
  629. }
  630. ///
  631. /// Defines that this widget should have some value
  632. ///
  633. void non_empty()
  634. {
  635. non_empty_=true;
  636. }
  637. ///
  638. /// Get loaded widget value
  639. ///
  640. T value()
  641. {
  642. if(!set())
  643. throw cppcms_error("Value not loaded");
  644. return value_;
  645. }
  646. ///
  647. /// Set widget value
  648. ///
  649. void value(T v)
  650. {
  651. set(true);
  652. value_=v;
  653. }
  654. ///
  655. /// Set minimal input number value
  656. ///
  657. void low(T a)
  658. {
  659. min_=a;
  660. check_low_=true;
  661. non_empty();
  662. }
  663. ///
  664. /// Set maximal input number value
  665. ///
  666. void high(T b)
  667. {
  668. max_=b;
  669. check_high_=true;
  670. non_empty();
  671. }
  672. ///
  673. /// Same as low(a); high(b);
  674. ///
  675. void range(T a,T b)
  676. {
  677. low(a);
  678. high(b);
  679. }
  680. ///
  681. /// Render first part of widget
  682. ///
  683. virtual void render_value(form_context &context)
  684. {
  685. if(set())
  686. context.out()<<"value=\""<<value_<<"\" ";
  687. else
  688. context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
  689. }
  690. virtual void clear()
  691. {
  692. base_html_input::clear();
  693. loaded_string_.clear();
  694. }
  695. ///
  696. /// Load widget data
  697. ///
  698. virtual void load(http::context &context)
  699. {
  700. auto_generate();
  701. loaded_string_.clear();
  702. set(false);
  703. valid(true);
  704. http::request::form_type::const_iterator p;
  705. http::request::form_type const &request=context.request().post_or_get();
  706. p=request.find(name());
  707. if(p==request.end()) {
  708. return;
  709. }
  710. else {
  711. loaded_string_=p->second;
  712. if(loaded_string_.empty())
  713. return;
  714. std::istringstream ss(loaded_string_);
  715. ss.imbue(context.locale());
  716. ss>>value_;
  717. if(ss.fail() || !ss.eof())
  718. valid(false);
  719. else
  720. set(true);
  721. }
  722. }
  723. ///
  724. /// Validate widget
  725. ///
  726. virtual bool validate()
  727. {
  728. if(!valid())
  729. return false;
  730. if(!set()) {
  731. if(non_empty_) {
  732. valid(false);
  733. return false;
  734. }
  735. return true;
  736. }
  737. if(check_low_ && value_ <min_) {
  738. valid(false);
  739. return false;
  740. }
  741. if(check_high_ && value_ > max_) {
  742. valid(false);
  743. return false;
  744. }
  745. return true;
  746. }
  747. private:
  748. T min_,max_,value_;
  749. bool check_low_;
  750. bool check_high_;
  751. bool non_empty_;
  752. std::string loaded_string_;
  753. };
  754. ///
  755. /// \brief The password widget is a simple text widget with some different
  756. //
  757. class CPPCMS_API password: public text {
  758. public:
  759. password();
  760. ~password();
  761. ///
  762. /// Set equality constraint to password widget -- this password should be
  763. /// equal to other one \a p2. Usefull for creation of new passwords -- if passwords
  764. /// are not equal, validation would fail
  765. ///
  766. void check_equal(password &p2);
  767. virtual bool validate();
  768. private:
  769. struct data;
  770. util::hold_ptr<data> d;
  771. password *password_to_check_;
  772. };
  773. ///
  774. /// \brief This class is extinction of text widget that validates it using additional regular expression
  775. ///
  776. class CPPCMS_API regex_field : public text {
  777. public:
  778. regex_field();
  779. ///
  780. /// Create widget using regular expression \a e
  781. ///
  782. regex_field(util::regex const &e);
  783. ///
  784. /// Set regular expression
  785. ///
  786. void regex(util::regex const &e);
  787. ~regex_field();
  788. virtual bool validate();
  789. private:
  790. util::regex const *expression_;
  791. struct data;
  792. util::hold_ptr<data> d;
  793. };
  794. ///
  795. /// \brief widget that checks that input is valid e-mail
  796. ///
  797. class CPPCMS_API email : public regex_field {
  798. public:
  799. email();
  800. ~email();
  801. private:
  802. static util::regex const email_expression_;
  803. struct data;
  804. util::hold_ptr<data> d;
  805. };
  806. ///
  807. /// This class represent an html checkbox input widget
  808. ///
  809. class CPPCMS_API checkbox: public base_html_input {
  810. public:
  811. ///
  812. /// The constructor that allows you to specify other type like "radio"
  813. ///
  814. checkbox(std::string const &type);
  815. ///
  816. /// Default constructor, type checkbox
  817. ///
  818. checkbox();
  819. virtual ~checkbox();
  820. ///
  821. /// Returns true of box was checked (selected)
  822. ///
  823. bool value();
  824. ///
  825. /// Set checked state
  826. ///
  827. void value(bool is_set);
  828. ///
  829. /// Get unique identification of the checkbox
  830. ///
  831. std::string identification();
  832. ///
  833. /// Set unique identification to the checkbox, useful when you want to
  834. /// have many options with same name
  835. ///
  836. void identification(std::string const &);
  837. virtual void render_value(form_context &context);
  838. virtual void load(http::context &context);
  839. private:
  840. struct data;
  841. util::hold_ptr<data> d;
  842. std::string identification_;
  843. bool value_;
  844. };
  845. ///
  846. /// Select multiple elements widget
  847. ///
  848. class CPPCMS_API select_multiple : public base_widget {
  849. public:
  850. select_multiple();
  851. ~select_multiple();
  852. ///
  853. /// Add a new option to list with display name \a msg, and specify if it is initially
  854. /// selected, default false
  855. ///
  856. void add(std::string const &msg,bool selected=false);
  857. ///
  858. /// Add a new option to list with display name \a msg, and specify if it is initially
  859. /// selected, default false, providing unique identification for the element \a id
  860. ///
  861. void add(std::string const &msg,std::string const &id,bool selected=false);
  862. ///
  863. /// Add a new option to list with localized display name \a msg, and specify if it is initially
  864. /// selected, default false
  865. ///
  866. void add(locale::message const &msg,bool selected=false);
  867. ///
  868. /// Add a new option to list with localized display name \a msg, and specify if it is initially
  869. /// selected, default false, providing unique identification for the element \a id
  870. ///
  871. void add(locale::message const &msg,std::string const &id,bool selected=false);
  872. ///
  873. /// Get the mapping of all selected items according to the order they where added to the list
  874. ///
  875. std::vector<bool> selected_map();
  876. ///
  877. /// Get all selected items ids according to the order they where added to the list, if no
  878. /// specific id was given, strings "0", "1"... would be used
  879. ///
  880. std::set<std::string> selected_ids();
  881. ///
  882. /// Get minimal amount of options that should be chosen, default = 0
  883. ///
  884. unsigned at_least();
  885. ///
  886. /// Set minimal amount of options that should be chosen, default = 0
  887. ///
  888. void at_least(unsigned v);
  889. ///
  890. /// Get maximal amount of options that should be chosen, default unlimited
  891. ///
  892. unsigned at_most();
  893. ///
  894. /// Set maximal amount of options that should be chosen, default unlimited
  895. ///
  896. void at_most(unsigned v);
  897. ///
  898. /// Same as at_least(1)
  899. ///
  900. void non_empty();
  901. ///
  902. /// Get the number of rows used for widget, default 0 -- undefined
  903. ///
  904. unsigned rows();
  905. ///
  906. /// Set the number of rows used for widget, default 0 -- undefined
  907. ///
  908. void rows(unsigned n);
  909. virtual void render_input(form_context &context);
  910. virtual bool validate();
  911. virtual void load(http::context &context);
  912. virtual void clear();
  913. private:
  914. struct data;
  915. util::hold_ptr<data> d;
  916. struct element {
  917. element();
  918. element(std::string const &v,locale::message const &msg,bool sel);
  919. element(std::string const &v,std::string const &msg,bool sel);
  920. uint32_t selected : 1;
  921. uint32_t need_translation : 1;
  922. uint32_t original_select : 1;
  923. uint32_t reserved : 29;
  924. std::string id;
  925. std::string str_option;
  926. locale::message tr_option;
  927. friend std::ostream &operator<<(std::ostream &out,element const &el);
  928. };
  929. std::vector<element> elements_;
  930. unsigned low_;
  931. unsigned high_;
  932. unsigned rows_;
  933. };
  934. class CPPCMS_API select_base : public base_widget {
  935. public:
  936. select_base();
  937. virtual ~select_base();
  938. void add(std::string const &string);
  939. void add(std::string const &string,std::string const &id);
  940. void add(locale::message const &msg);
  941. void add(locale::message const &msg,std::string const &id);
  942. int selected();
  943. std::string selected_id();
  944. void selected(int no);
  945. void selected_id(std::string id);
  946. void non_empty();
  947. virtual void render_input(form_context &context) = 0;
  948. virtual bool validate();
  949. virtual void load(http::context &context);
  950. virtual void clear();
  951. protected:
  952. struct element {
  953. element();
  954. element(std::string const &v,locale::message const &msg);
  955. element(std::string const &v,std::string const &msg);
  956. uint32_t need_translation : 1;
  957. uint32_t reserved : 31;
  958. std::string id;
  959. std::string str_option;
  960. locale::message tr_option;
  961. private:
  962. struct data;
  963. util::copy_ptr<data> d;
  964. };
  965. std::vector<element> elements_;
  966. private:
  967. struct data;
  968. util::hold_ptr<data> d;
  969. int selected_;
  970. int default_selected_;
  971. uint32_t non_empty_ : 1;
  972. uint32_t reserverd : 32;
  973. };
  974. class CPPCMS_API select : public select_base {
  975. public:
  976. select();
  977. virtual ~select();
  978. virtual void render_input(form_context &context);
  979. private:
  980. struct data;
  981. util::hold_ptr<data> d;
  982. };
  983. class CPPCMS_API radio : public select_base {
  984. public:
  985. radio();
  986. virtual ~radio();
  987. virtual void render_input(form_context &context);
  988. bool vertical();
  989. void vertical(bool);
  990. private:
  991. uint32_t vertical_ : 1;
  992. uint32_t reserved_ : 31;
  993. struct data;
  994. util::hold_ptr<data> d;
  995. };
  996. class CPPCMS_API submit : public base_html_input {
  997. public:
  998. submit();
  999. ~submit();
  1000. ///
  1001. /// Returns true if this specific button was pressed
  1002. ///
  1003. bool value();
  1004. ///
  1005. /// Sets the text on button
  1006. ///
  1007. void value(std::string val);
  1008. ///
  1009. /// Sets the text on button
  1010. ///
  1011. void value(locale::message const &msg);
  1012. virtual void render_value(form_context &context);
  1013. virtual void load(http::context &context);
  1014. private:
  1015. struct data;
  1016. util::hold_ptr<data> d;
  1017. bool pressed_;
  1018. locale::message value_;
  1019. };
  1020. } // widgets
  1021. } //cppcms
  1022. #endif // CPPCMS_FORM_H