diff -r ead1b2f93a16 news.fig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/news.fig Sat Mar 07 19:40:36 2009 +0100 @@ -0,0 +1,66 @@ +#FIG 3.2 Produced by xfig version 3.2.5 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 630 450 810 630 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 630 450 810 450 810 630 630 630 630 450 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 630 450 810 450 810 630 630 630 630 450 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 675 585 765 495 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 675 495 765 585 +-6 +6 900 450 3330 630 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 900 450 3330 450 3330 630 900 630 900 450 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 900 450 3330 450 3330 630 900 630 900 450 +4 1 0 50 -1 0 9 0.0000 4 135 840 2115 585 News history\001 +-6 +6 3420 450 3600 630 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 3420 450 3600 450 3600 630 3420 630 3420 450 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3420 450 3600 450 3600 630 3420 630 3420 450 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3465 585 3510 540 +2 1 0 6 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3510 540 3555 495 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3465 495 3555 585 +-6 +6 3420 720 3600 1890 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 3420 720 3600 720 3600 1890 3420 1890 3420 720 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3600 720 3420 720 3420 1890 3600 1890 3600 720 +2 3 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3465 810 3555 810 3510 765 3465 810 +2 3 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3465 1800 3555 1800 3510 1845 3465 1800 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3420 855 3600 855 +2 2 0 1 0 7 51 -1 10 0.000 0 0 -1 0 0 5 + 3420 1485 3600 1485 3600 1755 3420 1755 3420 1485 +-6 +6 3420 1980 3600 2160 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 3420 1980 3600 1980 3600 2160 3420 2160 3420 1980 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3420 1980 3600 1980 3600 2160 3420 2160 3420 1980 +2 3 0 0 0 7 51 -1 10 0.000 1 0 -1 0 0 4 + 3420 2160 3600 1980 3600 2160 3420 2160 +-6 +6 630 720 3330 2160 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 630 720 3330 720 3330 2160 630 2160 630 720 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 630 720 3330 720 3330 2160 630 2160 630 720 +-6 diff -r ead1b2f93a16 news.pdf Binary file news.pdf has changed diff -r ead1b2f93a16 news2.fig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/news2.fig Sat Mar 07 19:40:36 2009 +0100 @@ -0,0 +1,74 @@ +#FIG 3.2 Produced by xfig version 3.2.5 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 630 720 3330 2115 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 630 720 3330 720 3330 2115 630 2115 630 720 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 630 720 3330 720 3330 2115 630 2115 630 720 +-6 +6 3465 720 3645 1890 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 3465 720 3645 720 3645 1890 3465 1890 3465 720 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3645 720 3465 720 3465 1890 3645 1890 3645 720 +2 3 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3510 810 3600 810 3555 765 3510 810 +2 3 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 3510 1800 3600 1800 3555 1845 3510 1800 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3465 855 3645 855 +2 2 0 1 0 7 51 -1 10 0.000 0 0 -1 0 0 5 + 3465 1485 3645 1485 3645 1755 3465 1755 3465 1485 +-6 +6 3465 1935 3645 2115 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 3465 1935 3645 1935 3645 2115 3465 2115 3465 1935 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3465 1935 3645 1935 3645 2115 3465 2115 3465 1935 +2 3 0 0 0 7 51 -1 10 0.000 1 0 -1 0 0 4 + 3465 2115 3645 1935 3645 2115 3465 2115 +-6 +6 900 270 3330 450 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 900 270 3330 270 3330 450 900 450 900 270 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 900 270 3330 270 3330 450 900 450 900 270 +4 1 0 50 -1 0 9 0.0000 4 135 840 2115 405 News history\001 +-6 +6 630 270 810 450 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 630 270 810 270 810 450 630 450 630 270 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 630 270 810 270 810 450 630 450 630 270 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 675 405 765 315 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 675 315 765 405 +-6 +6 3465 270 3645 450 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 3465 270 3645 270 3645 450 3465 450 3465 270 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 3465 270 3645 270 3645 450 3465 450 3465 270 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3510 405 3555 360 +2 1 0 6 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3555 360 3600 315 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 3510 315 3600 405 +-6 +2 2 0 1 0 7 65 -1 4 0.000 0 0 -1 0 0 5 + 3780 585 540 585 540 2250 3780 2250 3780 585 +2 2 0 1 0 7 60 -1 16 0.000 0 0 -1 0 0 5 + 3420 675 3690 675 3690 2160 3420 2160 3420 675 +2 2 0 1 0 7 60 -1 4 0.000 0 0 -1 0 0 5 + 585 225 3735 225 3735 495 585 495 585 225 +2 2 0 1 0 7 70 -1 16 0.000 0 0 -1 0 0 5 + 450 135 3870 135 3870 2340 450 2340 450 135 diff -r ead1b2f93a16 news2.pdf Binary file news2.pdf has changed diff -r ead1b2f93a16 news_tree.fig --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/news_tree.fig Sat Mar 07 19:40:36 2009 +0100 @@ -0,0 +1,128 @@ +#FIG 3.2 Produced by xfig version 3.2.5 +Landscape +Center +Metric +Letter +100.00 +Single +-2 +1200 2 +6 4140 720 4320 1890 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 4140 720 4320 720 4320 1890 4140 1890 4140 720 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 4320 720 4140 720 4140 1890 4320 1890 4320 720 +2 3 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 4185 810 4275 810 4230 765 4185 810 +2 3 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 4 + 4185 1800 4275 1800 4230 1845 4185 1800 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4140 855 4320 855 +2 2 0 1 0 7 51 -1 10 0.000 0 0 -1 0 0 5 + 4140 1485 4320 1485 4320 1755 4140 1755 4140 1485 +-6 +6 4140 1980 4320 2160 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 4140 1980 4320 1980 4320 2160 4140 2160 4140 1980 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 4140 1980 4320 1980 4320 2160 4140 2160 4140 1980 +2 3 0 0 0 7 51 -1 10 0.000 1 0 -1 0 0 4 + 4140 2160 4320 1980 4320 2160 4140 2160 +-6 +6 3600 990 3870 1980 +2 2 0 1 0 7 50 -1 16 0.000 0 0 -1 0 0 5 + 3600 990 3870 990 3870 1980 3600 1980 3600 990 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 3645 1755 3825 1755 3825 1935 3645 1935 3645 1755 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 3645 1035 3825 1035 3825 1710 3645 1710 3645 1035 +-6 +6 2115 1215 3105 1485 +2 2 0 1 0 7 50 -1 4 0.000 0 0 -1 0 0 5 + 2115 1485 3105 1485 3105 1215 2115 1215 2115 1485 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 2880 1260 3060 1260 3060 1440 2880 1440 2880 1260 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 2160 1260 2835 1260 2835 1440 2160 1440 2160 1260 +-6 +6 2070 1800 3465 2430 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 2070 1800 3465 1800 3465 2430 2070 2430 2070 1800 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 2070 1800 3465 1800 3465 2430 2070 2430 2070 1800 +-6 +6 4050 270 4230 450 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 4050 270 4230 270 4230 450 4050 450 4050 270 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 4050 270 4230 270 4230 450 4050 450 4050 270 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4095 405 4140 360 +2 1 0 6 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4140 360 4185 315 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 4095 315 4185 405 +-6 +6 1980 270 2160 450 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 1980 270 2160 270 2160 450 1980 450 1980 270 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 1980 270 2160 270 2160 450 1980 450 1980 270 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2025 405 2115 315 +2 1 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 2 + 2025 315 2115 405 +-6 +6 2475 675 3465 945 +2 2 0 1 0 7 50 -1 4 0.000 0 0 -1 0 0 5 + 2475 945 3465 945 3465 675 2475 675 2475 945 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 2520 720 2700 720 2700 900 2520 900 2520 720 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 2745 720 3240 720 3240 900 2745 900 2745 720 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 3285 720 3420 720 3420 900 3285 900 3285 720 +-6 +6 1530 540 1800 1530 +2 2 0 1 0 7 50 -1 16 0.000 0 0 -1 0 0 5 + 1530 540 1800 540 1800 1530 1530 1530 1530 540 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 1575 585 1755 585 1755 765 1575 765 1575 585 +2 2 0 1 0 7 45 -1 20 0.000 0 0 -1 0 0 5 + 1575 855 1755 855 1755 1485 1575 1485 1575 855 +-6 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2520 1350 2745 1800 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2970 1350 3600 1485 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3735 1395 4140 1215 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3735 1845 4140 2025 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2610 810 2070 450 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 2970 810 3015 450 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 3375 810 4095 450 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1665 1170 2115 1395 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1665 675 2475 855 +2 2 0 1 0 7 50 -1 -1 0.000 0 0 -1 0 0 5 + 2250 270 3960 270 3960 450 2250 450 2250 270 +2 1 0 1 0 7 40 -1 -1 0.000 0 0 -1 1 0 2 + 1 1 1.00 60.00 120.00 + 1080 405 1530 720 +2 2 0 0 0 7 55 -1 20 0.000 0 0 -1 0 0 5 + 2250 270 3960 270 3960 450 2250 450 2250 270 +4 1 0 50 -1 0 9 0.0000 4 135 840 3060 405 News history\001 diff -r ead1b2f93a16 news_tree.pdf Binary file news_tree.pdf has changed diff -r ead1b2f93a16 nwidgets.tex --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/nwidgets.tex Sat Mar 07 19:40:36 2009 +0100 @@ -0,0 +1,507 @@ +\documentclass{article} +\usepackage[a4paper]{geometry} +\usepackage{graphics} + +\author{A.T.~Hofkamp} +\title{Nested widgets in parts} + +\begin{document} +\maketitle +\tableofcontents + +\section{Introduction}\label{sec:intro} +In the current implementation, a GUI{} window is contructed by means of a +widget array containing the data fields for all widgets of the window. +These data fields include fixed positions of the edges of each widget relative +to the origin of the window. + +The following points for possible improvement have been recognized: +\begin{itemize} +\item Modifying the size of one widget also means that other + widgets have to be re-positioned. This usually involves a lot of + recalculating widget edge positions. +\item The sizes of the widgets should be more flexible. The program supports + many different languages, and not all languages need the same amount of + space in each widget. +\end{itemize} + +In this document, \textit{nested widgets} are proposed as a approach to combat +these points. + + +\section{Nested widgets} +To overcome the weak points of the current static widget implementation, we may +want to switch to using nested widgets. + +Nested widgets bring a hierarchy of widgets (a tree of widgets). At the leafs, +there are the \textit{user widgets} (buttons, labels, etc). These widgets +know their own position and (minimal) size, and know how to react to resizing +requests\footnote{Further extensions are possible, for example rendering +to the screen.}. +To keep the user widgets together, \textit{structural widgets} are used. +These are at the non-leaf nodes in the tree. They manage the size and position +of their child widgets, and ultimately at the root of the hierarchy, the +window as a whole. + +In the OpenTTD{} nested widgets, the two main structural widgets are the +\textit{horizontal container widget} and the \textit{vertical container +widget}.\footnote{Much like the HBox and VBox classes in the GTK{} GUI{} +toolkit, or the QHBoxLayout and QVBoxLayout classes in Qt.} The horizontal +container widget puts its child widgets after each other from left to +right\footnote{And for countries that use right-to-left languages, from right +to left.}. The vertical container puts its child widgets underneath each +other. + +To demonstrate the idea, have a look at Figure~\ref{fig:news}. +% +\begin{figure} +\begin{minipage}{.49\linewidth} +\begin{center} +\includegraphics{news.pdf} +\caption{Widgets of the \textit{news history} window.} +\label{fig:news} +\end{center} +\end{minipage} +\hfill +\begin{minipage}{.49\linewidth} +\begin{center} +\includegraphics{news2.pdf} +\caption{Nested widgets version of the \textit{news history} window.} +\label{fig:news2} +\end{center} +\end{minipage} +\end{figure} +% +It shows the widgets used to create the \textit{news history} window. For +clarity, some space is put between the widgets. In Figure~\ref{fig:news2}, +structural widgets have been added. The three widgets of the title bar have +been put in a horizontal container widget (dark gray area). The vertical +scrollbar and the resize button have been put together in a vertical +container widget (light gray area). The canvas for the messages and the +vertical container holding the scrollbar and resize button are then put in +another horizontal container. Finally both horizontal containers are put in +the root vertical container widget. + +Note that in reality, there is no room between the container edge and its +contents, so wrapping container widgets around some other widgets does not +make the window bigger. + +In terms of C{++} objects, the tree of widgets is clearly visible. +% +\begin{figure} +\begin{center} +\includegraphics{news_tree.pdf} +\caption{Internal nested widgets data structures.} +\label{fig:newstree} +\end{center} +\end{figure} +% +Figure~\ref{fig:newstree} gives an impression. + +\medskip +Using nested widgets addresses the points raised in Section~\ref{sec:intro}, +and has some additional advantages: +\begin{itemize} +\item Since each user widget knows its own size, changing its size is a local + modification. The structural widgets will shuffle all the other widgets. +\item The same mechanism can be used to adapt the widget sizes opitmally for + each language. Overflow of the text will not happen any more. +\item The widget tree computes the minimal size of the window, making the + hard-coded values in the WindowDesc class obsolete. +\item The widget tree computes the resize steps of the window. + (Each user widget knows how to react to resizing. The structural widgets + collect that information and propagate it upwards to the root.) +\end{itemize} + +The current aim of the patch is to introduce nested widgets, and to generate +the widget array. +The nested widgets are however much more powerful, and can be +extended to a more powerful replacement of the current widget implementation. + +\medskip +The technical details of constructing a nested widget tree can be read in +Appendix~\ref{sec:nestedwidget:technicaldetails}. Basically, what you need to +do is to construct the whole tree bottom up by instantiating each widget and +putting them in containers, putting those containers other containers, etc +until the root of the nested widget tree is reached. +At that point, you can initalize the whole tree with just two method calls, +and generate the filled widget array with a third call into the nested widget +tree. + +\section{Nested widget parts} +Doing that by hand results in a lot of code that is not very nice to read and +change. To solve this problem, another data structure has been made, the +\textit{nested widget parts} structure. +It allows you to define the nested widget tree structure by listing all +widgets in the same nested structure. Together with proper indentation, it +looks like a program fragment. An example: +\begin{verbatim} +static const NWidgetPart _nested_select_game_widgets[] = { + NWidget(WWT_CAPTION, COLOUR_BROWN, 0), + SetMinimalSize(336, 14), SetDataTip(STR_0307_OPENTTD), + NWidget(WWT_PANEL, COLOUR_BROWN, 1), + + NWidget(NWID_SPACER), SetMinimalSize(0, 8), + + /* 'generate game' and 'load game' buttons */ + NWidget(NWID_HORIZONTAL), + NWidget(NWID_SPACER), SetMinimalSize(10, 0), + NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, SGI_GENERATE_GAME), + SetMinimalSize(158, 12), + SetDataTip(STR_0140_NEW_GAME, STR_02FB_START_A_NEW_GAME), + NWidget(WWT_PUSHTXTBTN, COLOUR_ORANGE, SGI_LOAD_GAME), + SetMinimalSize(158, 12), + SetDataTip(STR_0141_LOAD_GAME, STR_02FC_LOAD_A_SAVED_GAME), + NWidget(NWID_SPACER), SetMinimalSize(10, 0), + EndContainer(), + + NWidget(NWID_SPACER), SetMinimalSize(0, 6), + + .... // Other lines with buttons deleted to increase clarity. + + EndContainer(), +}; +\end{verbatim} +This fragment defines the top-part of the window at the ntro screen (the +caption and the first row of buttons). + +The whole definition is an array of \texttt{NWidgetPart} structures. The root +is a vertical container widget. A new widget starts at a \texttt{NWidget} +call. Behind it, additional settings for the widget can be done. For user +widgets only settings like \texttt{SetMinimalSize()} or \texttt{SetDataTip()} +are useful. For background (\textsc{WWT\_PANEL}, \textsc{WWT\_FRAME}, and +\textsc{WWT\_INSET} widgets) and container widgets (\textsc{NWID\_HORIZONTAL} +and \textsc{NWID\_VERTICAL}) collect all widgets following until they +encounter a \texttt{EndContainer()}. +See Appendix~\ref{sec:nestedwidgetpart:technicaldetails} for the technical +details of what is possible. + + +\section{Integration of nested widgets with the current implementation} +In the current implementation, the widget array is a central data structure, +and cannot be replaced by something else easily. + +For this reason the aim of this patch is only introduction of the nested +widget data structure for describing GUI{} windows. +The WindowDesc data structure has been extended to allow nested widget parts +as window specification. If it contains both the current widget array and the +nested widget parts, the latter is converted to another widget array, and both +arrays are compared with each other. +If the original widget array is not given and nested widget parts are +specified, the latter is used as window specification. + + +\newpage +\appendix + +\section{Technical details of making nested widget trees}% +\label{sec:nestedwidget:technicaldetails} + +\subsection{User widgets} +User widgets are created with the \texttt{NLeafWidget} class, as in +\begin{verbatim} + NWidgetLeaf *nwid = new NWidgetLeaf(type, colour, index, data, tip); + nwid->SetMinimalSize(minx, miny); // optional + nwid->SetFill(fillx, filly); // optional + nwid->SetResize(stepx, stepy); // optional +\end{verbatim} +The widget is created by instantiating the \texttt{NLeafWidget} class. The +\texttt{type} parameter defines what widget to create. Depending on the type, +there are default values for the sizing settings listed in +Figure~\ref{fig:nleafwidgetsettings}. The \texttt{data} and \texttt{tooltip} +defaults are \texttt{0x0} and \textsc{\texttt{STR\_NULL}} respectively. +% +\begin{figure} +\begin{center} +\begin{tabular}{|l|c|c|c|} \hline +\textbf{NLeafWidget} & \textbf{Mininal} & & \textbf{Resize} \\ +\textbf{type} & \textbf{size} & \textbf{Filling} & \textbf{step} \\ +\hline +\textsc{WWT\_PUSHBTN} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_IMGBTN} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_PUSHIMGBTN} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_IMGBTN\_2} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_TEXTBTN} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_PUSHTXTBTN} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_TEXTBTN\_2} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_LABEL} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_TEXT} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_MATRIX} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_EDITBOX} & (0, 0) & (false, false) & (0, 0) \\ +\textsc{WWT\_SCROLLBAR} & (12, 0) & (false, true) & (0, 1) \\ +\textsc{WWT\_SCROLL2BAR} & (12, 0) & (false, true) & (0, 1) \\ +\textsc{WWT\_HSCROLLBAR} & (0, 12) & (true, false) & (1, 0) \\ +\textsc{WWT\_CAPTION} & (0, 14) & (true, false) & (1, 0) \\ +\textsc{WWT\_STICKYBOX} & (12, 14) & (false, false) & (0, 0) \\ +\textsc{WWT\_RESIZEBOX} & (12, 12) & (false, false) & (0, 0) \\ +\textsc{WWT\_CLOSEBOX} & (11, 14) & (false, false) & (0, 0) \\ +\textsc{WWT\_DROPDOWN} & (0, 12) & (false, false) & (0, 0) \\ +\textsc{WWT\_DROPDOWNIN} & (0, 12) & (false, false) & (0, 0) \\ \hline +\end{tabular} +\end{center} +\caption{Default sizing settings for each type of \texttt{NLeafWidget} object.} +\label{fig:nleafwidgetsettings} +\end{figure} +% +The \texttt{colour} parameter defines the colour of the widget, and +\texttt{index} sets at what position the widget should be placed in the widget +array. +The \texttt{data} and \texttt{tip} parameters define the values for the +\textsf{Widget::data} and the \textsf{Widget::tooltips} fields. + +If the default sizing settings are not correct, they can be modified by +calling \texttt{SetMinimalSize()} for chaning the minimal size of the widget, +\texttt{SetFill()} for changing how the widget is extended during filling, and +\texttt{SetResize()} for modifying the resize step of the widget. + +\subsection{Container widgets} +The container widgets are the structural nested widgets. They do not have size +and resize properties of their own, but instead derive them from their +child widgets. +The simplest container widget is the vertical container widget. It puts its +child widgets underneath each other. +Instantiating a vertical container widget is done like +\begin{verbatim} + nwid = new NWidgetVertical(); + + // Add child widgets by calls like + nwid->Add(child_widget); +\end{verbatim} +The container widget is never stored in the widget array, and thus has no +parameters or methods for them. +After creation, adding a child widget to the container is done with the +\texttt{Add()} method. The first added child widget is put at the top, each +next added child widget is put below the previously added one. + +The size and resize properties of the container are derived from its child +widgets in the following way: +\begin{itemize} +\item Its horizontal size is the biggest horizontal size of one of its child + widgets. Smaller child widgets that allow horizontal fill are expanded in + horizontal direction. Smaller child widgets that cannot be horizontally + filled are centered. +\item Its vertical size is the sum of the vertical sizes of all its child + widgets. +\item It can fill in horizontal direction if all child widgets can do + horizontal fill. +\item It can fill in vertical direction if at least one child widget can do + vertical fill. +\item The horizontal resize step is non-zero only if the horizontal resize + step of all its child widgets are non-zero. Its step size if the smallest + common multiple of all its child widget horizontal resize steps. +\item The vertical resize step is 0 if none of its child widgets can resize + verrtically. Otherwise, it is the resize step of the first vertically + resizable child widget. All other child widgets are assumed not to be + vertically resizable.\footnote{What you would want here is that it takes + the smallest non-zero child vertical resize step, and also distribute + resizing evenly over all vertically resizable child widgets. The nested + widget tree can easily be extended to handle that. However it is not + supported by the resize flags in the widget array, thus there is currently + no point in doing this.} +\end{itemize} + +\medskip +The horizontal container (\texttt{NWidgetHorizontal} class) acts just like the +vertical container, except that vertical and horizontal are swapped. Which way +'top' goes depends on the language used. With languages that write from left +to right, the horizontal container \footnote{The direction of stacking is not +a fixed property of the horizontal container widget, but is instead a +parameter of the method that assigns sizes and positions. This allows +switching between both types of languages without difficulties.} starts at the +left and extends to the right. With languages that write from right to left, +the 'top' goes to the right and the widget put each child at the left of the +previous child. + + +\subsection{Background widgets} +The \textsc{WWT\_PANEL}, \textsc{WWT\_INSET}, and \textsc{WWT\_FRAME} widgets +can be used like a normal user widget, or as a widget that functions as a +background of another (container) child widget. + +In the first case, instantiation is something like +\begin{verbatim} + NWidgetBackground *nwid = new NWidgetBackground(type, colour, index, NULL); + nwid->SetMinimalSize(minx, miny); + nwid->SetFill(fillx, filly); // optional + nwid->SetResize(stepx, stepy); // optional +\end{verbatim} +The \texttt{type} parameter must be one of \textsc{WWT\_PANEL}, +\textsc{WWT\_INSET}, or \textsc{WWT\_FRAME}. The \texttt{colour} defines the +colour of the background widget, and the \texttt{index} sets the index of the +widget in the widget array. The default minimal size is (0, 0), the widget +allows filling in both directions, but no resizing. +Usually, you should set its minimal size to a non-zero size by using the +\texttt{SetMinimalSize()} method. If the default filling and resizing are not +wanted, these can be changed with the \texttt{SetFill()} and +\texttt{SetResize()} methods. + +\medskip +For the second case (use as a background widget), the instantiation sequence +is something like +\begin{verbatim} + NWidgetContainer *ncont = new NWidgetVertical(); // Construct a container widget + // Fill the container + NWidgetBackground *nwid = new new NWidgetBackground(type, colour, index, ncont); +\end{verbatim} +or more like a container widget: +\begin{verbatim} + NWidgetBackground *nwid = new new NWidgetBackground(type, colour, index, NULL); + // Make a child widget + nwid->Add(child_widget); +\end{verbatim} +The fourth parameter of the background widget can be used to specify the child +container widget to use. That container widget may be filled before hand, or +afterwards. The \texttt{Add()} method of the background widget is simply +forwarding the new widgets to its child container widget. +If you don't specify a container, a vertical container is created +automatically with the first call to \texttt{Add()}. + + +\subsection{Space widget} +The space widget is a user widget that only takes room, it is never rendered +onto the window. Its purpose is to allow gaps between user widgets (thus +creating groups of widgets), so the user has a better overview of the window +interface structure. +Instantiation is done like +\begin{verbatim} + NWidgetSpacer *nwid = new NWidgetSpacer(sizex, sizey); + nwid->SetMinimalSize(minx, miny); // optional + nwid->SetFill(fillx, filly); // optional + nwid->SetResize(stepx, stepy); // optional +\end{verbatim} +In the instantiation statement, the minimal size of the space is defined. +Normally, either \texttt{sizex} or \texttt{sizey} is 0. In that way, the space +widget only influences one direction which makes understanding the widget +structure easier. +By default, the space widget does not change size. This can be modified +with the same methods as used with the user widgets. + + +\subsection{Initializing a nested widget tree} +After constructing the nested widget tree, it needs to be initialized. +This is done by two method calls: +\begin{verbatim} + bool rtl = false; // We are not using a right-to-left language. + // Construct the entire nested widget tree. + // Assuming 'nwid_root' is the root widget of the window. + int biggest_index = nwid_root->ComputeMinimalSize(); + nwid_root->AssignPosition(0, 0, + nwid_root->min_x, nwid_root->min_y, + (nwid_root->resize_x > 0), (nwid_root->resize_y > 0), + rtl); +\end{verbatim} +The first call (\texttt{ComputeMinimalSize()}) performs a bottom-up traversal +of the widget tree, and pulls minimal size, fill, and resize information from +the user widgets up to the root of the tree. After the call, the +(\texttt{min\_x}, \texttt{min\_y}) pair contains the minimal size of the +window, and the (\texttt{resize\_x}, \texttt{resize\_y}) pair contains the +horizontal and vertical resize step sizes. +The \texttt{AssignPosition()} call pushes the collected information down +again, and makes all data consistent with each other. The fifth \texttt{rtl} +boolean parameter defines whether a right-to-left language is used. +Unfortunately, OpenTTD{} cannot handle the value \texttt{true} for the +\texttt{rtl} parameter at this time. + +The details to generate a widget array from an initialized nested widget tree +is a single \texttt{StoreWidget()} method call. Details on how to do it can be +found in the \texttt{InitializeNWidgets()} function. + + +\section{Technical details of using nested widget parts}% +\label{sec:nestedwidgetpart:technicaldetails} +The nested widget parts build on the nested widgets discussed in +Appendix~\ref{sec:nestedwidget:technicaldetails}. + +The nested widget parts are slightly less expressive than making a nested +widget tree manually. The reason for this is to make using them easier (for +example, the background widgets always use a vertical container for their +child widgets). In general, this should not give any problems. + + +\subsection{Leaf widget parts} +A leaf widget is written in neted widget parts in the following way: +\begin{verbatim} + NWidget(type, colour, index), + SetMinimalSize(minx, miny), + SetFill(fillx, filly), + SetResize(stepx, stepy), + SetDataTip(data, tip), +\end{verbatim} +The meaning of the parameters is the same as with the nested widgets. The +order of the settings of the second line and further is not relevant, but for +consistency, the above order is recommended. + +If the default values of a \texttt{NLeafWidget} are good, you can omit +explicitly setting the value. + +\subsection{Container widget parts} +Creating a container with all its child widgets is done with a declaration +like +\begin{verbatim} + NWidget(NWID_HORIZONTAL), // Use NWID_VERTICAL for vertical containers + ... // Put child widgets here + EndContainer(), +\end{verbatim} + +\subsection{Background widget parts} +As in the nested widgets, the nested widget parts also allow two forms of +background widgets, on the one hand as a user widget for rendering content, +and on the other hand as a background widget for its child. + +A background widget for rendering own content is created with +\begin{verbatim} + NWidget(type, colour, index), + SetMinimalSize(minx, miny), + SetFill(fillx, filly), + SetResize(stepx, stepy), + SetDataTip(data, tip), + EndContainer(), +\end{verbatim} +You can define the same fields as for a leaf widget. The \texttt{type} +parameter must be one \textsc{WWT\_PANEL}, \textsc{WWT\_INSET}, or +\textsc{WWT\_FRAME}. The \texttt{EndContainer()} is always needed. As with the +leaf widgets, if the default field values of the background widget are good, +you can omit setting it again. + +\medskip +A background widget used as a background for other widgets acts as a vertical +container. Use it as follows: +\begin{verbatim} + NWidget(type, colour, index), + SetDataTip(data, tip), + ... // Put child widgets here + EndContainer(), +\end{verbatim} +where \texttt{type}, \texttt{colour}, and \texttt{index} is the same as above. +In this case, the background widget gets its sizing information from the child +widgets, so you don't need to set them here. The \texttt{SetDataTip()} part is +only useful if its value must be different from the default values. + +\subsection{Space widget part} +The space widget is never stored in the widget array, and thus only has a few +data fields. Instantiation is done like +\begin{verbatim} + NWidget(NWID_SPACER), + SetMinimalSize(minx, miny), + SetFill(fillx, filly), + SetResize(stepx, stepy), +\end{verbatim} +The \texttt{minx} parameter is normally 0 in vertical container widgets, and +the \texttt{miny} parameter is normally 0 in horizontal container widgets. +If the default fill and resize settings are correct, they can be omitted +here. + + +\subsection{Creating a nested widget tree from its parts} +Constructing a nested widget tree from an array of nested widget parts is +done by a single function call: +\begin{verbatim} + NWidgetContainer *nwid_root; + nwid_root = MakeNWidgets(_nested_select_game_widgets, + lengthof(_nested_select_game_widgets)); +\end{verbatim} + +\end{document} + + +% vim: tw=78