A simple C++/Wt (Witty) skeleton for starting an application

The objective of this lesson is to show you how to make a simple web page navigation using Wt. Before starting you have to remember that Wt can be used to create 1 URL applications. That means you can have a full application that runs using just one URL. However it is also useful to give your users different URL’s to take advantage of some browser features like bookmarks or the back and forward buttons.

The skeleton we are going to create is to give you the following structure:

Let’s talk about the code.

  • The onInternalPathChange function is the one in charge of switching the contents of your web page depending on your URL.
  • The functions home and page1 show the main contents of your webpage. Something interesting here is that I’m using two ways to create internal links. The first one (the one shown in home) uses a regular anchor embedded in a string. You have to notice that the link “#/page1” includes a pound sign at the beginning. That is necessary so the setInternalPathEncoding function can turn it later into a functional link. The second way to create a link uses the WAnchor and WLink classes. WLink takes two arguments: the link type (in this case we have an internal link, so we use InternalPath) and a destination (we are using “/” because we want to send the user to the root page). WAnchor takes three arguments: a WLink, a string (which is the anchor text that the user sees on his browser) and the parent container.
  • header, footer and sidebar are general functions. In my case, they are always shown. You could later create classes that inherit from WContainerWidget to turbo charge them. For formatting purposes you should also take a look at the different layout options Wt offers.

 

Here is the code:

#include <Wt/WAnchor>
#include <Wt/WApplication>
#include <Wt/WContainerwidget>
#include <Wt/WLink>
#include <Wt/WText>

using namespace Wt;

class ControlExample: public WApplication {
private:
    std::string appName;
    WContainerWidget* _content;

public:
    ControlExample(const WEnvironment &env): WApplication(env) {
        appName = "Application Name";
        setTitle(appName);
        _content = 0;
        internalPathChanged().connect(this, &ControlExample::onInternalPathChange);

        header();
        home();
        sidebar();
        footer();
    }

    WContainerWidget* content() {
        if (_content == 0) {
            _content = new WContainerWidget(root());
            _content->setId("content");
        }
        return _content;
    }

    void onInternalPathChange() {
        content()->clear();
        if (internalPath() == "/") {
            home();
        }
        else if (internalPath() == "/page1") {
            page1();
        }
    }

    void header() {
        WContainerWidget* header = new WContainerWidget(root());
        header->setId("header");
        header->addWidget(new WText("<h1>" + appName + "</h1>"));
    }

    void sidebar() {
        WContainerWidget* sidebar = new WContainerWidget(root());
        sidebar->setId("sidebar");
        sidebar->addWidget(new WText("Sidebar Information"));
    }

    void footer() {
        WContainerWidget* footer = new WContainerWidget(root());
        footer->setId("footer");
        footer->addWidget(new WText("Developed using C++/Wt"));
    }

    void home() {
        WText *t = new WText("<strong>Home</strong> content and a link to <a href='#/page1'>page1</a>");
        t->setInternalPathEncoding(true);
        content()->addWidget(t);

    }

    void page1() {
        content()->addWidget(new WText("<strong>Home</strong> content and a link to "));
        WAnchor* a = new WAnchor(WLink(WLink::InternalPath, "/"), "home", content());
    }

};

WApplication* createApplication(const WEnvironment &env) {
    return new ControlExample(env);
}

int main(int argc, char** argv) {
    return WRun(argc, argv, &createApplication);
}

 

Important: in order to run this application I have changed my –deploy-path argument in the command line to the following:

--http-address=0.0.0.0 --http-port=8080 --deploy-path=/ --docroot=.

 

As with all my previous Wt examples, you have to select and copy this code into a single .cpp file. Check out my Hello World entry to find more information about building the application.

The application should run showing something like this:

 

Happy coding.

10 Replies to “A simple C++/Wt (Witty) skeleton for starting an application”

  1. Hi Andres,

    I love what you’re doing here exactley what I had in mind so I’ll try and make complimentary tutorials to what you have done.

    In regards to this, how would you incorporate the WMenu/WStackedWidget design into the onInternalPath signal design?

    Thanks,
    Jeremy

    1. Hi Andres,

      Another question: does this architecture allow for direct navigation to particular pages. That is if you put /page1 into the url would it navigate straight there. I’m having a bit of trouble making this happen.

      Regards,

  2. Your code does not render the skeleton of the structure indicated in the wire frame diagram. The containers are all stacked vertically: the sidebar and content containers are supposed to be inline, but they aren’t.

    1. Hi Bud, you are right!

      We have to add a little CSS to achieve it. Here’s an example:

      <style type="text/css">
      	body {
      		margin: 0 auto;
      	}
      	#header {
      		background-color: #262626;
      		color: #fff;
      		padding: 0.1em 0.5em;
      	}
      	#content {
      		display: inline-block;
      		width: 65%;
      		padding: 0.5em;
      	}
      	#sidebar {
      		display: inline-block;
      		width: 30%;
      		padding: 0.5em;
      	}
      	#footer {
      		background-color: #262626;
      		color: #fff;
      		padding: 0.5em;
      	}
      </style>
  3. Yeah, much better. Thanks Andres 🙂

    The code lines in the WApplication class are:

    this->instance()->styleSheet().addRule(“#header”, “background-color: #262626; color: #fff; padding: 0.1em 0.5em;”);
    this->instance()->styleSheet().addRule(“#content”, “display: inline-block; width: 65%; padding: 0.5em;”);
    this->instance()->styleSheet().addRule(“#sidebar”, “display: inline-block; width: 30%; padding: 0.5em;”);
    this->instance()->styleSheet().addRule(“#footer”, “background-color: #262626; color: #fff; padding: 0.5em;”);
    this->instance()->styleSheet().addRule(“BODY”, “background-color: #F0F8FF;”);

    Any thought of throwing out a new Wt tutorial; like, maybe, a navigation bar or login widget?

    Your tutorials have found a place on the Wt support wiki: http://redmine.webtoolkit.eu/projects/wt/wiki/Wt_Tutorials

    So, you know, it would be nice to see a few more!

  4. Jaimes: have you thought of adding another tutorial that uses setCssTheme() to apply bootstrap theme? Maybe applied to the Wt libraries navigation bar?

    1. What would be really useful is a tutorial on authentication which would display navigation bar when user authenticated and disappear when after logout. WNavigationBar uses bootstrap, and a nice touch would be to add a custom stylesheet to enhance the page a bit beyond the bootstrap base theme.

  5. Great tutorial for a simple webpage, now Im having a little difficulties including the css or styles. If someone would be so kind as to tell me exactly how both methods are done, Id be grateful. Im a bit green when it comes to both Wt and C++, but Ive done a bit of Java programming. And I guess at least that Im missing out on an #include when I try using the styles, but in general, It would help me get on the way of using Wt if I only had the basics explained.

Leave a Reply