CppCMS
cppcms/form.h
00001 
00002 //                                                                             
00003 //  Copyright (C) 2008-2012  Artyom Beilis (Tonkikh) <artyomtnk@yahoo.com>     
00004 //                                                                             
00005 //  See accompanying file COPYING.TXT file for licensing details.
00006 //
00008 #ifndef CPPCMS_FORM_H
00009 #define CPPCMS_FORM_H
00010 
00011 #include <cppcms/defs.h>
00012 #include <booster/noncopyable.h>
00013 
00014 #include <string>
00015 #include <set>
00016 #include <map>
00017 #include <list>
00018 #include <vector>
00019 #include <stack>
00020 #include <ostream>
00021 #include <sstream>
00022 #include <cppcms/http_context.h>
00023 #include <cppcms/http_request.h>
00024 #include <cppcms/http_response.h>
00025 #include <booster/copy_ptr.h>
00026 #include <booster/perl_regex.h>
00027 #include <booster/shared_ptr.h>
00028 #include <cppcms/cppcms_error.h>
00029 #include <cppcms/util.h>
00030 #include <cppcms/localization.h>
00031 
00032 namespace cppcms {
00033 
00034         namespace http {
00035                 class file;
00036         }
00037 
00038         namespace widgets {
00039                 class base_widget;
00040         }
00041 
00045         struct form_flags {
00049                 typedef enum {
00050                         as_html = 0,    
00051                         as_xhtml= 1,    
00052                 } html_type;
00053 
00057                 typedef enum {
00058                         as_p    = 0 , 
00059                         as_table= 1 , 
00060                         as_ul   = 2 , 
00061                         as_dl   = 3 , 
00062                         as_space= 4   
00063                 } html_list_type;
00064 
00068                 typedef enum {
00069                         first_part  = 0, 
00070                         second_part = 1  
00071                 } widget_part_type;
00072         };
00073 
00077         class CPPCMS_API form_context : public form_flags
00078         {
00079         public:
00083                 form_context();
00084 
00088                 form_context(form_context const &other);
00089 
00093                 form_context const &operator = (form_context const &other);
00094 
00102                 form_context(   std::ostream &output,
00103                                 html_type ht = form_flags::as_html,
00104                                 html_list_type hlt=form_flags::as_p);
00105 
00109                 ~form_context();
00110         
00114                 void html(html_type t);
00115 
00119                 void html_list(html_list_type t);
00120 
00124                 void widget_part(widget_part_type t);
00125 
00129                 void out(std::ostream &out);
00130                 
00134                 html_type html() const;
00135 
00139                 html_list_type html_list() const;
00140 
00144                 widget_part_type widget_part() const;
00145 
00149                 std::ostream &out() const;
00150 
00151         private:
00152                 uint32_t html_type_;
00153                 uint32_t html_list_type_;
00154                 uint32_t widget_part_type_;
00155                 std::ostream *output_;
00156                 uint32_t reserved_1;
00157                 uint32_t reserved_2;
00158                 struct _data;
00159                 booster::hold_ptr<_data> d;
00160 
00161         };
00162 
00163         
00169         class CPPCMS_API base_form : public form_flags {
00170         public:
00176                 virtual void render(form_context &context) = 0;
00177 
00183                 virtual void load(http::context &context) = 0;
00184 
00189                 virtual bool validate() = 0;
00190 
00194                 virtual void clear() = 0;
00195 
00199                 virtual void parent(base_form *subform) = 0;
00200 
00204                 virtual base_form *parent() = 0;
00205 
00206                 base_form();
00207                 virtual ~base_form();
00208         };
00209 
00216         class CPPCMS_API form : public booster::noncopyable,
00217                                 public base_form
00218         {
00219         public:
00220                 form();
00221                 virtual ~form();
00222 
00227                 virtual void render(form_context &context);
00228 
00232                 virtual void load(http::context &cont);
00233 
00238                 virtual bool validate();
00239 
00243                 virtual void clear();
00244 
00249                 void add(form &subform);
00250 
00256                 void attach(form *subform);
00257 
00262                 void add(widgets::base_widget &widget);
00263 
00269                 void attach(widgets::base_widget *widget);
00270 
00276                 CPPCMS_DEPRECATED inline form &operator + (form &f)
00277                 {
00278                         add(f);
00279                         return *this;
00280                 }
00281                 
00287                 CPPCMS_DEPRECATED inline form &operator + (widgets::base_widget &f)
00288                 {
00289                         add(f);
00290                         return *this;
00291                 }
00292 
00297                 virtual void parent(base_form *subform);
00298 
00303                 virtual form *parent();
00304                 
00320                 class CPPCMS_API iterator : public std::iterator<std::input_iterator_tag,widgets::base_widget>
00321                 {
00322                 public:
00326                         iterator();
00327 
00331                         iterator(form &);
00332 
00336                         ~iterator();
00337 
00341                         iterator(iterator const &other);
00342 
00346                         iterator const &operator = (iterator const &other);
00347 
00351                         widgets::base_widget *operator->() const
00352                         {
00353                                 return get();
00354                         }
00355 
00359                         widgets::base_widget &operator*() const
00360                         {
00361                                 return *get();
00362                         }
00363 
00367                         bool operator==(iterator const &other) const
00368                         {
00369                                 return equal(other);
00370                         }
00371 
00375                         bool operator!=(iterator const &other) const
00376                         {
00377                                 return !equal(other);
00378                         }
00379 
00386                         iterator operator++(int /*unused*/)
00387                         {
00388                                 iterator tmp(*this);
00389                                 next();
00390                                 return tmp;
00391                         }
00392 
00397                         iterator &operator++()
00398                         {
00399                                 next();
00400                                 return *this;
00401                         }
00402 
00403                 private:
00404 
00405                         friend class form;
00406 
00407                         bool equal(iterator const &other) const;
00408                         void zero();
00409                         void next();
00410                         widgets::base_widget *get() const;
00411 
00412                         std::stack<unsigned> return_positions_;
00413                         form *current_;
00414                         unsigned offset_;
00415                         struct _data;
00416                         booster::copy_ptr<_data> d;
00417 
00418                 };
00419 
00423                 iterator begin();
00424 
00428                 iterator end();
00429 
00430 
00431         private:
00432                 friend class iterator;
00433 
00434                 struct _data;
00435                 // Widget and ownership - true means I own it.
00436                 typedef std::pair<base_form *,bool> widget_type;
00437                 std::vector<widget_type> elements_;
00438                 form *parent_;
00439                 booster::hold_ptr<_data> d;
00440         };
00441 
00442 
00443 
00447         namespace widgets {
00448 
00456 
00457                 class CPPCMS_API base_widget :  
00458                         public base_form,
00459                         public booster::noncopyable
00460                 {
00461                 public:
00465                         base_widget();
00466 
00467                         virtual ~base_widget();
00468                         
00478                         bool set();
00479 
00483                         bool valid();
00484 
00488                         std::string id();
00489 
00493                         std::string name();
00494 
00498                         locale::message message();
00499 
00503                         bool has_message();
00504 
00509                         locale::message error_message();
00510 
00514                         bool has_error_message();
00515 
00519                         locale::message help();
00520 
00524                         bool has_help();
00525 
00529                         bool disabled();
00530 
00534                         void disabled(bool);
00535 
00539                         std::string attributes_string();
00540 
00546                         void set(bool);
00547 
00554                         void valid(bool);
00555 
00559                         void id(std::string);
00560 
00566                         void name(std::string);
00567 
00574                         void message(std::string);
00575 
00582                         void message(locale::message const &);
00583 
00589                         void error_message(std::string);
00590 
00596                         void error_message(locale::message const &);
00597 
00601                         void help(std::string);
00602                         
00606                         void help(locale::message const &msg);
00607 
00618                         void attributes_string(std::string v);
00619 
00620 
00625                         virtual void render(form_context &context);
00626 
00631                         virtual void render_input(form_context &context) = 0;
00632 
00636                         virtual void clear();
00637 
00641                         virtual bool validate();
00642 
00646                         virtual void render_attributes(form_context &context);
00647                         
00652                         virtual void parent(base_form *subform);
00653 
00658                         virtual form *parent();
00659 
00665                         void pre_load(http::context &);
00666 
00667                 protected:
00672                         void auto_generate(form_context *context = 0);
00673 
00674                 private:
00675                         void generate(int position,form_context *context = 0);
00676 
00677                         std::string id_;
00678                         std::string name_;
00679                         locale::message message_;
00680                         locale::message error_message_;
00681                         locale::message help_;
00682                         std::string attr_;
00683                         form *parent_;
00684 
00685                         uint32_t is_valid_  : 1;
00686                         uint32_t is_set_ : 1;
00687                         uint32_t is_disabled_ : 1;
00688                         uint32_t is_generation_done_ : 1;
00689                         uint32_t has_message_ : 1;
00690                         uint32_t has_error_ : 1;
00691                         uint32_t has_help_ : 1;
00692                         uint32_t reserverd_ : 25;
00693 
00694                         struct _data;
00695                         booster::hold_ptr<_data> d;
00696                 };
00697 
00707                 class CPPCMS_API base_text : virtual public base_widget {
00708                 public:
00709                         
00710                         base_text();
00711                         virtual ~base_text();
00712 
00716                         std::string value();
00717                         
00721                         void value(std::string v);
00722                         
00727                         void non_empty();
00728                         
00737                         void limits(int min,int max);
00738 
00742                         std::pair<int,int> limits();
00743 
00752                         void validate_charset(bool );
00753                         
00757                         bool validate_charset();
00758 
00770                         virtual bool validate();
00771 
00776                         virtual void load(http::context &);
00777 
00778                 private:
00779                         std::string value_;
00780                         int low_;
00781                         int high_;
00782                         bool validate_charset_;
00783                         size_t code_points_;
00784                         struct _data;
00785                         booster::hold_ptr<_data> d;
00786                 };
00787 
00796 
00797                 class CPPCMS_API base_html_input : virtual public base_widget {
00798                 public:
00803                         base_html_input(std::string const &type);
00804 
00808                         virtual ~base_html_input();
00809 
00813                         virtual void render_input(form_context &context);
00814 
00815                 protected:
00819                         virtual void render_value(form_context &context) = 0;
00820 
00821                 private:
00822                         struct _data;
00823                         booster::hold_ptr<_data> d;
00824                         std::string type_;
00825                 };
00826 
00830                 class CPPCMS_API text : public base_html_input, public base_text
00831                 {
00832                 public:
00836                         text();
00837                         
00842                         text(std::string const &type);
00843 
00844                         ~text();
00845 
00849                         void size(int n);
00850 
00854                         int size();
00855 
00856 
00857                         virtual void render_attributes(form_context &context);
00858                         virtual void render_value(form_context &context);
00859 
00860                 private:
00861                         int size_;
00862                         struct _data;
00863                         booster::hold_ptr<_data> d;
00864                 };
00865 
00876                 class CPPCMS_API hidden : public text 
00877                 {
00878                 public:
00879                         hidden();
00880                         ~hidden();
00886                         virtual void render(form_context &context);
00887                 private:
00888                         struct _data;
00889                         booster::hold_ptr<_data> d;
00890                 };
00891 
00892 
00897                 class CPPCMS_API textarea : public base_text 
00898                 {
00899                 public:
00900                         textarea();
00901                         ~textarea();
00902 
00906                         int rows();
00907 
00911                         int cols();
00912 
00916                         void rows(int n);
00917 
00921                         void cols(int n);
00922 
00923                         virtual void render_input(form_context &context);
00924 
00925                 private:
00926                         int rows_,cols_;
00927 
00928                         struct _data;
00929                         booster::hold_ptr<_data> d;
00930                 };
00931 
00941                 template<typename T>
00942                 class numeric: public base_html_input {
00943                 public:
00944                         numeric() :
00945                                 base_html_input("text"),
00946                                 check_low_(false),
00947                                 check_high_(false),
00948                                 non_empty_(false)
00949                         {
00950                         }
00951 
00955                         void non_empty()
00956                         {
00957                                 non_empty_=true;
00958                         }
00959 
00960 
00970                         T value()
00971                         {
00972                                 if(!set())
00973                                         throw cppcms_error("Value not loaded");
00974                                 return value_;
00975                         }
00976 
00980                         void value(T v)
00981                         {
00982                                 set(true);
00983                                 value_=v;
00984                         }
00985 
00989                         void low(T a)
00990                         {
00991                                 min_=a;
00992                                 check_low_=true;
00993                                 non_empty();
00994                         }
00995 
00999                         void high(T b)
01000                         {
01001                                 max_=b;
01002                                 check_high_=true;
01003                                 non_empty();
01004                         }
01005 
01009                         void range(T a,T b)
01010                         {
01011                                 low(a);
01012                                 high(b);
01013                         }
01014 
01018                         virtual void render_value(form_context &context)
01019                         {
01020                                 if(set())
01021                                         context.out()<<"value=\""<<value_<<"\" ";
01022                                 else
01023                                         context.out()<<"value=\""<<util::escape(loaded_string_)<<"\" ";
01024                         }
01025 
01026                         virtual void clear()
01027                         {
01028                                 base_html_input::clear();
01029                                 loaded_string_.clear();
01030                         }
01031 
01035                         virtual void load(http::context &context)
01036                         {
01037                                 pre_load(context);
01038 
01039                                 loaded_string_.clear();
01040 
01041                                 set(false);
01042                                 valid(true);
01043 
01044                                 http::request::form_type::const_iterator p;
01045                                 http::request::form_type const &request=context.request().post_or_get();
01046                                 p=request.find(name());
01047                                 if(p==request.end()) {
01048                                         return;
01049                                 }
01050                                 else {
01051                                         loaded_string_=p->second;
01052                                         if(loaded_string_.empty())
01053                                                 return;
01054 
01055                                         std::istringstream ss(loaded_string_);
01056                                         ss.imbue(context.locale());
01057                                         ss>>value_;
01058                                         if(ss.fail() || !ss.eof())
01059                                                 valid(false);
01060                                         else
01061                                                 set(true);
01062                                 }
01063                         }
01064                         
01068                         virtual bool validate()
01069                         {
01070                                 if(!valid())
01071                                         return false;
01072                                 if(!set()) {
01073                                         if(non_empty_) {
01074                                                 valid(false);
01075                                                 return false;
01076                                         }
01077                                         return true;
01078                                 }
01079                                 if(check_low_ && value_ <min_) {
01080                                         valid(false);
01081                                         return false;
01082                                 }
01083                                 if(check_high_ && value_ > max_) {
01084                                         valid(false);
01085                                         return false;
01086                                 }
01087                                 return true;
01088                         }
01089 
01090                 private:
01091 
01092                         T min_,max_,value_;
01093 
01094                         bool check_low_;
01095                         bool check_high_;
01096                         bool non_empty_;
01097                         std::string loaded_string_;
01098                 };
01099 
01102                 //  
01103                 class CPPCMS_API password: public text {
01104                 public:
01105                         password();
01106 
01107                         ~password();
01108 
01114                         void check_equal(password &p2);
01115                         virtual bool validate();
01116 
01117                 private:
01118                         struct _data;
01119                         booster::hold_ptr<_data> d;
01120                         password *password_to_check_;
01121                 };
01122 
01123                 
01127                 class CPPCMS_API regex_field : public text {
01128                 public:
01129                         regex_field();
01133                         regex_field(booster::regex const &e);
01134                         
01138                         regex_field(std::string const &e);
01139 
01140 
01144                         void regex(booster::regex const &e);
01145 
01146                         ~regex_field();
01147                         
01148                         virtual bool validate();
01149 
01150                 private:
01151                         booster::regex expression_;
01152                         struct _data;
01153                         booster::hold_ptr<_data> d;
01154                 };
01155 
01159                 class CPPCMS_API email : public regex_field {
01160                 public:
01161 
01162                         email();
01163                         ~email();
01164 
01165                 private:
01166                         struct _data;
01167                         booster::hold_ptr<_data> d;
01168                 };
01169 
01173                 class CPPCMS_API checkbox: public base_html_input {
01174                 public:
01180                         checkbox(std::string const &type);
01181 
01185                         checkbox();
01186                         virtual ~checkbox();
01187                         
01191                         bool value();
01192 
01196                         void value(bool is_set);
01197 
01201                         std::string identification();
01202 
01207                         void identification(std::string const &);
01208 
01209                         virtual void render_value(form_context &context);
01210                         virtual void load(http::context &context);
01211 
01212                 private:
01213                         struct _data;
01214                         booster::hold_ptr<_data> d;
01215                         std::string identification_;
01216                         bool value_;
01217                 };
01218         
01222                 class CPPCMS_API select_multiple : public base_widget {
01223                 public:
01224                         select_multiple();
01225                         ~select_multiple();
01226 
01231                         void add(std::string const &msg,bool selected=false);
01232 
01237                         void add(std::string const &msg,std::string const &id,bool selected=false);
01238 
01243                         void add(locale::message const &msg,bool selected=false);
01244 
01249                         void add(locale::message const &msg,std::string const &id,bool selected=false);
01250 
01254                         std::vector<bool> selected_map();
01255 
01260                         std::set<std::string> selected_ids();
01261 
01265                         unsigned at_least();
01266 
01270                         void at_least(unsigned v);
01271 
01275                         unsigned at_most();
01276 
01280                         void at_most(unsigned v);
01281 
01285                         void non_empty();
01286 
01290                         unsigned rows();
01291 
01295                         void rows(unsigned n);
01296                         
01297                         virtual void render_input(form_context &context);
01298                         virtual bool validate();
01299                         virtual void load(http::context &context);
01300                         virtual void clear();
01301 
01302                 private:
01303                         struct _data;
01304                         booster::hold_ptr<_data> d;
01305 
01306                         struct element {
01307                                 element();
01308                                 element(std::string const &v,locale::message const &msg,bool sel);
01309                                 element(std::string const &v,std::string const &msg,bool sel);
01310                                 uint32_t selected : 1;
01311                                 uint32_t need_translation : 1;
01312                                 uint32_t original_select : 1;
01313                                 uint32_t reserved : 29;
01314                                 std::string id;
01315                                 std::string str_option;
01316                                 locale::message tr_option;
01317                                 friend std::ostream &operator<<(std::ostream &out,element const &el);
01318                         };
01319 
01320                         std::vector<element> elements_;
01321                         
01322                         unsigned low_;
01323                         unsigned high_;
01324                         unsigned rows_;
01325                         
01326                 };
01327 
01332                 class CPPCMS_API select_base : public base_widget {
01333                 public:
01334                         select_base();
01335                         virtual ~select_base();
01336 
01340                         void add(std::string const &string);
01341 
01345                         void add(std::string const &string,std::string const &id);
01346 
01350                         void add(locale::message const &msg);
01351 
01355                         void add(locale::message const &msg,std::string const &id);
01356 
01361                         int selected();
01362 
01367                         std::string selected_id();
01368 
01372                         void selected(int no);
01373 
01377                         void selected_id(std::string id);
01378 
01382                         void non_empty();
01383                         
01384                         virtual void render_input(form_context &context) = 0;
01385                         virtual bool validate();
01386                         virtual void load(http::context &context);
01387                         virtual void clear();
01388 
01389                 protected:
01390                         struct CPPCMS_API element {
01391                                 
01392                                 element();
01393                                 element(std::string const &v,locale::message const &msg);
01394                                 element(std::string const &v,std::string const &msg);
01395                                 element(element const &);
01396                                 element const &operator=(element const &);
01397                                 ~element();
01398 
01399                                 uint32_t need_translation : 1;
01400                                 uint32_t reserved : 31;
01401                                 std::string id;
01402                                 std::string str_option;
01403                                 locale::message tr_option;
01404 
01405                         private:
01406                                 struct _data;
01407                                 booster::copy_ptr<_data> d;
01408 
01409                         };
01410 
01411                         std::vector<element> elements_;
01412 
01413                 private:
01414                         struct _data;
01415                         booster::hold_ptr<_data> d;
01416 
01417                         int selected_;
01418                         int default_selected_;
01419 
01420                         uint32_t non_empty_ : 1;
01421                         uint32_t reserverd  : 32;
01422                 };
01423 
01427                 class CPPCMS_API select : public select_base {
01428                 public:
01429                         select();
01430                         virtual ~select();
01431                         virtual void render_input(form_context &context);
01432 
01433                 private:
01434                         struct _data;
01435                         booster::hold_ptr<_data> d;
01436                 };
01437 
01441                 class CPPCMS_API radio : public select_base {
01442                 public:
01443                         radio();
01444                         virtual ~radio();
01445                         virtual void render_input(form_context &context);
01446                         
01450                         bool vertical();
01451 
01459                         void vertical(bool);
01460 
01461                 private:
01462                         uint32_t vertical_ : 1;
01463                         uint32_t reserved_ : 31;
01464 
01465                         struct _data;
01466                         booster::hold_ptr<_data> d;
01467                 };
01468 
01475                 class CPPCMS_API file : public base_html_input {
01476                 public:
01480                         void non_empty();
01481 
01487                         void limits(int min,int max);
01488 
01492                         std::pair<int,int> limits();
01493 
01502                         void filename(booster::regex const &fn);
01503 
01507                         booster::regex filename();
01508                         
01512                         void validate_filename_charset(bool);
01513 
01517                         bool validate_filename_charset();
01518 
01523                         booster::shared_ptr<http::file> value();
01524 
01528                         void mime(std::string const &);
01529 
01533                         void mime(booster::regex const &expr);
01534 
01540                         void add_valid_magic(std::string const &);
01541 
01542                         virtual void load(http::context &context);
01543                         virtual void render_value(form_context &context);
01544                         virtual bool validate();
01545                         
01546                         file();
01547                         ~file();
01548 
01549                 private:
01550 
01551                         int size_min_;
01552                         int size_max_;
01553                         
01554                         std::vector<std::string> magics_;
01555                         
01556                         std::string mime_string_;
01557                         booster::regex mime_regex_;
01558                         booster::regex filename_regex_;
01559 
01560                         uint32_t check_charset_ : 1;
01561                         uint32_t check_non_empty_ : 1;
01562                         uint32_t reserved_ : 30;
01563 
01564                         booster::shared_ptr<http::file> file_;
01565 
01566                         struct _data;
01567                         booster::hold_ptr<_data> d;
01568                 };
01569 
01570 
01574                 class CPPCMS_API submit : public base_html_input {
01575                 public:
01576                         submit();
01577                         ~submit();
01578                         
01582                         bool value();
01583 
01587                         void value(std::string val);
01588 
01592                         void value(locale::message const &msg);
01593 
01594                         virtual void render_value(form_context &context);
01595                         virtual void load(http::context &context);
01596 
01597                 private:
01598                         struct _data;
01599                         booster::hold_ptr<_data> d;
01600                         bool pressed_;
01601                         locale::message value_;
01602                 };
01603 
01604 
01605                 
01606 
01607         } // widgets
01608 
01609 
01610 } //cppcms
01611 
01612 #endif // CPPCMS_FORM_H