File: wt-sdj.xhtml

package info (click to toggle)
witty 3.1.2-3
  • links: PTS
  • area: main
  • in suites: squeeze
  • size: 45,512 kB
  • ctags: 35,832
  • sloc: cpp: 69,469; ansic: 66,945; xml: 4,383; sh: 594; perl: 108; makefile: 106
file content (98 lines) | stat: -rw-r--r-- 51,637 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="content-type" content="text/html; charset=utf-8" /><title /><meta name="generator" content="StarOffice/OpenOffice.org XSLT (http://xml.openoffice.org/sx2ml)" /><meta name="author" content="Koen Deforche" /><meta name="created" content="2005-12-30T12:33:03" /><meta name="changedby" content="Koen Deforche" /><meta name="changed" content="2006-04-08T14:57:08" /><base href="." /><style type="text/css">
	@page { size: 21.001cm 29.7cm; margin-top: 2cm; margin-bottom: 2cm; margin-left: 1.499cm; margin-right: 1.499cm }
	table { border-collapse:collapse; border-spacing:0; empty-cells:show }
	td, th { vertical-align:top; }
	h1, h2, h3, h4, h5, h6 { clear:both }
	ol, ul { padding:0; }
	*.Frame { vertical-align:middle; }
	*.Graphics { vertical-align:top; text-align:center; }
	*.Caption { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; margin-left:0.199cm; margin-right:0.199cm; margin-top:0.21cm; margin-bottom:0.21cm; text-indent:0cm; font-style:italic; clear: both }
	*.Figure { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; margin-left:0.199cm; margin-right:0.199cm; margin-top:0.21cm; margin-bottom:0.21cm; text-indent:0cm; font-style:italic; }
	*.Firstlineindent { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; margin-left:0cm; margin-right:0cm; text-indent:0.499cm; }
	*.Footer { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; }
	*.Footnote { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; margin-left:0.499cm; margin-right:0cm; text-indent:-0.499cm; }
	*.Framecontents { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.Hangingindent { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; margin-left:1cm; margin-right:0cm; text-indent:-0.499cm; }
	*.Header { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; }
	*.Heading { font-family:Arial; font-size:14pt; text-align:justify ! important; margin-top:0.423cm; margin-bottom:0.212cm; }
	*.Heading1 { font-family:Arial; font-size:16pt; text-align:justify ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-weight:bold; }
	*.Heading2 { font-family:Arial; font-size:14pt; text-align:justify ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-style:italic; font-weight:bold; }
	*.Heading3 { font-family:Arial; font-size:14pt; text-align:justify ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-weight:bold; }
	*.Heading4 { font-family:Arial; font-size:85%; text-align:justify ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-style:italic; font-weight:bold; }
	*.Index { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; }
	*.List { font-family:'Times New Roman'; font-size:10.5pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.ListIndent { font-family:'Times New Roman'; font-size:10.5pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; margin-left:5.001cm; margin-right:0cm; text-indent:-4.5cm; }
	*.P1 { font-family:'Times New Roman'; font-size:12pt; text-align:center ! important; font-style:italic; }
	*.P2 { font-family:'Times New Roman'; font-size:12pt; text-align:center ! important; }
	*.P3 { font-family:Arial; font-size:18pt; text-align:center ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-weight:bold; }
	*.P4 { font-family:'Lucida Sans'; font-size:14pt; text-align:center ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-style:italic; }
	*.P5 { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.P6 { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.P7 { font-family:Arial; font-size:12pt; text-align:justify ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-style:italic; font-weight:bold; }
	*.P8 { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.P9 { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.PreformattedText { font-family:'Courier New'; font-size:11pt; text-align:left ! important; margin-top:0cm; margin-bottom:0cm; }
	*.Sender { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; margin-top:0cm; margin-bottom:0.106cm; }
	*.Standard { font-family:'Times New Roman'; font-size:12pt; text-align:justify ! important; }
	*.Subtitle { font-family:Arial; font-size:14pt; text-align:center ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-style:italic; }
	*.Textbody { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; }
	*.Textbodyindent { font-family:'Times New Roman'; font-size:12pt; text-align:left ! important; margin-top:0cm; margin-bottom:0.212cm; margin-left:0.499cm; margin-right:0cm; text-indent:0cm; }
	*.Title { font-family:Arial; font-size:18pt; text-align:center ! important; margin-top:0.423cm; margin-bottom:0.212cm; font-weight:bold; }
	*.BulletSymbols { font-family:StarSymbol; font-size:9pt; }
	*.Captioncharacters { }
	*.Definition { }
	*.Example { font-family:'Courier New'; }
	*.Footnoteanchor { vertical-align:sup; }
	*.FootnoteSymbol { }
	*.Internetlink { color:#000080; text-decoration:underline; }
	*.SourceText { font-family:'Courier New'; }
	*.T1 { font-size:24pt; }
	*.T10 { font-family:'Times New Roman'; }
	*.T2 { font-weight:bold; }
	*.T3 { font-style:italic; }
	*.T4 { font-style:normal; }
	*.T5 { }
	*.T6 { font-family:'Courier New'; }
	*.T7 { }
	*.T8 { font-family:'Courier New'; font-size:10pt; }
	*.T9 { font-family:Arial; font-size:14pt; font-weight:bold; }
	*.VisitedInternetLink { color:#800000; text-decoration:underline; }
	</style></head><body dir="ltr">
<p>
<p class="P3"><span class="T1">A gentle introduction to the <a href="http://witty.sourceforge.net">Wt C++ Toolkit</a> for Web Applications</span></p><p class="P4">Koen Deforche and Wim Dumon, January, 2006 </p><p class="Textbody"> </p><p class="Textbody">* Originally published in <span class="T2">Software Developers Journal</span> April 2006 issue, and brought up-to-date for Wt version 1.1.0.</p>
<p class="Textbody">Also available as a <a href="wt-sdj.pdf">PDF file</a>.</p>

<h1 class="Heading1"><a name="1._Introduction" />1. Introduction</h1><h2 class="Heading2"><a name="Web_application_technology_for_the_future" />Web application technology for the future</h2>

<p class="Firstlineindent">C++ is an established language for developing many kinds of software such as desktop applications, email clients, database engines, and so on.  Still, the use of C++ for creating “web applications” has been limited. Instead, languages that dominate web application development are JAVA, PHP, Python, and Perl. With the exception of PHP, which is a language specifically designed for web development, web application frameworks are offered for the other languages to aid in web application development. Examples are J2EE and Struts for JAVA, Perl::CGI for Perl, or Zope for Python. These frameworks provide session-management, support for parsing data transmitted from the web browser from HTML forms and cookies, and help in generating the new page in response.</p>

<p style="float: right; width:50%; margin: 4ex">
  <img src="wt-sdj-models.png" style="width:100%"></img>
  Figure 1: (a) The dynamic page model traditionally used by web application frameworks, contrasted with (b) the event-driver model traditionally used by GUI toolkits, and Wt.
</p>

<p class="Textbody">
The paradigm followed by these web applications frameworks is illustrated in Figure 1(a). At each step, the web browser requests a new page to the web server, and may submit within the request a number of form values. At the server end, the web application processes the request, identifies the session, and performs business logic. Finally, the application generates the response page. The response page may contain not only HTML, but also JavaScript to enhance the interactivity of the web application. However, JavaScript has many quirks in different web browsers, and therefore requires great effort to write in a portable way. </p><p class="P5">New and highly successful web applications such as Google's Gmail or Google Maps, however, do no longer follow this page-by-page paradigm. Instead, they use a combination of JavaScript and server-side techniques, often referred to as AJAX, to dynamically update the web page with new content received from the server, <span class="T3">without reloading the web page.</span><span class="T4"> AJAX works by using JavaScript to make a HTTP request in the background to the server (e.g. 'Any new email?'). The server generates the appropriate response (e.g. 'Yes, 2: (1) ..., (2) ...'), in XML format. Finally, client-side JavaScript parses the response and updates the web page by manipulating the Document Object Model (DOM) (e.g. by prepending the two email messages to the inbox list).</span></p><p class="Textbody">This new technology which enjoyed much hype in 2005, causes a fundamental change in how web applications may be built. It is no longer necessary to transmit an entire new web page in response to every event. AJAX has fueled new possibilities for the web, and is therefore sometimes associated with an entire new and more interactive version of the web: Web 2.0. At the same time, the use of these technologies poses many challenges. The application developer needs to learn and absorb a number of technologies in order to use AJAX. In addition to the server-side framework and HTML/CSS, the developer needs to learn Dynamic HTML (DHTML) which is the manipulation of the Document Object Model (DOM) using JavaScript, some details of the HTTP protocol in order to generate valid GET or POST requests using JavaScript, and finally the usage of the XMLHttpRequest API. And to top it off, as always there is the variety of browser dialects to take into account, plus the desire to keep supporting older browsers lacking these new technologies. </p><h2 class="Heading2"><a name="Enter_Wt__21" />Enter Wt !</h2>
<p class="Firstlineindent">In contrast with the page model of traditional web applications frameworks, the model followed by Wt or a traditional GUI library is based on widgets, see Figure 1(b). The widgets are conceptually organized in a tree, and callback functions are attached to particular events. In response to an event, the callback is called, some work gets done, and/or the widget tree is modified. </p><p class="P6">Wt is a young C++ widget library for developing web applications. The application model of Wt is similar to the application models of existing GUI libraries (such as Microsoft's MFC or TrollTech's Qt). At the same time Wt hides many underlying technology details (HTML, Forms/CGI, JavaScript, AJAX, etc...) from the developer, not unlike how the Qt library hides the underlying X library or Microsoft Windows GUI details. </p><p class="P6">Because the API of Wt makes abstraction of the underlying technologies (Forms, JavaScript or AJAX), Wt chooses how to communicate with the web browser depending on technology support in the browser. The responsibility for making the application work in the jungle of web browsers is therefore also transferred from the application developers to the library developers. </p><p class="Standard"><span class="T5">In the remainder of this introductory article to Wt, we will first give an overview of the main classes and features, as well as an explanation of what Wt does behind the scenes. Next we will show how to use Wt by implementing the classic “hangman” game.</span></p><h1 class="Heading1"><a name="2._Library_overview" />2. Library overview</h1><h2 class="P7"><a name="Main_components" />Main components</h2><p class="Firstlineindent"><span class="T5">The entire user-interface is organized in a hierarchical widget tree of </span><span class="T6">WWidget</span><span class="T5"> objects. A </span><span class="T6">WWidget</span><span class="T5"> corresponds to a visible entity such as for example a piece of text (</span><span class="T6">WText</span><span class="T5">), a table (</span><span class="T6">WTable</span><span class="T5">), a line edit (</span><span class="T6">WLineEdit</span><span class="T5">), or a more complex composite widget (classes that implement </span><span class="T6">WCompositeWidget</span><span class="T5">). The user-interface, which corresponds to the web page, is specified by creating and maintaining this widget tree. Every </span><span class="T6">WWidget</span><span class="T5"> corresponds to a rectangular piece, and manages the contents and events within that rectangle.</span></p><p class="P6">The library provides a number of basic widgets that correspond directly to the widgets provided by HTML, and which are all descendants of <span class="T6">WWebWidget</span><span class="T5"> (</span><span class="T6">WText</span><span class="T5">, </span><span class="T6">WTable</span><span class="T5">, </span><span class="T6">WImage</span><span class="T5">, ...). These widgets  internally manipulate a server-side HTML DOM, which is then used by the core library to update the web page rendered by the browser. In contrast, </span><span class="T6">WCompositeWidget</span><span class="T5"> objects are widgets that are implemented by composition of other widgets. These widgets do not manipulate the DOM themselves but merely use the public API of the composing widgets. While Wt provides a number of these composite widgets (such as a tree-list widget and an auto-complete line edit), these widgets do not necessarily belong to the library, since they are implemented on top of Wt.</span></p><p class="Textbody"><span class="T5">Every Wt application must start with the instantiation of a </span><span class="T6">WApplication</span><span class="T5"> object. This object manages the root of the widget tree, information on browser capabilities and manages internationalization support using a locale and message resource bundles (see further).</span></p><h2 class="P7"><a name="Session_management" />Session management</h2><p class="Firstlineindent"><span class="T5">Similar to how multiple instances of conventional applications may be run concurrently, so will the Wt core system spawn multiple Wt applications for every independent web session. Each new “session” implies a new path of execution which starts in </span><span class="T6">wmain()</span><span class="T5">, which is the application entry point. Thus, the programmer only needs to implement a single-user application, unless users interact with a common component (such as a database) or with each other, for which standard data-sharing mechanisms must be used.</span></p><p class="P6">The current version of Wt implements these different paths of execution using different processes. Thus, for every new session, Wt spawns a new process. This has the main benefit of enjoying kernel-level memory protection between user sessions. As a consequence simple programming mistakes will not automatically compromise session-privacy. The downside of this approach is cost: current kernel implementations may require some amount of non-swappable memory associated with every process. In the future, Wt may offer different thread implementation choices, including user-level threads. </p><h2 class="Heading2"><a name="Signal_2FSlot_event_propagation" />Signal/Slot event propagation</h2><p class="Firstlineindent">Wt uses a signal/slot implementation for event propagation. User-interface events, such as mouse clicks, or text modifications, are exposed by Wt as <span class="T3">signals </span><span class="T4">associated with particular widgets</span>. To respond to an event, the programmer connects the respective signal to a <span class="T3">slot</span>. Any object method with a signature compatible with the signal may be used as a slot. Whenever the signal is emitted, all slots that have been connected to the signal are called. The signal/slot paradigm is a well-established type-safe and self-managed alternative to callbacks.</p><h2 class="Heading2"><a name="Internationalization" />Internationalization</h2><p class="Firstlineindent"><span class="T5">Internationalization and localization is an important property of a website, given the inherent global scope of the World-Wide-Web. Wt assists in internationalization by offering message resource bundles. A </span><span class="T6">WMessage</span><span class="T5"> object provides a piece of text which is dependent on the current locale. Widgets that display text to the user (such as </span><span class="T6">WText</span><span class="T5">) may be given a </span><span class="T6">WMessage</span><span class="T5"> instead of raw text. The message translations for every locale are stored in XML format in message resource files, one for every locale. When changing the application locale, using </span><span class="T6">WApplication::setLocale()</span><span class="T5">, the application automatically updates the corresponding widgets with the localized text.</span></p><h2 class="Heading2"><a name="Non-intrusive_upgrades" />Non-intrusive upgrades</h2><p class="Firstlineindent">Web applications enjoy a major advantage over conventional applications since the publisher can easily upgrade all copies of the application, by merely deploying a new version on his website. Usually the publisher may not want to terminate running sessions when deploying a new version, but instead offer the new version to new sessions. This process of non-intrusive upgrades is the default method of upgrading in Wt. </p><h2 class="Heading2"><a name="Session_lifetime" />Session lifetime</h2><p class="Firstlineindent"><span class="T5">Wt uses a keep-alive protocol between client and server to determine session lifetime. As long as the web page is displayed in the user's browser, the session is kept alive, otherwise the session is terminated. In addition the application can choose to end the session (for example in response to the user 'logging out'), by calling </span><span class="T6">WApplication::quit()</span><span class="T5">. Either way, when a session terminates, the main widget is destroyed. This allows the application to release any application-specific resources.</span></p><h2 class="Heading2"><a name="How_does_it_work_3F" />How does it work?</h2><p class="Firstlineindent">Wt implements two main tasks: rendering and maintaining the HTML DOM tree in the web browser, and responding to user input and user events, such as mouse clicks. </p><p class="P8"><span class="T5">All events that may be caught for processing are mapped to signals, which are available in the respective widgets. When an event is triggered by the user (e.g. a click on an 'OK' button), the web browser communicates the target object and corresponding signal (for example </span><span class="T6">OkButton-&gt;clicked</span><span class="T5">), together with all form data to the web server (using AJAX or plain HTML form submission). At the server, the corresponding Wt application instance processes first all form data to update the widget tree state. Then, the event is propagated by emitting the signal of the target object, which triggers all connected slots. These may perform business logic and modify the widget tree. Modifications to the widget tree are tracked by the library, and converted to modifications to a server-side model of the HTML DOM tree. Finally, depending on the method for communication, either the DOM tree changes, or the complete modified DOM tree are communicated back to the web browser, completing the event cycle.</span></p><p class="P6">Because of the clear separation between user-interface specification using the widget tree and the mechanism of rendering the tree, Wt optimizes rendering for increased responsiveness when AJAX is available. Wt accomplishes this by transmitting only visible widget changes during the first communication with the web browser. As soon as the page is loaded, remaining hidden widgets changes are transmitted in the background. As a consequence, both the initial response is optimized and the appearance of subsequent widgets appears snappy. </p><h1 class="Heading1"><a name="3._Tutorial" />3. Tutorial</h1><p class="Firstlineindent"><span class="T5">The tutorial section discusses two small programs to illustrate various Wt library concepts. The first program is a Hello World application, introducing two key concepts of the library: the widget tree and signal/slots. The second larger program is an online version of the classic hangman game, including a user ranking system, backed by a small database. The game is available online</span><span class="T5" /><span class="T5">. The hangman game illustrates how a widget tree for a more complex web application is constructed and managed, how to write your own widgets, signals and slots, how layout is handled, and offers an example of how data can be extracted from a database to be displayed on the website. The complete source code of the game is around 900 lines including comments. We selected the most interesting parts for this tutorial.</span></p><p class="Textbody"><span class="T5">The Wt documentation page</span><span class="T5" /><span class="T5"> contains an exhaustive list of  classes, methods, signals and slots exposed in the Wt API. Even the Hangman demo only uses a small portion of the available classes and methods. The complete sources of the tutorial examples, together with Makefiles to build them, are included in the Wt source distribution.</span></p><h2 class="Heading2"><a name="The_omnipresent_Hello_World" />The omnipresent Hello World</h2><p class="Firstlineindent"><span class="T5">The entry point of every Wt program is the </span><span class="T6">wmain()</span><span class="T5"> function. The simplest Wt program must instantiate the </span><span class="T6">WApplication</span><span class="T5"> object, and call the application idle loop. For the hello world application, a </span><span class="T6">WText</span><span class="T5"> object and a </span><span class="T6">WPushButton</span><span class="T5"> were added, having the root of the widget tree as parent. This will make them appear in the web browser. Clicking the Quit button cleanly terminates the session. This is achieved by connecting the </span><span class="T6">clicked</span><span class="T5"> signal of the Quit button with the </span><span class="T6">quit()</span><span class="T5"> slot of the application.</span></p><p class="Textbody"><span class="T5">It is important to remark that there is no obligation to call </span><span class="T6">quit()</span><span class="T5"> explicitly. When the user navigates away from the web application, Wt will detect that keep-alive messages are no longer received, and Wt will terminate the session as if </span><span class="T6">quit()</span><span class="T5"> was called.</span></p><p class="Caption">Listing 1. Hello World with Quit button </p><p class="PreformattedText">#include &lt;WApplication&gt; </p><p class="PreformattedText">#include &lt;WText&gt; </p><p class="PreformattedText">#include &lt;WPushButton&gt; </p><p class="PreformattedText"> </p><p class="PreformattedText">int wmain(int argc, char **argv) </p><p class="PreformattedText">{ </p><p class="PreformattedText">   WApplication appl(argc, argv);</p><p class="PreformattedText"> </p><p class="PreformattedText">   // Widgets can be added to a parent</p><p class="PreformattedText">   // by calling addWidget() ...</p><p class="PreformattedText">   appl.root()-&gt;addWidget(new Wtext("&lt;h1&gt;Hello, World!&lt;/h1&gt;"));</p><p class="PreformattedText"> </p><p class="PreformattedText">   // ... or by specifying a parent at</p><p class="PreformattedText">   // construction time</p><p class="PreformattedText">   WPushButton *Button = new WPushButton("Quit", appl.root());</p><p class="PreformattedText"> </p><p class="PreformattedText">   Button-&gt;clicked.connect(SLOT(&amp;appl, Wapplication::quit));</p><p class="PreformattedText">   return appl.exec();</p><p class="PreformattedText">} </p><h2 class="Heading2"><a name="My_first_widget" />My first widget</h2>


<p style="float: right; width:50%; margin: 4ex">
  <img src="wt-sdj-login.png" style="width:100%"></img>
  Figure 2: The hangman login widget, right after construction. Listing 3 is the source code for this web page.
</p>
<p class="Firstlineindent">We start the discussion the hangman game with the login process. This is handled by the LoginWidget. We have kept the business logic to a minimum, and indeed a bit simplistic. The LoginWidget invites the returning user to login using his user name and password, and to choose one of the available dictionaries from which words will used for the game. If the user was not present in the user database, we assume a new user and he is automatically added to the database. On successful login, a confirmation is displayed, otherwise the user is notified of the problem and may try again. </p><p class="P6">Hangman's LoginWidget demonstrates the possibility to write self-contained widgets in a nice object-oriented fashion, with clean interfaces, ready to be plugged in where they are required. The LoginWidget, with its non-standard behavior, may not immediately be a candidate for reuse, but nevertheless it demonstrates the interface principles. The LoginWidget has only two public member functions. The first is the constructor, which takes the parent widget as an argument. Since all built-in widgets take their parent as an argument in the constructor, it is a consistent approach to do this as well for custom widgets. The second member is a signal that will be emitted when the login process has been successfully completed. The signal also carries the user name, and the chosen game dictionary. </p><p class="P6">The object oriented widget tree approach for GUI libraries has led to a significant amount of widget reuse, which is evident from large scale desktop projects such as KDE. Especially where widgets cover pretty simple concepts, reuse of a widget is often no more complex than instantiating it in the right location of the object tree. The remainder of a program may interact with the widget using its methods and by installing callback functions to react to events. Traditional GUI widget examples are an expandable tree list, a file-open dialog, etc... which are almost always included in the GUI libraries. Wt introduces the exact same paradigm to the world of web programming, and invites the programmer to partition a web application in well defined and self contained widgets. </p><p class="Caption">Listing 2. LoginWidget class definition. </p><p class="PreformattedText"><span class="SourceText">class LoginWidget : public WContainerWidget</span></p><p class="PreformattedText"><span class="SourceText">{</span></p><p class="PreformattedText"><span class="T8">  public:</span></p><p class="PreformattedText"><span class="SourceText">    LoginWidget(WContainerWidget *parent = 0);</span></p><p class="PreformattedText"><span class="SourceText" /></p><p class="PreformattedText"><span class="SourceText">  public signals:</span></p><p class="PreformattedText"><span class="SourceText">    </span><span class="SourceText"><span class="T8">Wt::Signal&lt;std::string, Dictionary&gt;</span></span><span class="SourceText"> loginSuccessful;</span></p><p class="PreformattedText"><span class="SourceText" /></p><p class="PreformattedText"><span class="SourceText">  private slots:</span></p><p class="PreformattedText"><span class="SourceText">    void checkCredentials();</span></p><p class="PreformattedText"><span class="SourceText">    void startPlaying();</span></p><p class="PreformattedText"><span class="SourceText" /></p><p class="PreformattedText"><span class="SourceText">  private:</span></p><p class="PreformattedText"><span class="SourceText">    WText *IntroText;</span></p><p class="PreformattedText"><span class="SourceText">    WLineEdit *Username;</span></p><p class="PreformattedText"><span class="SourceText">    WLineEdit *Password;</span></p><p class="PreformattedText"><span class="SourceText">    WComboBox *Language;</span></p><p class="PreformattedText"><span class="SourceText">    std::string User;</span></p><p class="PreformattedText"><span class="SourceText">    Dictionary  Dict;</span></p><p class="PreformattedText"><span class="SourceText">    void confirmLogin(const std::string text);</span></p><p class="PreformattedText"><span class="SourceText">};</span></p><p class="PreformattedText"> </p><p class="P6">In Listing 2, we show the class definition of the LoginWidget class. The LoginWidget defines a public signal, <span class="SourceText">loginSuccessful</span>, and uses internally a number of slots to react to user events. Therefore, we must inherit (directly or indirectly) from <span class="SourceText">WObject</span>. We then declare signals and methods that will be used as in the class declaration.</p><p class="P6">LoginWidget inherits from <span class="SourceText">WContainerWidget</span>. A <span class="SourceText">WContainerWidget</span> is a widget which holds and manages child widgets. The parent of a widget is always a <span class="SourceText">WContainerWidget</span> or one of its derived classes (such as <span class="SourceText">WStackedWidget</span> or <span class="SourceText">WTableCell</span>). Children in a <span class="SourceText">WContainerWidget</span> are layed out in the order in which they were added to the container. The inline property of a widget determines its default layout behavior within the container. In-line widgets are layed out like words in a text, following lines and  wrapping at the right border of the container. Non in-line widgets are formatted as a new paragraph. Widgets may also be lifted out of this default layout flow to be manually positioned in various ways, but we will not discuss this here. Instead, as illustrated in the constructor discussed below, a <span class="SourceText">WTable</span> is used to create a more sophisticated layout.</p>

<p class="P6">The login widget, as rendered by Firefox, is shown in Figure 2. The code that generates this interactive form is entirely located inside the constructor of LoginWidget, which is shown in Listing 3. </p>

<p class="Caption">Listing 3. The LoginWidget constructor implementation. </p><p class="PreformattedText">LoginWidget::LoginWidget(WContainerWidget *parent)  </p><p class="PreformattedText">  : WContainerWidget(parent)</p><p class="PreformattedText">{ </p><p class="PreformattedText">  setPadding(WLength(100), Left | Right);</p><p class="PreformattedText"> </p><p class="PreformattedText">  WText *title = new WText("Login", this);</p><p class="PreformattedText">  title-&gt;decorationStyle().font().setSize(WFont::XLarge);</p><p class="PreformattedText"> </p><p class="PreformattedText">  IntroText = new Wtext("&lt;p&gt;Hangman keeps track of the best"</p><p class="PreformattedText">    "players. To recognize you, we ask you to log in. "</p><p class="PreformattedText">    "If you never logged in before, choose any name and "</p><p class="PreformattedText">    "password.&lt;/p&gt;", this);</p><p class="PreformattedText"> </p><p class="PreformattedText">  WTable *layout = new WTable(this);</p><p class="PreformattedText">  WLabel *usernameLabel = new WLabel("User name: ",</p><p class="PreformattedText">                                     layout-&gt;elementAt(0, 0));</p><p class="PreformattedText">  layout-&gt;elementAt(0, 0)-&gt;resize(WLength(14, Wlength::FontEx),</p><p class="PreformattedText">                                  WLength());</p><p class="PreformattedText">  Username = new WLineEdit(layout-&gt;elementAt(0, 1));</p><p class="PreformattedText">  usernameLabel-&gt;setBuddy(Username);</p><p class="PreformattedText"> </p><p class="PreformattedText">  WLabel *passwordLabel = new WLabel("Password: ",</p><p class="PreformattedText">                                     layout-&gt;elementAt(1, 0));</p><p class="PreformattedText">  Password = new WLineEdit(layout-&gt;elementAt(1, 1));</p><p class="PreformattedText">  Password-&gt;setEchoMode(WLineEdit::Password);</p><p class="PreformattedText">  passwordLabel-&gt;setBuddy(Password);</p><p class="PreformattedText"> </p><p class="PreformattedText">  WLabel *languageLabel= new WLabel("Language: ",</p><p class="PreformattedText">                                    layout-&gt;elementAt(2, 0));</p><p class="PreformattedText">  Language = new WcomboBox(layout-&gt;elementAt(2, 1));</p><p class="PreformattedText">  Language-&gt;insertItem(0, "English words (18957 words)");</p><p class="PreformattedText">  Language-&gt;insertItem(1, "Nederlandse woordjes (1688 woorden)");</p><p class="PreformattedText">  languageLabel-&gt;setBuddy(Language);</p><p class="PreformattedText"> </p><p class="PreformattedText">  new WBreak(this);</p><p class="PreformattedText"> </p><p class="PreformattedText">  WPushButton *LoginButton = new WPushButton("Login", this);</p><p class="PreformattedText">  LoginButton-&gt;clicked.connect(SLOT(this, LoginWidget::checkCredentials));</p><p class="PreformattedText">} </p><p class="P6"> </p><p class="P6">The constructor introduces a number of new concepts. We had encountered the <span class="SourceText">WText</span> and <span class="SourceText">WPushButton</span> already in the hello world example. The new widgets will hold few surprises. <span class="SourceText">WLineEdit</span> provides a single line edit input and <span class="SourceText">WComboBox</span> provides a drop-down selection box. The latter is populated with selection options using <span class="SourceText">insertItem()</span>. We use the <span class="SourceText">WLabel</span> class to provide labels for the three input fields, and tie them to the corresponding input-field using <span class="SourceText">setBuddy()</span>. By using <span class="SourceText">WLabel</span> instead of <span class="SourceText">WText</span>, the user may click on the label to give focus to the corresponding input field. <span class="SourceText">WTable</span> is a table, in this case used for layout purposes. The table cells, accessed using elementAt(row, column), are used as parent widget for some of the text widgets, the line inputs, and the combo box, so that they are layed out in an array. Finally, <span class="SourceText">WBreak</span> is the equivalent of the HTML line break tag (<span class="SourceText">&lt;br /&gt;</span>), and lets subsequent inline widgets start a new line.</p><p class="P6">The <span class="SourceText">setPadding()</span> call adds empty space within LoginWidget between its border and its children. The <span class="SourceText">WLength</span> class offers an interface to the CSS method of specifying sizes. An 'automatic' length is created by calling the default constructor. When constructed with parameters, a value and a unit (defaulting to <span class="SourceText">WLength::Pixels</span>) are specified. All CSS units (pixels, font height, font width, cm, percentage, ...) are supported by the <span class="SourceText">WLength</span> class. A few lines below the <span class="SourceText">setPadding()</span> call, the <span class="SourceText">WLength</span> class appears again, in the line where the table cell is resized. The table width is set to 14 font width units, while the height remains the default.</p><p class="P6">The last important new aspect of Wt in this constructor is the use of <span class="SourceText">decorationStyle()</span> to access style properties of a widget, which we use to set the font size of the title to extra large. In the hello world example, we used the old-fashioned <span class="SourceText">&lt;h2&gt;..&lt;/h2&gt;</span>, but here we demonstrate that you can apply CSS-based styles. This method will reappear in other functions.</p><p class="P6">We use <span class="SourceText">setEchoMode()</span> to mask the entered password with stars. Finally, the <span class="SourceText">connect()</span> call is similar as in the hello world application, but here we connect the <span class="SourceText">clicked</span> signal to the <span class="SourceText">LoginWidget::checkCredentials</span> slot.</p><p class="Caption">Listing 4. Methods <span class="SourceText">checkCredentials()</span> and <span class="SourceText">confirmLogin()</span> of the LoginWidget class.</p><p class="PreformattedText">void LoginWidget::checkCredentials() </p><p class="PreformattedText">{ </p><p class="PreformattedText">  User = Username-&gt;text();</p><p class="PreformattedText">  std::string pass = Password-&gt;text();</p><p class="PreformattedText">  Dict = (Dictionary) Language-&gt;currentIndex();</p><p class="PreformattedText"> </p><p class="PreformattedText">  if (HangmanDb::validLogin(User, pass)) {</p><p class="PreformattedText">    confirmLogin("&lt;p&gt;Welcome back, " + User + ".&lt;/p&gt;");</p><p class="PreformattedText">  } else</p><p class="PreformattedText">    if (HangmanDb::addUser(User, pass)) {</p><p class="PreformattedText">      confirmLogin("&lt;p&gt;Welcome, " + User</p><p class="PreformattedText">        + ". Good luck with your first game!&lt;/p&gt;");</p><p class="PreformattedText">    } else {</p><p class="PreformattedText">      IntroText-&gt;setText("&lt;p&gt;You entered the wrong"</p><p class="PreformattedText">          " username/password, please try again.&lt;/p&gt;");</p><p class="PreformattedText">      IntroText-&gt;decorationStyle().setForegroundColor(Wt::red);</p><p class="PreformattedText">      Username-&gt;setText("");</p><p class="PreformattedText">      Password-&gt;setText("");</p><p class="PreformattedText">    }</p><p class="PreformattedText">} </p><p class="PreformattedText"> </p><p class="PreformattedText">void LoginWidget::confirmLogin(const std::string text) </p><p class="PreformattedText">{ </p><p class="PreformattedText">  clear();</p><p class="PreformattedText"> </p><p class="PreformattedText">  WText *title = new WText("Loging successful", this);</p><p class="PreformattedText">  title-&gt;decorationStyle().font().setSize(WFont::XLarge);</p><p class="PreformattedText"> </p><p class="PreformattedText">  new WText(text, this);</p><p class="PreformattedText">  (new WPushButton("Start playing", this))</p><p class="PreformattedText">    -&gt;clicked.connect(SLOT(this, LoginWidget::startPlaying));</p><p class="PreformattedText">} </p><p class="PreformattedText"> </p><p class="P6">In <span class="SourceText">checkCredentials()</span> we validate the user and password that were entered. Therefore, it is a fine example of how user input is retrieved and how the webpage can be modified as a reaction to user input. In the first three lines, the user name, password, and language selection provided by the user are retrieved from the <span class="SourceText">WLineEdit</span> and <span class="SourceText">WComboBox</span> widgets, using respectively the <span class="SourceText">text()</span> and <span class="SourceText">currentIndex()</span> method calls. These methods always return the up-to-date values for these widgets, without any intervention from the programmer. This may not be surprising for a GUI library, but is a huge simplification compared to the traditional and tedious form-based content retrieval commonly found in web application frameworks.</p><p class="P6">In the subsequent code, the credentials are verified, and we call <span class="SourceText">confirmLogin()</span> when the login was successful. Otherwise we change the displayed message stored in the IntroText widget using <span class="SourceText">setText()</span> to notify the user of the failure. In addition, we change the message text color to red to alert the user. Text color is another property that can be accessed using <span class="SourceText">decorationStyle()</span>, which we previously used to set the font size of the title. Finally, we complete the slot implementation by clearing the user name and password text.</p><p class="P6">The most interesting and maybe surprising aspect of this slot implementation may be in the code that is not there! Wt has two possible ways for updating the web browser page: either by letting the browser move to a new page, or by using JavaScript, AJAX and DHMTL to update the current web page. Because the code does not specify the mechanism but only the desired result, Wt may use either of these methods depending on support for JavaScript and AJAX at the client. </p><p class="P6">We have kept the database interface simple on purpose. <span class="SourceText">HangmanDb::validLogin()</span> verifies if the user/password combination is stored in the database. If this fails, we try to add the user by means of the <span class="SourceText">HangmanDb::addUser()</span> call. This call will fail if the user name was already in the database. Even though the implementation of these functions will not be discussed in this article, it is worth to mention that they use the MySQL++ library to interact with a MySQL database.</p><p class="P6">When the login was successful, we display a welcome message and a confirmation of the login, which is implemented in <span class="SourceText">c</span><span class="SourceText"><span class="SourceText">onfirmLogin</span></span><span class="SourceText">()</span>. If you have digested the LoginWidget implementation well so far, you will find that this method contains no new magic. First, we use <span class="SourceText">clear()</span> to clear the container widget contents. Finally, in one statement we create a new button and at once connect its <span class="SourceText">clicked</span> signal to the <span class="SourceText">startPlaying()</span> slot.</p><p class="Caption">Listing 5. <span class="SourceText">LoginWidget::startPlaying()</span> slot implementation.</p><p class="PreformattedText">void LoginWidget::startPlaying() </p><p class="PreformattedText">{ </p><p class="PreformattedText">   emit(loginSuccessful(User, Dict));</p><p class="PreformattedText">} </p><p class="P6"> </p><p class="P6">The <span class="SourceText">startPlaying()</span> slot demonstrates how to emit a signal, in this case with arguments. What happens in response to the signal depends on slots that have been connected to this signal.</p><p class="P6">This concludes the entire implementation of the LoginWidget. In the remaining of the tutorial, we will reuse the same concepts that were used for the LoginWidget, to create highly responsive AJAX-enabled web applications. Because of the widget abstraction, you need no knowledge of JavaScript and even your knowledge of HTML can be minimal. On the other hand, Wt makes no big effort to abstract the decorative CSS concepts, instead exposing them almost directly using <span class="SourceText">decorationStyle()</span>. Therefore, familiarity with CSS will help you to style a Wt application.</p><h2 class="Heading2"><a name="The_second_widget_3A_unleashing_Wt_27s_power" />The second widget: unleashing <span class="T9">Wt</span>'s power</h2>
<p style="float: right; width:50%; margin: 4ex">
  <img src="wt-sdj-action.png" style="width:100%"></img>
  Figure 3: Hangman screen shot: an AJAX and DHTML web-application, entirely programmed in C++. All images are preloaded in the browser for improved user experience.
</p>
<p class="Firstlineindent">Until now, we introduced a rather unique paradigm to program web applications. We demonstrated Wt's added value to the programmer. The next widget also illustrates some new Wt widgets and features, but we also demonstrate an important aspect of Wt that highly enhances the user experience. One of the most appealing features of popular web applications like Google's Gmail and Google Maps is the excellent response time. Google has spent quite some effort in developing client-side JavaScript and AJAX code to achieve this. With few effort <span class="T10">–</span> indeed almost automatically <span class="T10">–</span> you can get similar response times using Wt, and indeed the library will be using similar techniques to achieve this. A nice bonus of using Wt is that the application will still function correctly even when AJAX or JavaScript support is not available! The HangmanWidget class, which we discuss next, contains some of these techniques.</p>

<p class="P6">HangmanWidget contains the real hangman game logic. Figure 3 is a screen shot of the game in action. For each new game, the program chooses a random secret word for the player to guess. From the alphabet, the player guesses a letter, and if the letter is part of the secret word, its occurrences in the word are revealed. In case of a wrong guess, you get one step closer to a hanging man. At the end of the game, we update the users score in the database, and offer the user the possibility to start a new game. The implementation of HangmanWidget contains few novelties, except for how we handle the hangman images. </p><p class="P6">In the constructor we construct the user interface. The part that constructs the images is isolated in the method <span class="SourceText">createImages()</span>.</p><p class="Caption">Listing 6. Hidden widgets are prefetched by the browser, ready to be displayed when <span class="SourceText">show()</span> is called.</p><p class="PreformattedText">void HangmanWidget::createHangmanImages(WContainerWidget *parent) </p><p class="PreformattedText">{ </p><p class="PreformattedText">  for (unsigned int i = 0; i &lt;= MaxGuesses; ++i) {</p><p class="PreformattedText">    std::string fname = "icons/hangman"</p><p class="PreformattedText">      + boost::lexical_cast&lt;std::string&gt;(i)</p><p class="PreformattedText">      + ".png";</p><p class="PreformattedText"> </p><p class="PreformattedText">    WImage *theImage = new WImage(fname, parent);</p><p class="PreformattedText">    HangmanImages.push_back(theImage);</p><p class="PreformattedText">  }</p><p class="PreformattedText"> </p><p class="PreformattedText">  HurrayImage = new Wimage("icons/hangmanhurray.png", parent);</p><p class="PreformattedText"> </p><p class="PreformattedText">  resetImages(); // Hide all images</p><p class="PreformattedText">} </p><p class="PreformattedText"> </p><p class="PreformattedText">void HangmanWidget::resetImages() </p><p class="PreformattedText">{ </p><p class="PreformattedText">  HurrayImage-&gt;hide();</p><p class="PreformattedText">  for (unsigned int i = 0; i &lt; HangmanImages.size(); ++i)</p><p class="PreformattedText">    HangmanImages[i]-&gt;hide();</p><p class="PreformattedText">} </p><p class="P6"> </p><p class="P6">This function introduces a new widget: the <span class="SourceText">WImage</span>, which not surprisingly corresponds to an image in HTML. The code shows how all widgets are created and inserted into the HangmanWidget. With what we discussed until now, we would expect that all images are displayed at the same time, which is clearly not what we want. Therefore, we call <span class="SourceText">resetImages()</span> after the images are created, and this method calls <span class="SourceText">hide()</span> on every image, after which none of them are visible. The game logic will show and hide the images, so that only the correct one is visible at any point in the game. Every <span class="SourceText">WWidget</span> can be hidden, and hidden widgets can be redisplayed by calling <span class="SourceText">show()</span>. But why do we create and hide them, where instead we could simply create and delete the <span class="SourceText">WImage</span> that we want to show? Alternatively we could work with only one image and modify the source of the image to change image! The answer lies in the response time, at least when AJAX is available. Wt first transfers information about visible widgets to the web browser. When the visible part of web page is rendered, the remaining hidden widgets are transmitted and inserted by the web browser into the DOM tree. Most web browsers will also preload the images referred to in these hidden widgets. As a consequence, when the user clicks on a letter button and we need to update the hangman image, we simply hide and show the correct image widget. Then, only a single HTTP request with a small response are communicated between the web browser and the server. An alternative implementation would invariably have caused the browser to fetch the new image, requiring a second round-trip to the server, plus the time to download the image. The hangman game uses this principle of hidden widgets frequently, for example also when you switch between high scores and the game. At any point in time, only one of these widgets is shown, and the user switches between these two widgets using the menu bar at the bottom. Wt is able to further reduce the reaction time in some cases by transferring the slot implementation completely to the browser, with the use of the so-called static signal/slot connections, but that discussion falls outside the scope of this introductory tutorial.</p><p class="P6">In summary, the use of hidden widgets is a simple and effective way to implement performant Wt applications. Hidden widgets do not compromise the application load time, since visible widgets are transferred first. </p><p class="P6">We will skip the implementation of the HighScoresWidget and the HangmanGame because they demonstrate no fundamental additional features. HighScoresWidget displays the highest ranking users, and HangmanGame connects together the LoginWidget, the HangmanWidget, and the HighScoresWidget. Information-hungry readers are however invited to take a quick look at the HangmanGame source, since it uses clickable text (no, not hyperlinks) to implement a menu bar and demonstrates the use <span class="SourceText">WStackedWidget</span>, a specialization of the <span class="SourceText">WcontainerWidget</span>.</p><h1 class="Heading1"><a name="4._Summary" />4. Summary</h1><p class="Firstlineindent">The Wt library provides an effective way to implement web applications and frees the application developer of many technical aspects and quirks associated with new web technologies such as JavaScript, AJAX and DHTML. Because of the many similarities between Wt and other GUI toolkits, application developers can treat the web browser in many aspects as just another GUI platform. </p><p class="P6">The tutorial demonstrated many important Wt features, but far from all Wt features. Static slots, which further improve event response times, file uploads and dynamic resources, internationalization, full CSS support, and many undiscussed widgets are only a selection of what we had to skip. For more information, we refer the reader to the online Wt documentation resources. </p>
</p>
</body></html>