wesnoth/doc/design/gui2/overall_design.tex
2018-03-09 11:37:00 +11:00

228 lines
12 KiB
TeX

\chapter{Overall design}
This chapter takes a deeper look into the overall design of the library. Before
we can explain how things work, we'll have a look at the features; both
implemented and planned for the future. Once we know what the gui should be able
to do I'll explain how these goals are achieved. The chapter ends with a short
explanation of the directory structure so you'll be able to find the parts of
the library.
\section{Features}
Wesnoth runs on a large amount of devices, with an even larger amount of display
resolutions, from $320\times 240$ on hand-held devices to $2560\times 1600$ on
large 30" screens. The gui should look appealing on all these devices. Therefore
there are three resolution groups:
\begin{description}
\item[hand-held devices] For these devices the code needs to be compiled with
\textbf{TINY\_GUI}. This forces all images to be scaled down by a factor two.
The typical resolutions on these devices are $320\times 240$ -- $640\times
480$.
\item[PC] For the usage on PC's Wesnoth offers the resolutions $800\times 600$
-- $2560\times 1600$\footnote{And larger once screens that size become
available.}.
\item[Netbooks] The first time when netbooks were introduced the normal resolution
was $800\times 480$, which is slightly smaller than the minimum PC resolution.
Therefore a start option \textsc{--smallgui} was added making minimal
modifications to the layout\footnote{Actually this is gui1 only.}.
\end{description}
In order to facilitate this range of resolutions the gui2 code allows several
definitions of a window, tuned for a specific resolution. The reason is twofold;
first to make a difference between the hand-held devices and PCs, second to allow
different views for different resolutions.
The main example of this feature\footnote{Not yet implemented, but one of the
main reasons to add this feature.} is the attack dialogue. The dialogue has a
button to show the damage calculation, which shows a new dialogue with the
calculation overview. From the UI point of view I consider that rather ugly and
rather have tabs to switch between the views. But when I have a larger screen the
dialogue only fills a small part and I need to switch between tabs to see the
info, in that case I rather have one dialogue without tabs, which directly shows
all information. When the user changes the resolution the dialogue should switch
between these two views, depending on the current resolution.
\paragraph{}
The gui should be able to adapt to the size actually needed, the current gui
uses fixed sizes at some places. This leads to problems such as when the screen
resolution is reduced widgets end up outside the dialogue or get truncated. The
same for some translated texts, where the translation is much longer as the
English original. Gui2 solves this problem by dynamically determining the size
of a widget and adjust the layout until it fits. This has the disadvantage that
dialogues with a lot of dynamic content, resize at random times and changing the
layout of the dialogue slightly. Another disadvantage is that when a dialogue
doesn't fit Wesnoth terminates. This problem can be fixed by adding scrollbars
to every window. When the dialogue doesn't fit the scrollbars are used and the
dialogue fits again, might be a bit ugly but at least everything fits again.
\paragraph{}
It must be possible for WML designers to change the entire gui of Wesnoth with
their own version. For example Spacenoth\footnote{That project is dead, but
that doesn't matter for this example.} is Wesnoth in a space setting, so the
project might want to use a more fitting user interface.
Adding a new gui is a lot of work and can't be done in one fell swoop, so the
code needs to support a gradual conversion. Therefore when you select your own
theme\footnote{Support for this selection and the entire fall-back haven't been
added yet. Obviously I want to add support, but it remains low priority until
somebody really wants to add their own gui.} the engine first searches in the
new theme for items\footnote{A widget or window.}. When an item is not found it
uses that item from the default theme. Therefore it's mandatory that every item
is defined for the default gui, which the engine validates at
startup\footnote{That causes the problem that Wesnoth sometimes refused to start
when the source and data are out-of-sync.}.
\section{The big picture}
First we dive into the components that define the gui.
\subsection{Widget}
A widget is the basic user interface element, like a label, a button or a text
entry. Every widget has its own behaviour, which sometimes can be influenced by
certain settings, but the main behaviour is fixed per widget. Next to behaviour
a widget also has a visual representation so the user can see and interact with
the widget.
Before the widget is shown to the user it needs to be created first, the
creation happens in the window builder class. This class reads the definition of
a widget and fills in the blanks et voil\`a the widget is there. Let's go over
this part in more slow-motion.
\paragraph{The definition}
The definition determines how a widget looks and some basic properties, these
properties are the same for all instances of that widget. For example a button
has a minimum size so the decoration can be drawn. It's possible to make
multiple definitions of a button. These different definitions, can look
different, have different minimum sizes and other properties.
These definitions are written in WML and a small loader class loads and
validates the definition. The definition is then added to the list of known
widgets of this type.
The definition of the widget depends on the resolution, this is for example used
in the button. It has a minimum size depending on the decoration used, in
\textbf{TINY\_GUI} mode the decoration is scaled down, so the minimum size can
also be reduced.
\paragraph{The builder}
The builder is started from the C++ code, started while building a window. This
window definition contains a list of widgets to build with more instance specific
values. For example a label builder has the text to show to the user as
parameter.
These builder ``scripts'' are also written in WML and loaded by a small loader
class that does the validation and builds the needed widget.
\paragraph{Widget}
The widget itself is written in a larger C++ class and it defines the behaviour
and provides various hooks to modify the properties of that widget. These hooks
are used by the builder, but can also be modified later by the engine.
Other hooks provide bindings to react to events. The bindings are now rather
static, but with the new event handling added late in the 1.8 release series
more things are possible. The plan is to enhance this part during the 1.9
release series and deprecate and remove the current interface.
Of course the question ``why wait until 1.9'' raises. The reason is simple: it
was added late in the 1.8 cycle to fix certain issues with the MP lobby. At that
time I had no time to convert the rest of the code, since I was working on the
MP lobby instead.
\subsection{Window}
A window can mean two things, the window widget and the window definition. In
this section the window definition is meant. Already discussed before, but a bit
more verbose this time.
The window definition defines a window and which widgets are placed in the
window. This window definition also depends on the resolution. This allows the
window to look different depending on the resolution. The changes can be small
or the window can look completely different.
\subsection{Dialogue}
A dialogue is a pure C++ thing. A dialogue shows a window, but is not a window itself.
So what's the difference\footnote{These are the definitions used in the gui2
code and not the definition of other window toolkits.}? A window is a dumb
combination of widgets created depending on the definitions in a WML file. After
the window is created it often needs extra content and reacts to certain events.
For example the language dialogue after building has an empty list of languages.
This is where the dialogue comes into play. The user asks for the language
selection dialogue. The code creates and shows a dialogue. The dialogue code
builds a window, then fills the language list with the available languages,
selects the current language and then shows it to the user.
In other dialogues the code also needs to wire in event handlers or build other
structures. It searches the wanted widget by id, in some cases it doesn't even
care what kind of widget is used. In other cases it needs to be of a certain
class or ``concept''. This allows a flexible design and lets the user select the
kind of widget used in some cases.
So the dialogue is the sugar between the WML window and an interactive dialogue
shown in the game.
\section{Directory structure}
This section describes the directories available. Instead of listing them in
alphabetic order, I list them in an order that makes explaining them more natural.
\begin{description}
\item[src/gui] The general source code directory with all parts used for the gui.
\begin{description}
\item[dialogs] This directory contains all dialogues used in Wesnoth, in
general every file contains one dialogue, the name of the file being the
logical name of what the dialogue does. Some dialogues have a helper
dialogue, which is sometimes embedded in the same file.
\item[widgets] This directory contains all widgets used in the library. Every
file contains one widget. Also base classes or concepts of widgets are
stored in this directory. During the development it also accumulated some
helper files, which don't fit in the aforementioned descriptions - this led
to the creation of the auxiliary directory. Some files haven't been moved to
this new directory yet.
\item[auxiliary] This directory contains auxiliary classes. Some helper
parts became so large that they got their own subdirectory.
\begin{description}
\item[event] Contains all event handling code, the translation from SDL events
to the internal events and their dispatching.
\item[widget\_definition] Contains the code to serialize the WML to an internal
data structure, needed to define that kind of widget. The names of the files
match the widget names. (Most files are rather small, but I prefer small
single tasked files over huge files controlling a lot of code\footnote{Some
might remember I started with a single file, which did exactly that, but the
file got too large to maintain efficiently.}.
\item[window\_builder] Contains the code to create a widget object from the
widget definition and the data supplied in the window definition. Again the
name of the file matches the name of widget they build. (These files are
also mostly small.)
\end{description}
\end{description}
\item[data/gui] The general data directory with all parts used for the gui. All
guis shipped with Wesnoth should be in a sub-directory of this one, with a
config file with the name of the directory as main entry point and include
the sub-directory. At the time of writing only one gui is shipped, the
default one.
\begin{description}
\item[default] This directory is the bases for the default gui.
\begin{description}
\item[macro] This directory contains some helper macros, for default font sizes.
\item[widget] This directory contains the definitions of widgets. Since there
can be multiple definitions of a widget their name is the name of the widget
with a suffix. The suffix for the default widgets is \textsc{default}, for
the others an appropriate name is picked.
\item[window] Contains definitions of windows, the name of the file is the
name of the dialogue it represents.
\end{description}
\end{description}
\end{description}