Usually new Pages are derived from existing ones by configuration - i.e. without writing any C++ code. However simple configuration may not work for all cases. Therefore you can always add code for any Page by writing a respective C++ class (as a subclass of Page).
And there are several sound reasons why to write code for a new Page...
All the usual configuration settings are needed whether C++ code for a Page is added or not, i.e. C++ code for a Page may be easily added after the general application structure (Roles, Pages, etc) has been setup.
Reminders: You need to register any Page that you want to use in the UI of your application in the Pages section of Config.any.
If the Page is to be used directly, there must be a respective configuration file 'ExamplePage.any' (unless your page does without any configuration):
[[#wd DisplayAnythingRenderer { /AnythingInfo { "class MyNewPage : public Page {" "public:" " MyNewPage();" " IFAObject *Clone() const;" "};" " " " " "RegisterPage(MyNewPage);" " " "MyNewPage::MyNewPage() : Page("MyNewPage")" "{" "}" " " "IFAObject *MyNewPage::Clone() const" "{" " // The New() method needs to be overridden so that other" " // Pages - that might be derived from MyNewPage purely by" " // configuration - can share the code of MyNewPage" " " " return new MyNewPage;" "}" } }]]Caution: The C++ code for a Page is always registered with the name of the class (using the RegisterPage macro in the *.cpp file):
[[#wd DisplayAnythingRenderer { /AnythingInfo { "RegisterPage(MyNewPage);" } }]]Whereas the name defined in the Page's C++ class default constructor defines the name that is used for identifying the Page at runtime and for retrieving the Page's configuration file. To work properly, the name used in the default constructor MUST match the name of the Page class:
[[#wd DisplayAnythingRenderer { /AnythingInfo { "MyNewPage::MyNewPage() : Page("MyNewPage")" "{" "}" } }]]
You place all the code that you need to have executed - before a Page
is rendered - in the method Preprocess() of the derived Page C++ class.
Example:
You want to prepare some data first (see [[#wd Lookup Recipe25 ]]).
[[#wd DisplayAnythingRenderer { /AnythingInfo { "void MyNewPage::Preprocess(Context &c)" "{" " Anything tmpStore = c.GetTmpStore();" " " " // put the necessary data in TmpStore" " // e.g. : tmpStore["MyData"]= ...." " " " Page::Preprocess(c);" "}" } }]]
Code that is executed whenever a Page is left is placed in the method
Postprocess().
Example:
HTML toggle buttons are a bit tricky, in that unset fields
are never reported by the browser.. this may be remedied
[[#wd DisplayAnythingRenderer { /AnythingInfo { "bool MyNewPage::Postprocess(String &action, Context &c)" "{" " // whenever the user leaves MyPage - by following some" " // link/button - this code is executed:" " " " // ...this might be used to synchronize UI settings etc." " " " Anything query= c.GetQuery();" " " " if (query.IsDefined("fields")) {" " Anything fields= query["fields"];" " " " if (!fields.IsDefined("myToggle"))" " fields["myToggle"]= "off";" " }" " return Page::Postprocess(action, c); " "}" } }]]
[[#wd DisplayAnythingRenderer { /AnythingInfo { "void MyNewPage::Mime(Reply &reply, Context&)" "{" " reply.AppendHeader("Content-type: application/pdf\n");" "}" } }]]