Update design document.
This commit is contained in:
parent
0d29a6d216
commit
dcfd8bea24
8 changed files with 555 additions and 1 deletions
|
@ -1,6 +1,27 @@
|
|||
\documentclass[a4paper,notitlepage,twocolumn,draft]{report}
|
||||
\documentclass[a4paper,notitlepage]{report}
|
||||
|
||||
\usepackage[english]{babel}
|
||||
\usepackage{listings}
|
||||
\lstset{
|
||||
numbers = left
|
||||
, showstringspaces = false
|
||||
, tabsize = 4
|
||||
, frame = single
|
||||
, xrightmargin = -7em
|
||||
, xleftmargin = -7em
|
||||
}
|
||||
|
||||
\lstdefinestyle{C++}{
|
||||
language = C++
|
||||
, escapeinside = {/*@}{@*/}}
|
||||
|
||||
\lstdefinelanguage{WML}{}
|
||||
\lstdefinestyle{WML}{
|
||||
language = WML
|
||||
, escapeinside = {\#*@}{@*\#}}
|
||||
|
||||
\usepackage{verbatim}
|
||||
|
||||
\usepackage {hyperref}
|
||||
|
||||
\author{M.~de Wever}
|
||||
|
@ -551,5 +572,214 @@ Subclasses of the tnotifier should add an notification function so the notifier
|
|||
can call all callbacks in the list. The notifier should take care of this
|
||||
calling.
|
||||
|
||||
|
||||
\chapter{Creating new widgets and dialogues}
|
||||
|
||||
This chapter dives into the area of creating your own widgets or dialogues. For
|
||||
this example we use a real widget and dialogue under development. The widget
|
||||
being developed is the progress bar and the screen the initial load screen.
|
||||
|
||||
First we make the widget then the screen in order to test the widget, this
|
||||
happens often when you need to add a new widget that you need it for a new
|
||||
dialogue so you need to create both for testing. Another option is to add the
|
||||
widget as dummy item to another existing dialogue. When adding a dialogue for
|
||||
which all widgets already exist this doesn't matter and you can directly dive
|
||||
into generating the dialogue.
|
||||
|
||||
\section{Creating the widget}
|
||||
\label{creating_the_widget}
|
||||
|
||||
The widget is normally split in 7 different files. Three .cpp/.hpp files and one
|
||||
WML file. Usually I start to create the new files by simply copy pasting the old
|
||||
files and pick a rather small class like timage or something. Then I start to
|
||||
update the build system files, followed by creating the code for the
|
||||
classes\footnote{Obviously I already thought about the design of the class
|
||||
before that, but that's of less importance in this tutorial}.
|
||||
|
||||
Now we start to explain what the various files do, first a general overview of
|
||||
the files after which I dive more into the implementation of the file.
|
||||
|
||||
\begin{description}
|
||||
|
||||
\item[src/gui/auxiliary/widget\_definition/progress\_bar.*]
|
||||
These files contain the definition of the progress bar. This mainly involves
|
||||
the fixed fields for the widget. This widget has no extra fields so the copy
|
||||
pasted version suffices. This file contains the \emph{static} properties for
|
||||
a certain definition of a progress bar.
|
||||
|
||||
\begin{description}
|
||||
\item[hpp] Listing \ref{widget_definition.hpp} contains the sample code.
|
||||
\begin{description}
|
||||
\item[Line \ref{widget_definition.hpp:control}] Normally a
|
||||
widget definition inherits from tcontrol\_definition which defines the
|
||||
basic mandatory fields for a widget definition and a templated load
|
||||
function for the resolution. Most widgets don't add more members to this
|
||||
class.
|
||||
\item[Line \ref{widget_definition.hpp:resolution}] Normally a resolution
|
||||
definition inherits from tresolution\_definition\_ which define the
|
||||
basic mandatory fiets for a resolution definition. Not all widgets use
|
||||
these members, but most do. Most widgets don't add more members to this
|
||||
class, except most container classes that add a grid builder
|
||||
definition. Another example is are the scrollbars which define some
|
||||
minimum sizes for parts of their control.
|
||||
\end{description}
|
||||
|
||||
\item[cpp] Listing \ref{widget_definition.cpp} contains the sample code.
|
||||
\begin{description}
|
||||
\item[Line \ref{widget_definition.cpp:textdomain}] Every file in the library
|
||||
is inside the ``wesnoth-lib'' text domain.
|
||||
\item[Line \ref{widget_definition.cpp:constructor}] The constructor used is
|
||||
pretty typical for all widgets.
|
||||
\item[Line \ref{widget_definition.cpp:resolution_constructor}] The
|
||||
constructor used is semi-typical. Resolutions that have their own
|
||||
members initialize them in the constructor, but also validate mandatory
|
||||
fields for their existence.
|
||||
|
||||
Also the progress bar only has one state, most widgets have more and
|
||||
thus add more states.
|
||||
|
||||
And maybe the most important part of this constructor is the wiki
|
||||
comment. This comment is used to generate wiki pages about the widget.
|
||||
These wiki pages are used by content creators to know how to create a
|
||||
proper WML file for the class.
|
||||
\end{description}
|
||||
\end{description}
|
||||
|
||||
\item[data/gui/default/widget/progress\_bar\_default.cfg]
|
||||
Now that the widget is defined, we can decide how it should look. Which is
|
||||
done in this file. Note that in the formula we use ``percentage'' which is
|
||||
the percentage of the bar to be filled.
|
||||
|
||||
% TODO add the description of the files
|
||||
|
||||
\item[src/gui/auxiliary/window\_builder/progress\_bar.*]
|
||||
These files contain the code to build a widget from the definition described
|
||||
above and a config object as defined in the window. This file contains the
|
||||
\emph{dynamic} properties of the progress bar. Since the progress bar has no
|
||||
dynamic content this file is also rather short.
|
||||
|
||||
\begin{description}
|
||||
\item[hpp] Listing \ref{window_builder.hpp} contains the sample code.
|
||||
\begin{description}
|
||||
\item[Line \ref{window_builder.hpp:control}] Normally a
|
||||
window builder inherits from tbuilder\_control which defines the
|
||||
basic mandatory fields for a window builder.
|
||||
|
||||
The function also declares the build function.
|
||||
|
||||
Widget define their own member if they want to have some runtime
|
||||
settings, e.g. the spacer defines its fixed size if needed.
|
||||
\end{description}
|
||||
|
||||
\item[cpp] Listing \ref{window_builder.cpp} contains the sample code.
|
||||
\begin{description}
|
||||
\item[Line \ref{window_builder.cpp:textdomain}] Every file in the library
|
||||
is inside the ``wesnoth-lib'' text domain.
|
||||
\item[Line \ref{window_builder.cpp:constructor}] The constructor used is
|
||||
pretty typical for all widgets.
|
||||
|
||||
If the constructor initialize custom members it may add some validation.
|
||||
This is also true when the widget has a grid, like the listbox or
|
||||
multi\_page.
|
||||
\item[Line \ref{window_builder.cpp:build}]
|
||||
This build() is semi-typical, it creates the widget initializes the
|
||||
default fields and returns the created object.
|
||||
|
||||
Widgets with their own members initialize them after initializing the
|
||||
default members.
|
||||
\item[Line \ref{window_builder.cpp:wiki}]
|
||||
At the end of the file it contains two wiki comment sections:
|
||||
|
||||
The first defines a macro with a short description of the widget.
|
||||
|
||||
The second describes the extra fields for the instance of the widget.
|
||||
\end{description}
|
||||
\end{description}
|
||||
|
||||
\item[src/gui/widgets/progress\_bar.*]
|
||||
These files contain the interaction the widget has with the outer world and
|
||||
how it reacts to events. Again the progress bar is rather boring. The
|
||||
interesting part is the setter of the percentage, here the value of the
|
||||
percentage use in the drawing routines is set\footnote{Other classes have a
|
||||
separate update canvas, but that's because the canvas in those classes is
|
||||
invalidated in several functions.}
|
||||
|
||||
% TODO add the description of the files
|
||||
|
||||
\end{description}
|
||||
|
||||
This completes the simple progress bar widget. Of course we haven't tested it
|
||||
yet since there's no dialogue to test it in. So let's implement a dialogue.
|
||||
|
||||
\begin{comment}
|
||||
|
||||
FIXME add to list in settings.
|
||||
|
||||
FIXME add a caveat emptor regarding broken linker
|
||||
|
||||
FIXME add the builder files, at least mention them
|
||||
|
||||
|
||||
\section{Creating the window}
|
||||
|
||||
The window is normally split in 3 files. One .cpp/.hpp file and one WML file.
|
||||
The dialogue used it the load progress dialogue, this is not the greatest
|
||||
example dialogue, so this section may later use another dialogue as example.
|
||||
|
||||
\end{comment}
|
||||
|
||||
\appendix
|
||||
|
||||
|
||||
\chapter{Files for creating the widget}
|
||||
|
||||
This chapter contains the files created in \S~\ref{creating_the_widget}, these
|
||||
files aren't the real files added, but a slightly modified version; The
|
||||
copyright headers are stripped to avoid taking up useless space. Some extra
|
||||
comments are added to make referencing possible. This also means the files here
|
||||
will get out of date with the real files when fixes are committed, that's also
|
||||
fine since it doesn't change how the files are structured. The label still
|
||||
mentions the original filename, but might over time differ from the listings
|
||||
below.
|
||||
|
||||
\lstinputlisting[style=C++
|
||||
, caption={src/gui/auxiliary/widget\_definition/progress\_bar.hpp}
|
||||
, label=widget_definition.hpp]
|
||||
{gui2/widget_definition.hpp}
|
||||
|
||||
\pagebreak
|
||||
\lstinputlisting[style=C++
|
||||
, caption={src/gui/auxiliary/widget\_definition/progress\_bar.cpp}
|
||||
, label=widget_definition.cpp]
|
||||
{gui2/widget_definition.cpp}
|
||||
|
||||
\pagebreak
|
||||
\lstinputlisting[style=WML
|
||||
, caption={data/gui/default/widget/progress\_bar\_default.cfg}
|
||||
, label=progress_bar.cfg]
|
||||
{gui2/progress_bar.cfg}
|
||||
|
||||
\pagebreak
|
||||
\lstinputlisting[style=C++
|
||||
, caption={src/gui/auxiliary/window\_builder/progress\_bar.hpp}
|
||||
, label=window_builder.hpp]
|
||||
{gui2/window_builder.hpp}
|
||||
|
||||
\lstinputlisting[style=C++
|
||||
, caption={src/gui/auxiliary/window\_builder/progress\_bar.cpp}
|
||||
, label=window_builder.cpp]
|
||||
{gui2/window_builder.cpp}
|
||||
|
||||
\lstinputlisting[style=C++
|
||||
, caption={src/gui/widgets/progress\_bar.hpp}
|
||||
, label=progress_bar.hpp]
|
||||
{gui2/progress_bar.hpp}
|
||||
|
||||
\pagebreak
|
||||
\lstinputlisting[style=C++
|
||||
, caption={src/gui/widgets/progress\_bar.cpp}
|
||||
, label=progress_bar.cpp]
|
||||
{gui2/progress_bar.cpp}
|
||||
|
||||
\end{document}
|
||||
|
||||
|
|
84
doc/design/gui2/progress_bar.cfg
Normal file
84
doc/design/gui2/progress_bar.cfg
Normal file
|
@ -0,0 +1,84 @@
|
|||
#textdomain wesnoth-lib
|
||||
###
|
||||
### Definition of an progress bar, which has the same height on normal and tiny
|
||||
### gui.
|
||||
###
|
||||
|
||||
[progress_bar_definition]
|
||||
id = "default"
|
||||
description = "A progress_bar."
|
||||
|
||||
[resolution]
|
||||
|
||||
min_width = 14
|
||||
min_height = 41
|
||||
|
||||
default_width = 54
|
||||
default_height = 41
|
||||
|
||||
max_width = 0
|
||||
max_height = 41
|
||||
|
||||
[state_enabled]
|
||||
|
||||
[draw]
|
||||
|
||||
# Outer "golden" border.
|
||||
[rectangle]
|
||||
x = 0
|
||||
y = 0
|
||||
w = "(width)"
|
||||
h = 41
|
||||
border_thickness = 1
|
||||
border_colour = "188, 176, 136"
|
||||
[/rectangle]
|
||||
|
||||
# Inner black border, with gray filling.
|
||||
[rectangle]
|
||||
x = 1
|
||||
y = 1
|
||||
w = "(width - 2)"
|
||||
h = 39
|
||||
border_thickness = 1
|
||||
border_colour = "0, 0, 0"
|
||||
fill_colour = "21, 22, 24"
|
||||
[/rectangle]
|
||||
|
||||
# 3D effect at upper side.
|
||||
[rectangle]
|
||||
x = 2
|
||||
y = 3
|
||||
w = "(((width - 4) * precentage) / 100)"
|
||||
h = 2
|
||||
border_thickness = 0
|
||||
fill_colour = "79, 103, 123"
|
||||
[/rectangle]
|
||||
|
||||
# Main bar
|
||||
[rectangle]
|
||||
x = 2
|
||||
y = 5
|
||||
w = "(((width - 4) * precentage) / 100)"
|
||||
h = 33
|
||||
border_thickness = 0
|
||||
fill_colour = "21, 53, 80"
|
||||
[/rectangle]
|
||||
|
||||
# 3D effect at lower side.
|
||||
[rectangle]
|
||||
x = 2
|
||||
y = 38
|
||||
w = "(((width - 4) * precentage) / 100)"
|
||||
h = 2
|
||||
border_thickness = 0
|
||||
fill_colour = "10, 26, 40"
|
||||
[/rectangle]
|
||||
|
||||
[/draw]
|
||||
|
||||
[/state_enabled]
|
||||
|
||||
[/resolution]
|
||||
|
||||
[/progress_bar_definition]
|
||||
|
40
doc/design/gui2/progress_bar.cpp
Normal file
40
doc/design/gui2/progress_bar.cpp
Normal file
|
@ -0,0 +1,40 @@
|
|||
#define GETTEXT_DOMAIN "wesnoth-lib"
|
||||
|
||||
#include "gui/widgets/progress_bar.hpp"
|
||||
|
||||
#include "gui/auxiliary/widget_definition/progress_bar.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/widgets/settings.hpp"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
#define LOG_SCOPE_HEADER get_control_type() + " [" + id() + "] " + __func__
|
||||
#define LOG_HEADER LOG_SCOPE_HEADER + ':'
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
REGISTER_WIDGET(progress_bar)
|
||||
|
||||
void tprogress_bar::set_percentage(const unsigned percentage)
|
||||
{
|
||||
assert(percentage <= 100);
|
||||
|
||||
if(percentage_ != percentage) {
|
||||
percentage_ = percentage;
|
||||
|
||||
foreach(tcanvas& c, canvas()) {
|
||||
c.set_variable("percentage", variant(percentage));
|
||||
}
|
||||
|
||||
set_dirty();
|
||||
}
|
||||
}
|
||||
|
||||
const std::string& tprogress_bar::get_control_type() const
|
||||
{
|
||||
static const std::string type = "progress_bar";
|
||||
return type;
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
60
doc/design/gui2/progress_bar.hpp
Normal file
60
doc/design/gui2/progress_bar.hpp
Normal file
|
@ -0,0 +1,60 @@
|
|||
#ifndef GUI_WIDGETS_PROGRESS_BAR_HPP_INCLUDED
|
||||
#define GUI_WIDGETS_PROGRESS_BAR_HPP_INCLUDED
|
||||
|
||||
#include "gui/widgets/control.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
class tprogress_bar
|
||||
: public tcontrol
|
||||
{
|
||||
public:
|
||||
|
||||
tprogress_bar()
|
||||
: tcontrol(COUNT)
|
||||
, percentage_(-1)
|
||||
{
|
||||
// Force canvas update
|
||||
set_percentage(0);
|
||||
}
|
||||
|
||||
/***** ***** ***** ***** Inherited ***** ***** ***** *****/
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
void set_active(const bool /*active*/) {}
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
bool get_active() const { return true; }
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
unsigned get_state() const { return ENABLED; }
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
bool disable_click_dismiss() const { return false; }
|
||||
|
||||
|
||||
/***** ***** ***** setters / getters for members ***** ****** *****/
|
||||
|
||||
void set_percentage(const unsigned percentage);
|
||||
unsigned get_percentage() const { return percentage_; }
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Possible states of the widget.
|
||||
*
|
||||
* Note the order of the states must be the same as defined in settings.hpp.
|
||||
*/
|
||||
enum tstate { ENABLED, COUNT };
|
||||
|
||||
/** The percentage done. */
|
||||
unsigned percentage_;
|
||||
|
||||
/** Inherited from tcontrol. */
|
||||
const std::string& get_control_type() const;
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
41
doc/design/gui2/widget_definition.cpp
Normal file
41
doc/design/gui2/widget_definition.cpp
Normal file
|
@ -0,0 +1,41 @@
|
|||
#define GETTEXT_DOMAIN "wesnoth-lib" /*@ \label{widget_definition.cpp:textdomain} @*/
|
||||
|
||||
#include "gui/auxiliary/widget_definition/progress_bar.hpp"
|
||||
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
tprogress_bar_definition::tprogress_bar_definition(const config& cfg) : /*@ \label{widget_definition.cpp:constructor} @*/
|
||||
tcontrol_definition(cfg)
|
||||
{
|
||||
DBG_GUI_P << "Parsing progress bar " << id << '\n';
|
||||
|
||||
load_resolutions<tresolution>(cfg);
|
||||
}
|
||||
|
||||
tprogress_bar_definition::tresolution::tresolution(const config& cfg) : /*@ \label{widget_definition.cpp:resolution_constructor} @*/
|
||||
tresolution_definition_(cfg)
|
||||
{
|
||||
/*WIKI
|
||||
* @page = GUIWidgetDefinitionWML
|
||||
* @order = 1_progress_bar
|
||||
*
|
||||
* == Progress bar ==
|
||||
*
|
||||
* @macro = progress_bar_description
|
||||
*
|
||||
* The definition of a progress bar. This object shows the progress of a certain
|
||||
* action, or the value state of a certain item.
|
||||
*
|
||||
* The following states exist:
|
||||
* * state_enabled, the progress bar is enabled.
|
||||
*
|
||||
*/
|
||||
|
||||
// Note the order should be the same as the enum tstate is progress_bar.hpp.
|
||||
state.push_back(tstate_definition(cfg.child("state_enabled")));
|
||||
}
|
||||
|
||||
} // namespace gui2
|
||||
|
22
doc/design/gui2/widget_definition.hpp
Normal file
22
doc/design/gui2/widget_definition.hpp
Normal file
|
@ -0,0 +1,22 @@
|
|||
#ifndef GUI_AUXILIARY_WIDGET_DEFINITION_PROGRESS_BAR_HPP_INCLUDED
|
||||
#define GUI_AUXILIARY_WIDGET_DEFINITION_PROGRESS_BAR_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/widget_definition.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
struct tprogress_bar_definition /*@ \label{widget_definition.hpp:control} @*/
|
||||
: public tcontrol_definition
|
||||
{
|
||||
explicit tprogress_bar_definition(const config& cfg);
|
||||
|
||||
struct tresolution /*@ \label{widget_definition.hpp:resolution} @*/
|
||||
: public tresolution_definition_
|
||||
{
|
||||
explicit tresolution(const config& cfg);
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
52
doc/design/gui2/window_builder.cpp
Normal file
52
doc/design/gui2/window_builder.cpp
Normal file
|
@ -0,0 +1,52 @@
|
|||
#define GETTEXT_DOMAIN "wesnoth-lib" /*@ \label{window_builder.cpp:textdomain} @*/
|
||||
|
||||
#include "gui/auxiliary/window_builder/progress_bar.hpp"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "gui/auxiliary/log.hpp"
|
||||
#include "gui/widgets/progress_bar.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace implementation {
|
||||
|
||||
tbuilder_progress_bar::tbuilder_progress_bar(const config& cfg) /*@ \label{window_builder.cpp:constructor} @*/
|
||||
: tbuilder_control(cfg)
|
||||
{
|
||||
}
|
||||
|
||||
twidget* tbuilder_progress_bar::build() const /*@ \label{window_builder.cpp:build} @*/
|
||||
{
|
||||
tprogress_bar* widget = new tprogress_bar();
|
||||
|
||||
init_control(widget);
|
||||
|
||||
DBG_GUI_G << "Window builder: placed progress bar '"
|
||||
<< id << "' with defintion '"
|
||||
<< definition << "'.\n";
|
||||
|
||||
return widget;
|
||||
}
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
/*@ \label{window_builder.cpp:wiki} @*//*WIKI_MACRO
|
||||
* @start_macro = progress_bar_description
|
||||
*
|
||||
* A progress bar shows the progress of a certain object.
|
||||
* @end_macro
|
||||
*/
|
||||
|
||||
/*WIKI
|
||||
* @page = GUIWidgetInstanceWML
|
||||
* @order = 2_progress_bar
|
||||
*
|
||||
* == Image ==
|
||||
*
|
||||
* @macro = progress_bar_description
|
||||
*
|
||||
* A progress bar has no extra fields.
|
||||
*/
|
||||
|
25
doc/design/gui2/window_builder.hpp
Normal file
25
doc/design/gui2/window_builder.hpp
Normal file
|
@ -0,0 +1,25 @@
|
|||
#ifndef GUI_AUXILIARY_WINDOW_BUILDER_PROGRESS_BAR_HPP_INCLUDED
|
||||
#define GUI_AUXILIARY_WINDOW_BUILDER_PROGRESS_BAR_HPP_INCLUDED
|
||||
|
||||
#include "gui/auxiliary/window_builder/control.hpp"
|
||||
|
||||
namespace gui2 {
|
||||
|
||||
namespace implementation {
|
||||
|
||||
struct tbuilder_progress_bar /*@ \label{window_builder.hpp:control} @*/
|
||||
: public tbuilder_control
|
||||
{
|
||||
|
||||
tbuilder_progress_bar(const config& cfg);
|
||||
|
||||
twidget* build () const;
|
||||
};
|
||||
|
||||
} // namespace implementation
|
||||
|
||||
} // namespace gui2
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Add table
Reference in a new issue