Commit 3efc72c9 authored by Dave Cooper's avatar Dave Cooper
Browse files

updated manual with first part of Custom User Interfaces section.

parent d5bb82e3
......@@ -32,7 +32,7 @@
(right-section-inner-html (with-cl-who-string ()
((:a :name "Top"))
(:h1 "Configure Your Future: $" (fmt "~:d" (ceiling (the current-price))))
(:h1 "Estimated Pricing: $" (fmt "~:d" (ceiling (the current-price))))
(str (the current-choice-screen inner-html))
(str (the summary inner-html))
......
......@@ -181,11 +181,11 @@
:current-price
(funcall (the discount-func)
(ecase (the selected-gendl-license)
(:agpl (if (the academic?) 4500 6000))
(:agpl (if (the academic?) (* 4500 1.2) (* 6000 1.2)))
(:trial 0)
(:student 100)
(:professional (if (the academic?) 3000 4500))
(:enterprise (if (the academic?) 4500 6000)))
(:student (* 100 1.2))
(:professional (if (the academic?) (* 3000 1.2) (* 4500 1.2)))
(:enterprise (if (the academic?) (* 4500 1.2) (* 6000 1.2))))
(first (the-child root-path))))
(lw-32-base :type 'radio-price-choice
......
......@@ -29,7 +29,7 @@
(link-title "Home")
(right-section-inner-html
(with-cl-who-string ()
(:h2 "Welcome to Genworks")
(:h2 "Welcome to Genworks [Happy New Year! New site prototype, being released slightly before it is ready...]")
((:div :id "welcome")
((:img :src "/newsite-static/images/logo-transparent.png" :ALT "star-logo" :CLASS "left" :WIDTH "155"
:height "149"))
......
......@@ -239,15 +239,21 @@ Generative Programming, Dynamic Languages, 3D Geometry, NURBS, Solid Modeling, D
:inner-html (with-cl-who-string ()
((:div :class "news")
(:h2 "Latest News")
(:h3 "2012-03-28")
(:h3 "2012-12-31")
(:p
"New Genworks Website prototype is launched.")
"New Genworks Website made live.")
((:div :class "hr-dots"))
(:h3 "2012-03-15")
(:p
"Integration and Testing of Genworks GDL 1581 (GenDL) with "
((:a :href "http://www.smlib.com") " SMLib 8.51 ")
" is completed.")
(:h3 "2012-12-15")
(:p "Port of core Genworks GenDL
to " ((:a :href "http://www.clozure.com/clozurecl") "Clozure Common Lisp") " (CCL) is completed.")
((:div :class "hr-dots"))
(:h3 "2012-11-30")
(:p "GenDL 1582 Professional and Student version is released.")
((:div :class "hr-dots"))
(if (eql self (the news))
(htm ((:p :class "more")
((:a :href (the (relative-url-to (the index-html url)))) "less...")))
......
......@@ -31,6 +31,17 @@
(right-section-inner-html
(with-cl-who-string ()
(:h2 "Prior News")
(:h3 "2012-03-28")
(:p
"New Genworks Website prototype is launched.")
((:div :class "hr-dots"))
(:h3 "2012-03-15")
(:p
"Integration and Testing of Genworks GDL 1581 (GenDL) with "
((:a :href "http://www.smlib.com") " SMLib 8.51 ")
" is completed.")
((:div :class "hr-dots"))
(:H3 "2012-03-01")
(:p "Genworks GDL (GenDL)included as a standard dist with " ((:a :href "http://www.quicklisp.org") "Quicklisp") ".")
((:div :class "hr-dots"))
......
......@@ -32,14 +32,6 @@
(with-cl-who-string ()
(:h2 "The People who make Genworks possible")
(:h3 "J.R. \"Bob\" Dobbs")
((:div :class "profile")
((:div :class "people")
(:h4 "President")
(:p
"\"Bob\" founded Genworks in 1997 with the intention to make Generative technology and
Knowledge Based Engineering available to more than just the toplevel niche markets.")))
(:h3 "Dave Cooper")
((:div :class "profile")
((:div :class "people")
......
......@@ -30,5 +30,6 @@
(publish-gwl-app "/newsite" "www.genworks.com:assembly")
(publish-gwl-app "/" "www.genworks.com:assembly")
(publish-gwl-app "/newsite/" "www.genworks.com:assembly")
(publish-gwl-app "/newsite.html" "www.genworks.com:assembly")
......@@ -29,7 +29,7 @@
:destination static))
(publish-gwl-app "/" "genworks.com:assembly")
;;(publish-gwl-app "/" "genworks.com:assembly")
#+nil
(dolist (host (list "cl-users.com" "cl-users.org" "cl-users.net"
......
......@@ -9,7 +9,7 @@
:serial
t
:version
"2012122900"
"2013010200"
:depends-on
(:gdl-dom)
:components
......@@ -24,4 +24,5 @@
(:gdl "source/advanced-gendl")
(:file "source/tasty-environment")
(:file "source/gendl-geometry")
(:file "source/custom-user-interfaces")
(:file "source/assembly")))
\ No newline at end of file
......@@ -176,16 +176,50 @@
\newlabel{subsec:viewframes}{{6.0.2}{39}{View Frames\relax }{subsection.6.0.2}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {6.4}{\ignorespaces Shock Absorber Assembly V0.1}}{41}{figure.6.4}}
\newlabel{fig:shockabsorberassemblyv01}{{6.4}{41}{Shock Absorber Assembly V0.1\relax }{figure.6.4}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {6.5}{\ignorespaces Tasty Inspector}}{42}{figure.6.5}}
\newlabel{fig:tasty-inspector}{{6.5}{42}{Tasty Inspector\relax }{figure.6.5}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {6.6}{\ignorespaces Settable Slots in Tasty}}{42}{figure.6.6}}
\newlabel{fig:tasty-s-slots}{{6.6}{42}{Settable Slots in Tasty\relax }{figure.6.6}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {7}Working with Geometry in Gendl}{43}{chapter.7}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chap:workingwithgeometryingendl}{{7}{43}{Working with Geometry in Gendl\relax }{chapter.7}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {8}More Common Lisp for Gendl}{45}{chapter.8}}
\@writefile{toc}{\contentsline {chapter}{\numberline {8}Custom User Interfaces in GenDL}{45}{chapter.8}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chap:morecommonlispforgendl}{{8}{45}{More Common Lisp for Gendl\relax }{chapter.8}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {9}Advanced Gendl}{47}{chapter.9}}
\newlabel{chap:customuserinterfacesingendl}{{8}{45}{Custom User Interfaces in GenDL\relax }{chapter.8}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.1}Package and Environment for Web Development}{45}{section.8.1}}
\newlabel{sec:packageandenvironmentforwebdevelopment}{{8.1}{45}{Package and Environment for Web Development\relax }{section.8.1}{}}
\@writefile{toc}{\contentsline {section}{\numberline {8.2}Traditional Web Pages and Applications}{45}{section.8.2}}
\newlabel{sec:traditionalwebpagesandapplications}{{8.2}{45}{Traditional Web Pages and Applications\relax }{section.8.2}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.1}{\ignorespaces Simple Static Page Example}}{46}{figure.8.1}}
\newlabel{fig:gwl-1}{{8.1}{46}{Simple Static Page Example\relax }{figure.8.1}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.2}{\ignorespaces Simple Static Page Example}}{46}{figure.8.2}}
\newlabel{fig:gwl-1-html}{{8.2}{46}{Simple Static Page Example\relax }{figure.8.2}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {8.2.1}A Simple Static Page Example}{46}{subsection.8.2.1}}
\newlabel{subsec:asimplestaticpageexample}{{8.2.1}{46}{A Simple Static Page Example\relax }{subsection.8.2.1}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.3}{\ignorespaces Simple Static Page Example}}{47}{figure.8.3}}
\newlabel{fig:gwl-1-image}{{8.3}{47}{Simple Static Page Example\relax }{figure.8.3}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.4}{\ignorespaces Mixing Static HTML and Dynamic Content}}{48}{figure.8.4}}
\newlabel{fig:gwl-2}{{8.4}{48}{Mixing Static HTML and Dynamic Content\relax }{figure.8.4}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {8.2.2}A Simple Dynamic Page which Mixes HTML and Common Lisp/GenDL}{48}{subsection.8.2.2}}
\newlabel{subsec:asimpledynamicpagewhichmixeshtmlandcommonlisp/gendl}{{8.2.2}{48}{A Simple Dynamic Page which Mixes HTML and Common Lisp/GenDL\relax }{subsection.8.2.2}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.5}{\ignorespaces Mixing Static HTML and Dynamic Content}}{49}{figure.8.5}}
\newlabel{fig:gwl-2-image}{{8.5}{49}{Mixing Static HTML and Dynamic Content\relax }{figure.8.5}{}}
\@writefile{toc}{\contentsline {subsection}{\numberline {8.2.3}Linking to Multiple Pages}{49}{subsection.8.2.3}}
\newlabel{subsec:linkingtomultiplepages}{{8.2.3}{49}{Linking to Multiple Pages\relax }{subsection.8.2.3}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.6}{\ignorespaces Linking to Multiple Pages}}{50}{figure.8.6}}
\newlabel{fig:gwl-3}{{8.6}{50}{Linking to Multiple Pages\relax }{figure.8.6}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.7}{\ignorespaces Linking to Multiple Pages}}{50}{figure.8.7}}
\newlabel{fig:gwl-3a}{{8.7}{50}{Linking to Multiple Pages\relax }{figure.8.7}{}}
\@writefile{lof}{\contentsline {figure}{\numberline {8.8}{\ignorespaces Linking to Multiple Pages}}{51}{figure.8.8}}
\newlabel{fig:gwl-3-image}{{8.8}{51}{Linking to Multiple Pages\relax }{figure.8.8}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {9}More Common Lisp for Gendl}{53}{chapter.9}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chap:advancedgendl}{{9}{47}{Advanced Gendl\relax }{chapter.9}{}}
\newlabel{chap:upgradenotes}{{9}{49}{Upgrade Notes\relax }{chapter*.9}{}}
\newlabel{chap:morecommonlispforgendl}{{9}{53}{More Common Lisp for Gendl\relax }{chapter.9}{}}
\@writefile{toc}{\contentsline {chapter}{\numberline {10}Advanced Gendl}{55}{chapter.10}}
\@writefile{lof}{\addvspace {10\p@ }}
\@writefile{lot}{\addvspace {10\p@ }}
\newlabel{chap:advancedgendl}{{10}{55}{Advanced Gendl\relax }{chapter.10}{}}
\newlabel{chap:upgradenotes}{{10}{57}{Upgrade Notes\relax }{chapter*.9}{}}
This is makeindex, version 2.15 [TeX Live 2012] (kpathsea + Thai support).
This is makeindex, version 2.15 [TeX Live 2011] (kpathsea + Thai support).
Scanning input file tutorial.idx....done (37 entries accepted, 0 rejected).
Sorting entries....done (208 comparisons).
Generating output file tutorial.ind....done (81 lines written, 0 warnings).
......
This diff is collapsed.
......@@ -52,5 +52,11 @@
\BOOKMARK [1][-]{subsection.6.0.1}{The Toolbars}{chapter.6}% 52
\BOOKMARK [2][-]{subsection.6.0.2}{View Frames}{subsection.6.0.1}% 53
\BOOKMARK [0][-]{chapter.7}{Working with Geometry in Gendl}{}% 54
\BOOKMARK [0][-]{chapter.8}{More Common Lisp for Gendl}{}% 55
\BOOKMARK [0][-]{chapter.9}{Advanced Gendl}{}% 56
\BOOKMARK [0][-]{chapter.8}{Custom User Interfaces in GenDL}{}% 55
\BOOKMARK [1][-]{section.8.1}{Package and Environment for Web Development}{chapter.8}% 56
\BOOKMARK [1][-]{section.8.2}{Traditional Web Pages and Applications}{chapter.8}% 57
\BOOKMARK [2][-]{subsection.8.2.1}{A Simple Static Page Example}{section.8.2}% 58
\BOOKMARK [2][-]{subsection.8.2.2}{A Simple Dynamic Page which Mixes HTML and Common Lisp/GenDL}{section.8.2}% 59
\BOOKMARK [2][-]{subsection.8.2.3}{Linking to Multiple Pages}{section.8.2}% 60
\BOOKMARK [0][-]{chapter.9}{More Common Lisp for Gendl}{}% 61
\BOOKMARK [0][-]{chapter.10}{Advanced Gendl}{}% 62
......@@ -2277,25 +2277,31 @@ desired, either programmatically from the command-line, in an end-user
application, or from the Tasty environment.
\begin{figure}
\begin{center}
\includegraphics[width=4in,height=3in]{../images/tasty-inspector.png}
\end{center}
\caption{Tasty Inspector}
@sp 1
@center @image{images/tasty-inspector,,3.2in}
@center Figure 9: Tasty inspector.
@sp 1
\label{fig:tasty-inspector}
\end{figure}
\begin{figure}
\begin{center}
\includegraphics[width=4in,height=3in]{../images/tasty-s-slots.png}
\end{center}
\caption{Settable Slots in Tasty}
@center @image{images/tasty-s-slots,,3.2in}
@center Figure 10: Tasty settable slots.
@sp 1
\label{fig:tasty-s-slots}
\end{figure}
To modify the value in Tasty: select ``Inspect'' mode from the Tree
menu, then select the root of the @b{assembly} tree to set the
inspector on that object (see Figure
menu, then select the root of the \texttt{assembly} tree to set the inspector on that object (see Figure
\ref{fig:tasty-inspector}). Once the inspector is displaying this object, it is
possible to expand its settable slots by clicking on the ``Show
Settables!'' link. (use the ``X'' link to collapse the settable slots
......@@ -2312,6 +2318,493 @@ button (see Figure
\chapter{Custom User Interfaces in GenDL}
\label{chap:customuserinterfacesingendl}
One of the strengths of GenDL is the ability to create custom
web-based user interfaces. GenDL contains a built-in web server and
supports the creation of generative \emph{web-based} user interfaces\footnote{GenDL does not contain support for native desktop
GUI applications. Although the host Common Lisp
environment (e.g. Allegro CL or LispWorks) may contain a GUI builder
and Integrated Development Environment, and you are free to use these,
GenDL does not provide specific support for them.}. Using the same \texttt{define-object} syntax which you have already learned, you can define web
pages, sections of web pages, and \emph{form control} elements such as type-in fields, checkboxes, and choice
lists. Using this capability does require a basic working knowledge of
the HTML language\footnote{We will not cover HTML in this manual, but
plentiful resources are available online and in print.}.
Any web extensions such as custom JavaScript and JavaScript libraries
can also be used, as with any standard web application.
With the primitive objects and functions in its \texttt{:gwl} package, GenDL supports both the traditional ``Web 1.0''
interfaces (with fillout forms, page submittal, and complete page
refresh) as well as so-called ``Web 2.0'' interaction with AJAX.
\section{Package and Environment for Web Development}
\label{sec:packageandenvironmentforwebdevelopment}
Similarly to @b{gdl:define-package}, you can use
@b{gwl:define-package} in order to create a working package which has
access to the symbols you will need for building a web application (in
addition to all the other GenDL symbols).
The @b{:gwl-user} package is pre-defined and may be used for practice
work. For real projects, you should define your own package using
@b{gwl:define-package}.
The acronym ``GWL'' stands for Generative Web Language, which is not
actually a separate language from GenDL itself, but rather a set of
primitive objects and functions available with GenDL for building web
applications. The YADD reference documentation for package
``Generative Web Language'' provides detailed specifications for all
the primitive objects and functions.
\section{Traditional Web Pages and Applications}
\label{sec:traditionalwebpagesandapplications}
To make a GenDL object presentable as a web page, the following two
steps are needed:
\begin{enumerate}
\item Mix \texttt{base-html-sheet} into the object definition.
\item define a GenDL function called \texttt{main-sheet} within the object definition.
\end{enumerate}
The \texttt{main-sheet} function should return valid
HTML for the page. The easiest way to produce HTML is with the use of
an HTML generating library, such as \href{http://weitz.de/cl-who}{CL-WHO} or \href{http://www.franz.com/support/documentation/current/doc/aserve/htmlgen.html}{HTMLGen}, both of which are built into GenDL.
For our examples we will use cl-who, which is currently the
standard default HTML generating library used internally by
GenDL. Here we will make note of the major features of cl-who while
introducing the examples; for complete documentation on cl-who, please
visit the page at Edi Weitz' website listed above.
\subsection{A Simple Static Page Example}
\label{subsec:asimplestaticpageexample}
In Figure
\ref{fig:gwl-1}, GWL convenience macro \texttt{with-cl-who} is used; this sets up a standard default environment for outputting HTML
within a GWL application.
\begin{figure}
\begin{lrbox}{\boxedverb}
\begin{minipage}{\linewidth}
\tiny{
\begin{verbatim}(in-package :gwl-user)
(define-object president (base-html-sheet)
:input-slots
((name "Carter") (term 1976) (table-border 1))
:functions
((write-html-sheet
() (with-cl-who (:indent t)
(:html (:head (:title (fmt "Info on President: ~a"
(the name))))
(:body ((:table :border (the table-border))
(:tr (:th "Name") (:th "Term"))
(:tr (:td (str (the name)))
(:td (str (the term)))))))))))
;;
;; Access the above example with
;; http://localhost:9000/make?object=gwl-user::president
;;
\end{verbatim}}
\end{minipage}
\end{lrbox}
\fbox{\usebox{\boxedverb}}
\caption{Simple Static Page Example}
\label{fig:gwl-1}
\end{figure}
The code in Figure
\ref{fig:gwl-1} produces HTML output as shown in Figure
\ref{fig:gwl-1-html} which looks similar to Figure
\ref{fig:gwl-1-image} in a web browser.
\begin{figure}
\begin{lrbox}{\boxedverb}
\begin{minipage}{\linewidth}
\tiny{
\begin{verbatim}
<html>
<head>
<title>Info on President: Carter
</title>
</head>
<body>
<table border="1">
<tr> <th>Name</th>
<th>Term</th>
</tr>
<tr> <td>Carter</td>
<td>1976</td>
</tr>
</table>
</body></html>
\end{verbatim}}
\end{minipage}
\end{lrbox}
\fbox{\usebox{\boxedverb}}
\caption{Simple Static Page Example}
\label{fig:gwl-1-html}
\end{figure}
\begin{figure}
\begin{center}
\includegraphics[width=4in,height=3in]{../images/gwl-1.png}
\end{center}
\caption{Simple Static Page Example}
\label{fig:gwl-1-image}
\end{figure}
Several important concepts are packed into this example. Note the following:
\begin{itemize}
\item Our convenience macro \texttt{with-cl-who} is used to wrap the native \texttt{with-html-output} macro which comes with the cl-who library.
\item We use the keyword argument \texttt{:indent t} in order to pretty-print the generated HTML. This does
not affect the browser display but can make the generated HTML
easier to read and debug. This option should be left as nil (the
default) for production deployments.
\item The \texttt{fmt} symbol has special meaning
within the cl-who environment and works the same as a Common
Lisp \texttt{format nil}in order to evaluate a format
string together with matching arguments, and produce a string at
runtime.
\item The \texttt{str} symbol has special meaning
within the cl-who environment and works by evaluating an
expression at runtime to return a string or other printable
object, which is then included at that point in the HTML output.
\item Expressions within the \texttt{body} of an
HTML tag have to be evaluated, usually by use of the \texttt{fmt} or \texttt{str} in cl-who. There are three examples of this in the
above sample: one \texttt{fmt} and two \texttt{str}.
\item Expressions within a \emph{tag attribute} are always evaluated automatically, and so do
\textbf{not} require a \texttt{str} or other special symbol to force evaluation at
runtime. Tag attributes in HTML (or XML) are represented as a
plist spliced in after a tag name, wrapped in extra parentheses
around the tag name. In the sample above, the \texttt{:border (the table-border)} is an example of a tag attribute on the \texttt{:table} tag. Notice that the expression \texttt{(the table-border)} does not need \texttt{str} in order to be evaluated - it gets evaluated automatically.
\item In cl-who, if a tag attribute evaluates to \texttt{nil}, then that tag attribute will be left out of the output
completely. For example if \texttt{(the table-border)} evaluates to nil, then the \texttt{:table} tag will be outputted without any attributes at
all. This is a convenient way to conditionalize tag
attributes.
\item The URL \texttt{http://localhost:9000/make?object=gwl-user::president} is published automatically based on the package and
name of the object definition. When you visit this URL, the
response is redirected to a unique URL identified by
a \emph{session ID}. This ensures that each user to your
application site will see their own specific instance of the
page object. The session ID is constructed from a combination of
the current date and time, along with a pseudo-random
number.
\end{itemize}
\subsection{A Simple Dynamic Page which Mixes HTML and Common Lisp/GenDL}
\label{subsec:asimpledynamicpagewhichmixeshtmlandcommonlisp/gendl}
Within the cl-who environment, it is possible to include any standard
Common Lisp structures such as \texttt{let}, \texttt{dolist} , \texttt{dotimes}, etc, which accept a \emph{body} of code. The requirement is that any internal code body
must be wrapped in a list beginning with the special symbol \texttt{htm}, which has meaning to cl-who.
\begin{figure}
\begin{lrbox}{\boxedverb}
\begin{minipage}{\linewidth}
\tiny{
\begin{verbatim}(in-package :gwl-user)
(define-object presidents (base-html-sheet)
:input-slots
((presidents (list (list :name "Ford"
:term 1974)
(list :name "Carter"
:term 1976)
(list :name "Clinton"
:term 1992)
(list :name "Bush"
:term 2000)
(list :name "Obama"
:term 2008)))
(table-border 1))
:functions
((write-html-sheet
()
(with-cl-who (:indent t)
(let ((title (format nil "Info on ~a Presidents:"
(length (the presidents)))))
(htm
(:html
(:head (:title (str title)))
(:body
(:p (:c (:h3 (str title))))
((:table :border (the table-border))
(:tr (:th "Name") (:th "Term"))
(dolist (president (the presidents))
(htm
(:tr (:td (str (getf president :name)))
(:td (str (getf president :term)))))))))))))))
;;
;; Access the above example with
;; http://localhost:9000/make?object=gwl-user::presidents
;;
\end{verbatim}}
\end{minipage}
\end{lrbox}
\fbox{\usebox{\boxedverb}}
\caption{Mixing Static HTML and Dynamic Content}
\label{fig:gwl-2}
\end{figure}
\begin{figure}
\begin{center}
\includegraphics[width=4in,height=3in]{../images/gwl-2.png}
\end{center}
\caption{Mixing Static HTML and Dynamic Content}
\label{fig:gwl-2-image}
\end{figure}
The example in Figure
\ref{fig:gwl-2} uses this technique to output an HTML table row for each ``row'' of data in a list of lists.
The output looks similar to Figure
\ref{fig:gwl-2-image} in a web browser.
Note the following from this example:
\begin{itemize}
\item \texttt{title} is a \texttt{let} variable, so we use \texttt{(str title)} to evaluate it as a string. We do not use \texttt{(str (the title))} because \texttt{title} is a local variable and not a message (i.e. slot) in the object.
\item Inside the \texttt{dolist}, we ``drop back into'' HTML mode using the \texttt{htm} operator.
\end{itemize}
\subsection{Linking to Multiple Pages}
\label{subsec:linkingtomultiplepages}
The base-html-sheet mixin provides a \texttt{self-link} message for the purpose of generating a hyperlink to that
page. Typically you will have a ``parent'' page object which links to