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

192
docs/Makefile Normal file
View file

@ -0,0 +1,192 @@
# Makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
PAPER =
BUILDDIR = _build
# User-friendly check for sphinx-build
ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1)
$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/)
endif
# Internal variables.
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
# the i18n builder cannot share the environment and doctrees with the others
I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest coverage gettext
help:
@echo "Please use \`make <target>' where <target> is one of"
@echo " html to make standalone HTML files"
@echo " dirhtml to make HTML files named index.html in directories"
@echo " singlehtml to make a single large HTML file"
@echo " pickle to make pickle files"
@echo " json to make JSON files"
@echo " htmlhelp to make HTML files and a HTML help project"
@echo " qthelp to make HTML files and a qthelp project"
@echo " applehelp to make an Apple Help Book"
@echo " devhelp to make HTML files and a Devhelp project"
@echo " epub to make an epub"
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
@echo " latexpdf to make LaTeX files and run them through pdflatex"
@echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx"
@echo " text to make text files"
@echo " man to make manual pages"
@echo " texinfo to make Texinfo files"
@echo " info to make Texinfo files and run them through makeinfo"
@echo " gettext to make PO message catalogs"
@echo " changes to make an overview of all changed/added/deprecated items"
@echo " xml to make Docutils-native XML files"
@echo " pseudoxml to make pseudoxml-XML files for display purposes"
@echo " linkcheck to check all external links for integrity"
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
@echo " coverage to run coverage check of the documentation (if enabled)"
clean:
rm -rf $(BUILDDIR)/*
html:
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
dirhtml:
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
singlehtml:
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
pickle:
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
@echo
@echo "Build finished; now you can process the pickle files."
json:
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
@echo
@echo "Build finished; now you can process the JSON files."
htmlhelp:
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
@echo
@echo "Build finished; now you can run HTML Help Workshop with the" \
".hhp project file in $(BUILDDIR)/htmlhelp."
qthelp:
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
@echo
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/hump.qhcp"
@echo "To view the help file:"
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/hump.qhc"
applehelp:
$(SPHINXBUILD) -b applehelp $(ALLSPHINXOPTS) $(BUILDDIR)/applehelp
@echo
@echo "Build finished. The help book is in $(BUILDDIR)/applehelp."
@echo "N.B. You won't be able to view it unless you put it in" \
"~/Library/Documentation/Help or install it in your application" \
"bundle."
devhelp:
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
@echo
@echo "Build finished."
@echo "To view the help file:"
@echo "# mkdir -p $$HOME/.local/share/devhelp/hump"
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/hump"
@echo "# devhelp"
epub:
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
@echo
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
latex:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@echo "Run \`make' in that directory to run these through (pdf)latex" \
"(use \`make latexpdf' here to do that automatically)."
latexpdf:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through pdflatex..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
latexpdfja:
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
@echo "Running LaTeX files through platex and dvipdfmx..."
$(MAKE) -C $(BUILDDIR)/latex all-pdf-ja
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
text:
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
man:
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
@echo
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
texinfo:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo
@echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
@echo "Run \`make' in that directory to run these through makeinfo" \
"(use \`make info' here to do that automatically)."
info:
$(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
@echo "Running Texinfo files through makeinfo..."
make -C $(BUILDDIR)/texinfo info
@echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
gettext:
$(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
@echo
@echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
changes:
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
linkcheck:
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/output.txt."
doctest:
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
@echo "Testing of doctests in the sources finished, look at the " \
"results in $(BUILDDIR)/doctest/output.txt."
coverage:
$(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage
@echo "Testing of coverage in the sources finished, look at the " \
"results in $(BUILDDIR)/coverage/python.txt."
xml:
$(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml
@echo
@echo "Build finished. The XML files are in $(BUILDDIR)/xml."
pseudoxml:
$(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml
@echo
@echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml."

293
docs/conf.py Normal file
View file

@ -0,0 +1,293 @@
# -*- coding: utf-8 -*-
#
# SUIT documentation build configuration file, created by
# sphinx-quickstart on Sat Oct 10 13:10:12 2015.
#
# This file is execfile()d with the current directory set to its
# containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys
import os
import shlex
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration ------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.mathjax',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
# source_suffix = ['.rst', '.md']
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'SUIT'
copyright = u'2016, Matthias Richter'
author = u'Matthias Richter'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '1.0'
# The full version, including alpha/beta/rc tags.
release = '1.0'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = ['_build']
# The reST default role (used for this markup: `text`) to use for all
# documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# If true, keep warnings as "system message" paragraphs in the built documents.
#keep_warnings = False
# If true, `todo` and `todoList` produce output, else they produce nothing.
todo_include_todos = False
# -- Options for HTML output ----------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
html_theme = 'alabaster'
# Theme options are theme-specific and customize the look and feel of a theme
# further. For a list of options available for each theme, see the
# documentation.
#html_theme_options = {}
# Add any paths that contain custom themes here, relative to this directory.
#html_theme_path = []
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
#html_logo = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
#html_favicon = None
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# Add any extra paths that contain custom files (such as robots.txt or
# .htaccess) here, relative to this directory. These files are copied
# directly to the root of the documentation.
#html_extra_path = []
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
#html_sidebars = {}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Language to be used for generating the HTML full-text search index.
# Sphinx supports the following languages:
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja'
# 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr'
#html_search_language = 'en'
# A dictionary with options for the search language support, empty by default.
# Now only 'ja' uses this config value
#html_search_options = {'type': 'default'}
# The name of a javascript file (relative to the configuration directory) that
# implements a search results scorer. If empty, the default will be used.
#html_search_scorer = 'scorer.js'
# Output file base name for HTML help builder.
htmlhelp_basename = 'suitdoc'
# -- Options for LaTeX output ---------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
# Latex figure (float) alignment
#'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'suit.tex', u'SUIT Documentation',
u'Matthias Richter', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output ---------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'SUIT', u'SUIT Documentation',
[author], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output -------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'SUIT', u'SUIT Documentation',
author, 'SUIT', 'One line description of project.',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'
# If true, do not generate a @detailmenu in the "Top" node's menu.
#texinfo_no_detailmenu = False
primary_domain = "js"
highlight_language = "lua"
import sphinx_rtd_theme
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]

191
docs/core.rst Normal file
View file

@ -0,0 +1,191 @@
Core Functions
==============
.. note::
Work in progress...
The core functions can be divided into two parts: Functions of interest to the
user and functions of interest to the (widget) developer.
External Interface
------------------
Drawing
-------
.. function:: draw()
Draw the GUI - call in ``love.draw``.
.. data:: theme
The current theme. See :doc:`themes`.
Mouse Input
^^^^^^^^^^^
.. function:: updateMouse(x,y, buttonDown)
:param number x,y: Position of the mouse.
:param boolean buttonDown: Whether the mouse button is down.
Update mouse position and button status. You do not need to call this function,
unless you use some screen transformation (e.g., scaling, camera systems, ...).
Keyboard Input
^^^^^^^^^^^^^^
.. function:: keypressed(key)
:param KeyConstant key: The pressed key.
Forwards a ``love.keypressed(key)`` event to SUIT.
.. function:: textinput(char)
:param string char: The pressed character
Forwards a ``love.textinput(key)`` event to SUIT.
Internal Helpers
----------------
.. function:: getOptionsAndSize(...)
:param mixed ...: Varargs.
:returns: ``options, x,y,w,h``.
Converts varargs to option table and size definition. Used in the widget
functions.
.. function:: registerDraw(f, ...)
:param function f: Function to call in ``draw()``.
:param mixed ...: Arguments to f.
Registers a function to be executed during :func:`draw()`. Used by widgets to
make themselves visible.
.. function:: enterFrame()
Prepares GUI state when entering a frame.
.. function:: exitFrame()
Clears GUI state when exiting a frame.
GUI State
^^^^^^^^^
.. function:: anyHot()
:returns: ``true`` if any widget is in the ``hot`` state.
Checks if any widget is in the hot state
.. function:: isHot(id)
:param mixed id: Identifier of the widget.
:returns: ``true`` if the widget is in the ``hot`` state.
Checks if the widget identified by ``id`` is hovered by the mouse.
.. function:: wasHot(id)
:param mixed id: Identifier of the widget.
:returns: ``true`` if the widget was in the ``hot`` state in the last frame.
Checks if the widget identified by ``id`` was hovered by the mouse in the last frame.
.. function:: isActive(id)
:param mixed id: Identifier of the widget.
:returns: ``true`` if the widget is in the ``active`` state.
Checks whether the mouse button is pressed on the widget identified by ``id``.
Mouse Input
^^^^^^^^^^^
.. function:: mouseInRect(x,y,w,h)
:param numbers x,y,w,h: Rectangle definition.
:returns: ``true`` if the mouse cursor is in the rectangle.
Checks whether the mouse cursor is in the rectangle defined by ``x,y,w,h``.
.. function:: registerMouseHit(id, ul_x, ul_y, hit)
:param mixed id: Identifier of the widget.
:param numbers ul_x, ul_y: Upper left corner of the widget.
:param function hit: Function to perform the hit test.
Registers a hit-test defined by the function ``hit`` for the widget identified
by ``id``. Sets the widget to ``hot`` if th hit-test returns ``true``. Sets the
widget to ``active`` if the hit-test returns ``true`` and the mouse button is
pressed.
The hit test receives coordinates in the coordinate system of the widget, i.e.
``(0,0)`` is the upper left corner of the widget.
.. function:: registerHitbox(id, x,y,w,h)
:param mixed id: Identifier of the widget.
:param numbers x,y,w,h: Rectangle definition.
Registers a hitbox for the widget identified by ``id``. Literally this function::
function registerHitbox(id, x,y,w,h)
return registerMouseHit(id, x,y, function(u,v)
return u >= 0 and u <= w and v >= 0 and v <= h
end)
end
.. function:: mouseReleasedOn(id)
:param mixed id: Identifier of the widget.
:returns: ``true`` if the mouse was released on the widget.
Checks whether the mouse button was released on the widget identified by ``id``.
.. function:: getMousePosition()
:returns: Mouse positon ``mx, my``.
Get the mouse position.
Keyboard Input
^^^^^^^^^^^^^^
.. function:: getPressedKey()
:returns: KeyConstant
Get the currently pressed key (if any).
.. function:: grabKeyboardFocus(id)
:param mixed id: Identifier of the widget.
Try to grab keyboard focus. Successful only if the widget is in the ``active``
state.
.. function:: hasKeyboardFocus(id)
:param mixed id: Identifier of the widget.
:returns: ``true`` if the widget has keyboard focus.
Checks whether the widget identified by ``id`` currently has keyboard focus.
.. function:: keyPressedOn(id, key)
:param mixed id: Identifier of the widget.
:param KeyConstant key: Key to query.
:returns: ``true`` if ``key`` was pressed on the widget.
Checks whether the key ``key`` was pressed while the widget identified by
``id`` has keyboard focus.

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]_.

161
docs/index.rst Normal file
View file

@ -0,0 +1,161 @@
SUIT
====
Simple User Interface Toolkit for `LÖVE <http://love2d.org>`_.
SUIT up
-------
You can download SUIT and view the code on github: `vrld/SUIT
<http://github.com/vrld/SUIT>`_.
You may also download the sourcecode as a `zip
<http://github.com/vrld/SUIT/zipball/master>`_ or `tar
<http://github.com/vrld/SUIT/tarball/master>`_ file.
Using `Git <http://git-scm.com>`_, you can clone the project by running::
git clone git://github.com/vrld/SUIT
Once done, tou can check for updates by running::
git pull
Read on
-------
.. toctree::
:maxdepth: 2
Getting Started <gettingstarted>
Widgets <widgets>
Layout <layout>
Core Functions <core>
Themeing <themes>
License <license>
Example code
------------
::
suit = require 'suit'
function love.load()
-- generate some assets
snd = generateClickySound()
normal, hot = generateImageButton()
smallerFont = love.graphics.newFont(10)
end
-- mutable widget data
local slider= {value = .5, max = 2}
local input = {text = "Hello"}
local chk = {text = "Check me out"}
function love.update(dt)
-- new layout at 100,100 with a padding of 20x20 px
suit.layout.reset(100,100, 20,20)
-- Button
state = suit.Button("Hover me!", suit.layout.row(200,30))
if state.entered then
love.audio.play(snd)
end
if state.hit then
print("Ouch!")
end
-- Input box
if suit.Input(input, suit.layout.row()).submitted then
print(input.text)
end
-- dynamically add widgets
if suit.Button("test2", suit.layout.row(nil,40)).hovered then
-- drawing options can be provided for each widget ... optionally
suit.Button("You can see", {align='left', valign='top'}, suit.layout.row(nil,30))
suit.Button("...but you can't touch!", {align='right', valign='bottom'}, suit.layout.row(nil,30))
end
-- Checkbox
suit.Checkbox(chk, {align='right'}, suit.layout.row())
-- nested layouts
suit.layout.push(suit.layout.row())
suit.Slider(slider, suit.layout.col(160, 20))
suit.Label(("%.02f"):format(slider.value), suit.layout.col(40))
suit.layout.pop()
-- image buttons
suit.ImageButton({normal, hot = hot}, suit.layout.row(200,100))
if chk.checked then
-- precomputed layout can fill up available space
suit.layout.reset()
rows = suit.layout.rows{pos = {400,100},
min_height = 300,
{200, 30},
{30, 'fill'},
{200, 30},
}
suit.Label("You uncovered the secret!", {align="left", font = smallerFont}, rows.cell(1))
suit.Label(slider.value, {align='left'}, rows.cell(3))
-- give different id to slider on same object so they don't grab
-- each others user interaction
suit.Slider(slider, {id = 'vs', vertical=true}, rows.cell(2))
print(rows.cell(3))
end
end
function love.draw()
-- draw the gui
suit.core.draw()
end
-- forward keyboard events
function love.textinput(t)
suit.core.textinput(t)
end
function love.keypressed(key)
suit.core.keypressed(key)
end
-- generate assets (see love.load)
function generateClickySound()
local snd = love.sound.newSoundData(512, 44100, 16, 1)
for i = 0,snd:getSampleCount()-1 do
local t = i / 44100
local s = i / snd:getSampleCount()
snd:setSample(i, (.7*(2*love.math.random()-1) + .3*math.sin(t*9000*math.pi)) * (1-s)^1.2 * .3)
end
return love.audio.newSource(snd)
end
function generateImageButton()
local normal, hot = love.image.newImageData(200,100), love.image.newImageData(200,100)
normal:mapPixel(function(x,y)
local d = (x/200-.5)^2 + (y/100-.5)^2
if d < .12 then
return 200,160,20,255
end
return 0,0,0,0
end)
hot:mapPixel(function(x,y)
local d = (x/200-.5)^2 + (y/100-.5)^2
if d < .13 then
return 255,255,255,255
end
return 0,0,0,0
end)
return love.graphics.newImage(normal), love.graphics.newImage(hot)
end
Indices and tables
------------------
* :ref:`genindex`
* :ref:`modindex`
* :ref:`search`

172
docs/layout.rst Normal file
View file

@ -0,0 +1,172 @@
Layout
======
.. note::
Still under construction...
Immediate Mode Layouts
----------------------
.. function:: reset(x,y, pad_x, pad_y)
:param numbers x,y: Origin of the layout (optional).
:param pad_x,pad_y: Cell padding (optional).
Reset the layout, puts the origin at ``(x,y)`` and sets the cell padding to
``pad_x`` and ``pad_y``.
.. function:: padding(pad_x,pad_y)
:param pad_x,pad_y: Cell padding.
Sets the cell padding to ``pad_x`` and ``pad_y``.
.. function:: push(x,y)
:param numbers x,y: Origin of the inner layout (optional).
Saves the layout state (position, padding, sizes, etc.) on a stack and resets
the layout with position ``(x,y)``.
Used for nested row/column layouts.
.. function:: pop()
Restores the layout parameters from the stack and advances the layout position
according to the size of the popped layout.
Used for nested row/column layouts.
.. function:: row(w,h)
:param mixed w,h: Cell width and height (optional).
:returns: Position and size of the cell: ``x,y,w,h``.
Creates a new cell below the current cell with width ``w`` and height ``h``. If
either ``w`` or ``h`` is omitted, the value is set the last used value. Both
``w`` and ``h`` can be a string, which takes the following meaning:
``max``
Maximum of all values since the last reset.
``min``
Mimimum of all values since the last reset.
``median``
Median of all values since the last reset.
Used to provide the last four arguments to a widget, e.g.::
suit.Button("Start Game", suit.layout.row(100,30))
suit.Button("Options", suit.layout.row())
suit.Button("Quit", suit.layout.row(nil, "median"))
.. function:: col(w,h)
:param mixed w,h: Cell width and height (optional).
:returns: Position and size of the cell: ``x,y,w,h``.
Creates a new cell right to the current cell with width ``w`` and height ``h``.
If either ``w`` or ``h`` is omitted, the value is set the last used value. Both
``w`` and ``h`` can be a string, which takes the following meaning:
``max``
Maximum of all values since the last reset.
``min``
Mimimum of all values since the last reset.
``median``
Median of all values since the last reset.
Used to provide the last four arguments to a widget, e.g.::
suit.Button("OK", suit.layout.col(100,30))
suit.Button("Cancel", suit.layout.col("max"))
Predefined Layouts
------------------
Apart from immediate mode layouts, you can specify layouts in advance.
The specification is a table of tables, where each inner table follows the
convention of :func:`row` and :func:`col`.
The result is a layout definition object that can be used to access the cells.
There is almost only one reason to do so: You know the area of your layout in
advance (say, the screen size), and want certain cells to dynamically fill the
available space.
.. note::
Unlike immediate mode layouts, predefined layouts **can not be nested**.
Layout Specifications
^^^^^^^^^^^^^^^^^^^^^
Layout specifications are tables of tables, where the each inner table
corresponds to a cell. The inner tables define the width and height of the cell
according to the rules of :func:`row` and :func:`col`, with one additonal
keyword:
``fill``
Fills the available space, determined by ``min_height`` or ``min_width`` and
the number of cells with property ``fill``.
For example, this row specification makes the height of the second cell to
``(300 - 50 - 50) / 1 = 200``::
{min_height = 300,
{100, 50},
{nil, 'fill'},
{nil, 50},
}
This column specification divides the space evenly among two cells::
{min_width = 300,
{'fill', 100}
{'fill'}
}
Apart from ``min_height`` and ``min_width``, layout specifications can also
define the position (upper left corner) of the layout using the ``pos`` keyword::
{min_width = 300, pos = {100,100},
{'fill', 100}
{'fill'}
}
Layout Definition Objects
^^^^^^^^^^^^^^^^^^^^^^^^^
Once constructed, the layout can be executed using a layout definition object
in two ways:
- Using iterators::
for i, x,y,w,h in definition() do
suit.Button("Button "..i, x,y,w,h)
end
- Using the ``cell(i)`` accessor::
suit.Button("Button 1", definition.cell(1))
suit.Button("Button 3", definition.cell(3))
suit.Button("Button 2", definition.cell(2))
Constructors
^^^^^^^^^^^^
.. function:: rows(spec)
:param table spec: Layout specification.
:returns: Layout definition object.
Defines a row layout.
.. function:: cols(spec)
:param table spec: Layout specification.
:returns: Layout definition object.
Defines a column layout.

26
docs/license.rst Normal file
View file

@ -0,0 +1,26 @@
License
=======
Copyright (c) 2016 Matthias Richter
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
Except as contained in this notice, the name(s) of the above copyright holders
shall not be used in advertising or otherwise to promote the sale, use or
other dealings in this Software without prior written authorization.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

5
docs/themes.rst Normal file
View file

@ -0,0 +1,5 @@
Themeing
========
.. note::
Under construction.

186
docs/widgets.rst Normal file
View file

@ -0,0 +1,186 @@
Widgets
=======
.. note::
Still under construction...
Immutable Widgets
-----------------
.. function:: Button(text, [options], x,y,w,h)
:param string text: Button label.
:param table options: Optional settings (see below).
:param numbers x,y: Upper left corner of the widget.
:param numbers w,h: Width and height of the widget.o
:returns: Return state (see below).
Creates a button widget at position ``(x,y)`` with width ``w`` and height
``h``.
.. function:: Label(text, [options], x,y,w,h)
:param string text: Label text.
:param table options: Optional settings (see below).
:param numbers x,y: Upper left corner of the widget.
:param numbers w,h: Width and height of the widget.o
:returns: Return state (see below).
Creates a label at position ``(x,y)`` with width ``w`` and height ``h``.
.. function:: ImageButton(options, x,y)
:param table options: Widget options.
:param numbers x,y: Upper left corner of the widget.
:returns: Return state (see below).
Creates an image button widget at position ``(x,y)``.
Unlike all other widgets, an ``ImageButton`` is not affected by the current
theme.
The options table must at least contain an image for the ``normal`` state.
The pixels with non-zero alpha value define the active area of the widget.
You can provide additional ``hot`` and ``active`` images, but the widget area
is always computed from the ``normal`` image.
Note that ``ImageButton`` does not recieve width and height parameters. As
such, it does not necessarily honor the cell size of a :doc:`layout`.
**Additional Options:**
``normal``
Image for the normal state of the widget. Mandatory.
``hot``
Image for the hot state of the widget. Defaults to ``normal`` if omitted.
``active``
Image for the active state of the widget. Defaults to ``
Mutable Widgets
---------------
.. function:: Checkbox(checkbox, [options], x,y,w,h)
:param table checkbox: Checkbox state.
:param table options: Optional settings (see below).
:param numbers x,y: Upper left corner of the widget.
:param numbers w,h: Width and height of the widget.o
:returns: Return state (see below).
Creates a checkbox at position ``(x,y)`` with width ``w`` and height ``h``.
**State:**
``checkbox`` is a table with the following components:
``checked``
``true`` if the checkbox is checked, ``false`` otherwise.
``text``
Optional label to show besides the checkbox.
.. function:: Slider(slider, [options], x,y,w,h)
:param table slider: Slider state.
:param table options: Optional settings (see below).
:param numbers x,y: Upper left corner of the widget.
:param numbers w,h: Width and height of the widget.o
:returns: Return state (see below).
Creates a slider at position ``(x,y)`` with width ``w`` and height ``h``.
Sliders can be horizontal (default) or vertical.
**State:**
``value``
Current value of the slider. Mandatory argument.
``min``
Minimum value of the slider. Defaults to ``min(value, 0)`` if omitted.
``max``
Maximum value of the slider. Defaults to ``min(value, 1)`` if omitted.
``step``
Value stepping for keyboard input. Defaults to ``(max - min)/10`` if omitted.
**Additional Options:**
``vertical``
Whether the slider is vertical or horizontal.
**Additional Return State:**
``changed``
``true`` when the slider value was changed, ``false`` otherwise.
.. function:: Input(input, [options], x,y,w,h)
:param table input: Checkbox state
:param table options: Optional settings (see below).
:param numbers x,y: Upper left corner of the widget.
:param numbers w,h: Width and height of the widget.o
:returns: Return state (see below).
Creates an input box at position ``(x,y)`` with width ``w`` and height ``h``.
Implements typical movement (arrow keys, home and end key) and editing
(deletion with backspace and delete) facilities.
**State:**
``text``
Current text inside the input box. Defaults to the empty string if omitted.
``cursor``
Cursor position. Defined as the position before the character (including
EOS), so ``1`` is the position before the first character, etc. Defaults to
the end of ``text`` if omitted.
**Additional Return State:**
``submitted``
``true`` when enter was pressed while the widget has keyboard focus.
Common Options
--------------
``id``
Identifier of the widget regarding user interaction. Defaults to the first
argument (e.g., ``text`` for buttons) if omitted.
``font``
Font of the label. Defaults to the current font (``love.graphics.getFont()``).
``align``
Horizontal alignment of the label. One of ``"left"``, ``"center"``, or
``"right"``. Defaults to ``"center"``.
``valign``
Vertical alignment of the label. On of ``"top"``, ``"middle"``, or
``"bottom"``. Defaults to ``"middle"``.
``color``
Table overwriting the color. Undefined colors default to the theme colors.
Common Return States
--------------------
``id``
Identifier of the widget.
``hit``
``true`` if the mouse was pressed and released on the button, ``false``
otherwise.
``hovered``
``true`` if the mouse is above the widget, ``false`` otherwise.
``entered``
``true`` if the mouse entered the widget area, ``false`` otherwise.
``left``
``true`` if the mouse left the widget area, ``false`` otherwise.