Add documentation

This commit is contained in:
Matthias Richter 2016-01-01 21:42:03 +01:00
parent 652291c175
commit 1dc24f9108
9 changed files with 1451 additions and 0 deletions

225
docs/gettingstarted.rst Normal file
View file

@ -0,0 +1,225 @@
Getting Started
===============
Before actually getting started, it is important to understand the motivation
and mechanics behind SUIT:
- **SUIT is an immediate mode GUI library**
- **Less is more**
- **Layouting must be easy**
Immediate mode?
---------------
With classical (retained) mode libraries you typically have a stage where you
create the whole UI when the program initializes. After that point, the GUI
is expected to not change very much.
With immediate mode libraries, on the other hand, the GUI is created every
frame from scratch. There are no widget objects, only functions that draw the
widget and update some internal GUI state. This allows to put the widgets in
their immediate conceptual context (instead of a construction stage). It also
makes the UI very flexible: Don't want to draw a widget? Simply remove the
call. Handling the mutable data (e.g., text of an input box) of each widget is
your responsibility. This separation of data and behaviour gives you greater
control of what is happening when an where, but can take a bit of time getting
used to - especially if you have used retained mode libraries before.
What SUIT is
^^^^^^^^^^^^
SUIT is simple: It provides only the most important widgets for games:
- :func:`Buttons <Button>` (including :func:`Image Buttons <ImageButton>`)
- :func:`Text Labels <Label>`
- :func:`Checkboxes <Checkbox>`
- :func:`Text Input <Input>`
- :func:`Value Sliders <Slider>`
SUIT is comfortable: It features a simple, yet effective row/column-based
layouting engine.
SUIT is adaptable: You can easily alter the color scheme, change how widgets
are drawn or swap the whole theme.
SUIT is hackable: The core library can be used to construct new widgets with
relative ease.
**SUIT is good at games!**
What SUIT is not
^^^^^^^^^^^^^^^^
SUIT is not a complete GUI library: It does not provide dropdowns, sub-windows,
radio buttons, menu bars, ribbons, etc.
SUIT is not a complete GUI library: SUIT spits separation of concerns, MVC and
other good OO practices in the face.
SUIT is not a complete GUI library: There is no markup language to generate or
style the GUI.
**SUIT is not good at "serious" applications!**
Hello, World
------------
SUIT is simple: Load the library, define your GUI in ``love.update()``, and
draw it in ``love.draw()``::
suit = require 'suit'
local show_message = false
function love.update(dt)
-- Put a button on the screen. If hit, show a message.
if suit.Button("Hello, World!", 100,100, 300,30).hit then
show_message = true
end
if show_message then
suit.Label("How are you today?", 100,150, 300,30)
end
end
function love.draw()
suit.core.draw()
end
As you can see, each widget is created by a function call (:func:`suit.Button
<Button>` and :func:`suit.Label <Label>`). The first argument is always the
"payload" of the widget, and the last four arguments define the position and
dimension of the widget. The widget returns a table indicating their updated
GUI state. The most important is ``hit``, which signals that the mouse was
clicked and released on the widget. See :doc:`Widgets <widgets>` for more info.
Mutable state
-------------
Widgets that mutate some state - input boxes and sliders - receive a table
argument as payload, e.g.::
local slider = {value = 1, max = 2}
function love.update(dt)
suit.Slider(slider, 100,100, 200,30)
suit.Label(tostring(slider.value), 300,100, 100,30)
end
Options
-------
You can define optional, well, options after the payload. These options usually
affect how the widget is drawn. For example, to align the label text to the
left in the above example, you would write::
local slider = {value = 1, max = 2}
function love.update(dt)
suit.Slider(slider, 100,100, 200,30)
suit.Label(tostring(slider.value), {align = "left"}, 300,100, 100,30)
end
Which options are available and what they are doing depends on the widget and
the theme.
Keyboard input
--------------
The input widget requires that you forward ``keypressed`` and ``textinput``
events to SUIT::
local input = {text = ""}
function love.update(dt)
suit.Input(input, 100,100,200,30)
suit.Label("Hello, "..input.text, {align="left"}, 100,150,200,30)
end
-- forward keyboard events
function love.textinput(t)
suit.core.textinput(t)
end
function love.keypressed(key)
suit.core.keypressed(key)
end
Layout
------
It is tedious to write down the position and size of each widget. It is also
not very easy to figure out what those numbers mean when you look at your code
after not touching it for some time. SUIT offers a simple, yet effective
layouting engine to put widgets in rows or columns. If you have ever dabbled
with `Qt's <http://qt.io>`_ ``QBoxLayout``, you already know 78.42% [1]_
of what you need to know.
The first example can be written as follows::
suit = require 'suit'
local show_message = false
function love.update(dt)
suit.layout.reset(100,100) -- reset layout origin to x=100, y=100
suit.layout.padding(10,10) -- padding of 10x10 pixels
-- add a new row with width=300 and height=30 and put a button in it
if suit.Button("Hello, World!", suit.layout.row(300,30)).hit then
show_message = true
end
-- add another row of the same size below the first row
if show_message then
suit.Label("How are you today?", suit.layout.row())
end
end
function love.draw()
suit.core.draw()
end
At the beginning of each frame, the layout has to be reset. You can provide an
optional starting position and padding as arguments. Rows and columns are added
using ``layout.row(w,h)`` and ``layout.col(w,h)``. If omitted, the width and
height of the cell are copied from the previous cell. There are also special
identifiers that calculate the size from all cells since the last ``reset()``:
``max``, ``min`` and ``median``. They do what you expect them to do.
It is also possible to nest rows and columns and to let cells dynamically fill
available space. Refer to the :doc:`Layout <layout>` documentation for more
information.
Themeing
--------
SUIT allows to customize the appearance of any widget (except
:func:`ImageButton`). Each widget is drawn by a function of the same name in
the ``theme``-table of the core module. So, a button is drawn by the function
``suit.core.theme.Button``. You can overwrite these functions or swap the whole
table to achieve a different look.
However, most of the time, especially when prototyping, you probably don't want
to do this. For this reason, the default theme can be customized by modifying a
color scheme, contained in the table ``suit.core.theme.color``::
theme.color = {
normal = {bg = {78,78,78}, fg = {200,200,200}, border={20,20,20}},
hot = {bg = {98,98,98}, fg = {69,201,84}, border={30,30,30}},
active = {bg = {88,88,88}, fg = {49,181,64}, border={10,10,10}}
}
The keys ``normal``, ``hot`` and ``active`` correspond to different widget states:
When the mouse is above a widget, it is ``hot``, if the mouse is pressed (but
not released) on a widget, it is ``active``, and otherwise it is in the
``normal`` state.
Each state defines a background (``bg``), foreground (``fg``) and border color.
You can change the colors directly by overwriting the values::
function love.load()
suit.core.theme.color.normal.fg = {255,255,255}
suit.core.theme.color.hot = {bg = {200,230,255}, {fg = {0,0,0}, border = {120,140,180}}}
end
.. [1] Determined by rigorous scientific experiments [2]_.
.. [2] Significance level p = 0.5 [1]_.