@@ -75,6 +75,7 @@ if(NOT DISABLE_ICONV) | |||
endif(NOT DISABLE_ICONV) | |||
include_directories(${CMAKE_BINARY_DIR}) | |||
include_directories(${CMAKE_SOURCE_DIR}) | |||
include_directories(boost_locale) | |||
set(CPPCMS_LIBRARY_SUFFIX ${CMAKE_SHARED_LIBRARY_SUFFIX}) | |||
@@ -91,7 +92,7 @@ check_cxx_source_compiles( | |||
int main() { std::u16string s16; std::u32string s32; }" | |||
HAVE_CPP0X_UXSTRING) | |||
Check_cxx_source_compiles( | |||
check_cxx_source_compiles( | |||
"#include <list> | |||
int main(){std::list<int> l; auto p=l.begin();}" | |||
HAVE_CPP_0X_AUTO) | |||
@@ -257,8 +258,39 @@ if(NOT DISABLE_SHARED) | |||
target_link_libraries(cppcms boost_locale) | |||
endif(NOT DISABLE_SHARED) | |||
add_executable(hello_world hello_world.cpp) | |||
find_program(PYTHON python) | |||
if(NOT PYTHON) | |||
message(FATAL "Can't build without Python interpreter") | |||
endif(NOT PYTHON) | |||
# Templates builds | |||
add_custom_command( | |||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/skin1.cpp | |||
COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/cppcms_tmpl_cc | |||
-n skin1 | |||
-o ${CMAKE_CURRENT_BINARY_DIR}/skin1.cpp | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_skin1.tmpl | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_view1.tmpl | |||
DEPENDS | |||
${CMAKE_CURRENT_SOURCE_DIR}/cppcms_tmpl_cc | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_skin1.tmpl | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_view1.tmpl) | |||
add_custom_command( | |||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/skin2.cpp | |||
COMMAND ${PYTHON} ${CMAKE_CURRENT_SOURCE_DIR}/cppcms_tmpl_cc | |||
-n skin2 | |||
-o ${CMAKE_CURRENT_BINARY_DIR}/skin2.cpp | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_skin2.tmpl | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_view1.tmpl | |||
DEPENDS | |||
${CMAKE_CURRENT_SOURCE_DIR}/cppcms_tmpl_cc | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_skin2.tmpl | |||
${CMAKE_CURRENT_SOURCE_DIR}/hello_world_view1.tmpl) | |||
add_executable(hello_world hello_world.cpp skin1.cpp skin2.cpp) | |||
target_link_libraries(hello_world ${CPPCMS_LIB}) | |||
add_executable(cppcms_config_find_param cppcms_config_find_param.cpp json.cpp) | |||
@@ -1,3 +1,9 @@ | |||
- Implement full util::format | |||
- Add macros for variadic templates support | |||
- Implement to_(w)string | |||
- form.* | |||
Implement, Select, Radio, Date-Time | |||
- http_request.*, cgi_api.* | |||
Implement File Upload | |||
- Implement Asynchronous API | |||
- Implement JSON-RPC | |||
- Reintegrate Sessions Support | |||
- Reintegrate Cache Support | |||
- Update cppcms_tmpl_cc according to new code |
@@ -8,6 +8,7 @@ | |||
#include "intrusive_ptr.h" | |||
#include "applications_pool.h" | |||
#include "http_response.h" | |||
#include "views_pool.h" | |||
#include <set> | |||
#include <vector> | |||
@@ -158,6 +159,27 @@ void application::assign(application *app,std::string regex,int part) | |||
add(*app,regex,part); | |||
} | |||
void application::render(std::string template_name,base_content &content) | |||
{ | |||
service().views_pool().render(context().skin(),template_name,response().out(),content); | |||
} | |||
void application::render(std::string skin,std::string template_name,base_content &content) | |||
{ | |||
service().views_pool().render(skin,template_name,response().out(),content); | |||
} | |||
void application::render(std::string template_name,std::ostream &out,base_content &content) | |||
{ | |||
service().views_pool().render(context().skin(),template_name,out,content); | |||
} | |||
void application::render(std::string skin,std::string template_name,std::ostream &out,base_content &content) | |||
{ | |||
service().views_pool().render(skin,template_name,out,content); | |||
} | |||
void application::recycle() | |||
{ | |||
if(root()->d->conn) { | |||
@@ -14,6 +14,7 @@ namespace cppcms { | |||
class url_dispatcher; | |||
class applications_pool; | |||
class application; | |||
class base_content; | |||
namespace locale { | |||
class environment; | |||
@@ -42,6 +43,11 @@ namespace cppcms { | |||
http::response &response(); | |||
url_dispatcher &dispatcher(); | |||
void render(std::string template_name,base_content &content); | |||
void render(std::string skin,std::string template_name,base_content &content); | |||
void render(std::string template_name,std::ostream &out,base_content &content); | |||
void render(std::string skin,std::string template_name,std::ostream &out,base_content &content); | |||
void add(application &app); | |||
void add(application &app,std::string regex,int part); | |||
@@ -13,6 +13,7 @@ | |||
#include "hold_ptr.h" | |||
#include "base_content.h" | |||
#include "noncopyable.h" | |||
#include "config.h" | |||
namespace cppcms { | |||
@@ -47,9 +47,10 @@ | |||
"cookies_secure" : false | |||
}, | |||
"views" : { | |||
"paths" : [ "./teplates" ], | |||
"skins" : [ "skin1", "skin2" ], | |||
"auto_reload" : true | |||
"default_skin" : "skin1" | |||
// "paths" : [ "./teplates" ], | |||
// "skins" : [ "skin1", "skin2" ], | |||
// "auto_reload" : true | |||
}, | |||
"file_server" : { | |||
"enable" : true, | |||
@@ -18,6 +18,8 @@ | |||
#include <boost/bind.hpp> | |||
#include <fstream> | |||
#include "hello_world_view.h" | |||
class chat : public cppcms::application { | |||
public: | |||
@@ -189,13 +191,13 @@ public: | |||
}; | |||
class hello : public cppcms::application { | |||
public: | |||
hello(cppcms::service &srv) : | |||
cppcms::application(srv) | |||
{ | |||
dispatcher().assign("^/(\\d+)$",&hello::num,this,1); | |||
dispatcher().assign("^/view(/(\\w+))?$",&hello::view_test,this,2); | |||
dispatcher().assign("^/get$",&hello::gform,this); | |||
dispatcher().assign("^/post$",&hello::pform,this); | |||
dispatcher().assign("^/err$",&hello::err,this); | |||
@@ -207,6 +209,14 @@ public: | |||
{ | |||
} | |||
void view_test(std::string skin) | |||
{ | |||
view::hello c; | |||
if(!skin.empty()) | |||
context().skin(skin); | |||
render("hello",c); | |||
} | |||
void devide(cppcms::locale::boundary::boundary_type type,std::string const &str,char const *name) | |||
{ | |||
response().out()<<name<<":"; | |||
@@ -1,7 +1,7 @@ | |||
<% c++ #include "hello_world_view.h" %> | |||
<% namespace vary %> | |||
<% class master uses view::master %> | |||
<% template test(string &v,int p) %> | |||
<% template test(std::string &v,int p) %> | |||
<% foreach c in v %> | |||
<% item %><% c %><% end %> | |||
<% end %> | |||
@@ -1,8 +1,5 @@ | |||
#include "base_view.h" | |||
#include "application.h" | |||
#include "view.h" | |||
#include <list> | |||
#include "form.h" | |||
using namespace cppcms; | |||
class my_hello_world; | |||
namespace view { | |||
@@ -17,60 +14,57 @@ struct data { | |||
data(char const *n="",int v=0) : name(n),val(v){} | |||
}; | |||
struct my_form : public form { | |||
widgets::text username; | |||
widgets::textarea name; | |||
widgets::email mail; | |||
widgets::password p1; | |||
widgets::password p2; | |||
widgets::number<int> integer; | |||
widgets::number<double> real; | |||
widgets::checkbox ok; | |||
widgets::select fruit; | |||
struct a_form : public cppcms::form { | |||
cppcms::widgets::text username; | |||
cppcms::widgets::textarea name; | |||
cppcms::widgets::email mail; | |||
cppcms::widgets::password p1; | |||
cppcms::widgets::password p2; | |||
cppcms::widgets::numeric<int> integer; | |||
cppcms::widgets::numeric<double> real; | |||
cppcms::widgets::checkbox ok; | |||
//widgets::select fruit; | |||
//widgets::radio fruit; | |||
widgets::select_multiple meat; | |||
widgetset my_set; | |||
my_form(application *w) : | |||
username("user",w->gettext("Username")), | |||
name("name",w->gettext("Real Name")), | |||
mail("mail",w->gettext("Mail")), | |||
p1("pass",w->gettext("Password")), | |||
p2("passcopy",w->gettext("Confirm")), | |||
integer("int",w->gettext("Integer")), | |||
real("real",w->gettext("Real")), | |||
ok("ok",w->gettext("Never save")), | |||
fruit("fr",w->gettext("Fruit")), | |||
meat("mt",2,w->gettext("Meat")) | |||
//widgets::select_multiple meat; | |||
//widgetset my_set; | |||
a_form() | |||
{ | |||
*this & username & mail & name & p1 & p2 & | |||
integer & real & ok & fruit & meat ; | |||
my_set<< username<<mail<<name<<p1<<p2<<integer<<real<<ok<<fruit<<meat; | |||
username.set_nonempty(); | |||
name.set_nonempty(); | |||
p2.set_equal(p1); | |||
p2.help=w->gettext("(Same as above)"); | |||
p1.set_nonempty(); | |||
p2.set_nonempty(); | |||
real.set_range(-1.0,1.5); | |||
fruit.add("Orange"); | |||
using cppcms::locale::translate; | |||
username.message(translate("Username")); | |||
name.message(translate("Real Name")); | |||
mail.message(translate("E-Mail")); | |||
p1.message(translate("Password")); | |||
p2.message(translate("Confirm")); | |||
integer.message(translate("Integer")); | |||
real.message(translate("Real")); | |||
ok.message(translate("Never Save")); | |||
*this + username + mail + name + p1 + p2 + | |||
integer + real + ok; | |||
username.non_empty(); | |||
name.non_empty(); | |||
p2.check_equal(p1); | |||
p2.help(translate("(Same as above)")); | |||
p1.non_empty(); | |||
p2.non_empty(); | |||
real.range(-1.0,1.5); | |||
/* fruit.add("Orange"); | |||
fruit.add("Palm"); | |||
meat.add("Beef"); | |||
meat.add("<<Chicken>>"); | |||
meat.add("Duck"); | |||
meat.set_min(2); | |||
meat.help=w->gettext("At least two choises"); | |||
meat.help=w->gettext("At least two choises");*/ | |||
} | |||
}; | |||
struct hello : public master { | |||
string username,realname,password; | |||
std::string username,realname,password; | |||
bool ok; | |||
std::string msg; | |||
std::list<int> numbers; | |||
std::list<data> lst; | |||
my_form form; | |||
hello(application *w) : form(w) {} | |||
a_form form; | |||
}; | |||
}; | |||
@@ -10,11 +10,11 @@ | |||
</form> | |||
<form action="" method="post"> | |||
<p> | |||
<% foreach widget w in form.my_set %> | |||
<% foreach w in form %> | |||
<% separator %><br/><% item %> | |||
<% if not empty w.msg %><% w.msg %>:<% end %> | |||
<% if w.has_message() %><% w.message() %>:<% end %> | |||
<% form input w %> | |||
<% if not w.is_valid %>:<% form error w %><% end %> | |||
<% if not w.valid() %>:<% w.error_message() %><% end %> | |||
<% end %> | |||
<% end %> | |||
<input type="submit" value="Submit" /> | |||
@@ -30,10 +30,11 @@ | |||
<% foreach x in numbers %> | |||
<ul> | |||
<% item %> | |||
<li><% ngt "passed one day","passed %1% days",x using x %></li> | |||
<li><% ngt "passed one day","passed {1} days",x using x %></li> | |||
<% end %> | |||
</ul> | |||
<% end %> | |||
<% end template %> | |||
<% end class %> | |||
<% end namespace %> | |||
@@ -9,6 +9,7 @@ | |||
#include "applications_pool.h" | |||
#include "thread_pool.h" | |||
#include "url_dispatcher.h" | |||
#include "views_pool.h" | |||
#include "cppcms_error.h" | |||
#include <boost/bind.hpp> | |||
@@ -19,6 +20,7 @@ namespace http { | |||
struct context::data { | |||
std::locale locale; | |||
std::string skin; | |||
http::request request; | |||
std::auto_ptr<http::response> response; | |||
data(context &cntx) : | |||
@@ -33,6 +35,17 @@ context::context(intrusive_ptr<impl::cgi::connection> conn) : | |||
{ | |||
d.reset(new data(*this)); | |||
d->response.reset(new http::response(*this)); | |||
skin(service().views_pool().default_skin()); | |||
} | |||
std::string context::skin() | |||
{ | |||
return d->skin; | |||
} | |||
void context::skin(std::string const &skin) | |||
{ | |||
d->skin=skin; | |||
} | |||
@@ -36,6 +36,9 @@ namespace cppcms { | |||
void locale(std::string const &name); | |||
cppcms::service &service(); | |||
std::string skin(); | |||
void skin(std::string const &name); | |||
void run(); | |||
typedef enum { | |||
@@ -13,6 +13,7 @@ | |||
#include "internal_file_server.h" | |||
#include "json.h" | |||
#include "localization.h" | |||
#include "views_pool.h" | |||
#ifdef CPPCMS_POSIX | |||
@@ -140,6 +141,12 @@ void service::setup() | |||
{ | |||
int apps=settings().get("service.applications_pool_size",threads_no()*2); | |||
impl_->applications_pool_.reset(new cppcms::applications_pool(*this,apps)); | |||
impl_->views_pool_.reset(new cppcms::views_pool(settings())); | |||
} | |||
cppcms::views_pool &service::views_pool() | |||
{ | |||
return *impl_->views_pool_; | |||
} | |||
@@ -17,6 +17,7 @@ namespace cppcms { | |||
class applications_pool; | |||
class thread_pool; | |||
class views_pool; | |||
namespace json { | |||
class value; | |||
} | |||
@@ -34,6 +35,7 @@ namespace cppcms { | |||
cppcms::applications_pool &applications_pool(); | |||
cppcms::thread_pool &thread_pool(); | |||
json::value const &settings(); | |||
cppcms::views_pool &views_pool(); | |||
locale::generator const &generator(); | |||
std::locale locale(); | |||
@@ -35,6 +35,7 @@ namespace impl { | |||
std::auto_ptr<applications_pool> applications_pool_; | |||
std::auto_ptr<thread_pool> thread_pool_; | |||
std::auto_ptr<locale::generator> locale_generator_; | |||
std::auto_ptr<views_pool> views_pool_; | |||
std::locale default_locale_; | |||
#ifdef CPPCMS_WIN32 | |||
@@ -0,0 +1,8 @@ | |||
#ifndef CPPCMS_VIEW_H | |||
#define CPPCMS_VIEW_H | |||
#include "form.h" | |||
#include "filters.h" | |||
#include "base_view.h" | |||
#include "views_pool.h" | |||
#endif | |||
@@ -125,12 +125,12 @@ public: | |||
time_stamp_ = st.st_mtime; | |||
shared_object_.reset(new impl::shared_object(file_name,reloadable)); | |||
typedef void (*loader_type)(mapping_type *); | |||
typedef void (*loader_type)(mapping_type &); | |||
loader_type loader=reinterpret_cast<loader_type>(shared_object_->symbol("cppcms_"+name+"_get_skins")); | |||
if(!loader) { | |||
throw cppcms_error(file_name + " is not CppCMS loadable skin"); | |||
} | |||
loader(&mapping_); | |||
loader(mapping_); | |||
return; | |||
} | |||
throw cppcms_error("Can't load skin " + name); | |||
@@ -181,26 +181,38 @@ struct views_pool::data { | |||
std::vector<std::string> search_path; | |||
}; | |||
views_pool::views_pool() | |||
views_pool::views_pool() : | |||
d(new data()) | |||
{ | |||
} | |||
views_pool::views_pool(json::value const &settings) | |||
std::string views_pool::default_skin() const | |||
{ | |||
return d->default_skin; | |||
} | |||
views_pool::views_pool(json::value const &settings) : | |||
d(new data()) | |||
{ | |||
d->skins=static_instance().d->skins; | |||
std::vector<std::string> paths=settings.get("views.paths",std::vector<std::string>()); | |||
d->search_path=paths; | |||
std::vector<std::string> skins=settings.get("views.skins",std::vector<std::string>()); | |||
d->dynamic_reload= settings.get("views.auto_reload",false); | |||
if(paths.empty() || skins.empty()) | |||
d->default_skin = settings.get<std::string>("views.default_skin",""); | |||
if(d->default_skin.empty() && d->skins.size()==1) | |||
d->default_skin=d->skins.begin()->first; | |||
if(paths.empty() || skins.empty()) { | |||
return; | |||
} | |||
for(unsigned i=0;i<skins.size();i++) { | |||
std::string name=skins[i]; | |||
if(d->skins.find(name)!=d->skins.end()) | |||
throw cppcms_error("Two skins with same name provided:" + name); | |||
d->skins[name]=skin(name,paths,d->dynamic_reload); | |||
} | |||
d->default_skin = settings.get<std::string>("views.default_skin",""); | |||
if(d->default_skin.empty()) | |||
d->default_skin=skins[0]; | |||
} | |||
void views_pool::render(std::string skin_name,std::string template_name,std::ostream &out,base_content &content) | |||
@@ -241,6 +253,15 @@ views_pool::~views_pool() | |||
{ | |||
} | |||
void views_pool::add_view(std::string name,mapping_type const &mapping) | |||
{ | |||
data::skins_type::iterator p=d->skins.find(name); | |||
if(p!=d->skins.end()) | |||
throw cppcms_error("Skin " + name + "can't be loaded twice"); | |||
d->skins[name]=skin(name,mapping); | |||
} | |||
namespace { // Make sure that static views pool is loaded | |||
struct loader { | |||
loader() | |||
@@ -19,7 +19,7 @@ namespace cppcms { | |||
typedef std::map<std::string,view_factory_type> mapping_type; | |||
template<typename View,typename Content> | |||
std::auto_ptr<base_view> view_builder(std::ostream &stream,base_content *c) | |||
static std::auto_ptr<base_view> view_builder(std::ostream &stream,base_content *c) | |||
{ | |||
std::auto_ptr<base_view> p(new View(stream,dynamic_cast<Content &>(*c))); | |||
return p; | |||
@@ -29,8 +29,15 @@ namespace cppcms { | |||
views_pool(json::value const &settings); | |||
~views_pool(); | |||
void render(std::string template_name,std::ostream &out,base_content &content); | |||
/// | |||
/// Thread safe member function | |||
/// | |||
void render(std::string skin,std::string template_name,std::ostream &out,base_content &content); | |||
/// | |||
/// Get default skin name | |||
/// | |||
std::string default_skin() const; | |||
void add_view(std::string skin,mapping_type const &mapping); | |||