Skip to content

Commit

Permalink
Doc. [ci skip]
Browse files Browse the repository at this point in the history
  • Loading branch information
skaller committed Nov 24, 2017
1 parent 7537618 commit 541d36c
Show file tree
Hide file tree
Showing 4 changed files with 363 additions and 0 deletions.
72 changes: 72 additions & 0 deletions doc/tutorial/gui01.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
==================================
Getting Started With the Felix GUI
==================================

Felix comes with a library to create platform
independent graphical user interfaces. It uses
the Simple Direct Media Layer, version 2, SDL2
system with add-ons to do this.

SDL2 runs on Linux, OSX, Windows, iOS and Android
and is designed for implementation of portable games.

Installation
============

For the Felix GUI to work, *development versions* of
the following components must be installed:

.. code-block:: text
SDL2
SDL2_image
SDL2_ttf
SDL2_gfx
On Linux using apt package manager do this:

.. code-block:: text
sudo apt-get install libsdl2-dev
sudo apt-get install libsdl2_image-dev
sudo apt-get install libsdl2_ttf-dev
sudo apt-get install libsdl2_gfx-dev
Felix already contains database entries for these
packages, but at the time of writing this tutorial,
the libraries are expected to be in `/usr/local`
which is where you would put them if you built them yourself.

However Debian filesystem layout standards used by Linux OS
such as Ubuntu that use `apt` package manager put components
in `/usr/` instead. So unfortunately you will have to modify the
database by hand by editing these files

.. code-block:: text
build/release/host/config/sdl2.fpc
build/release/host/config/sdl2_image.fpc
build/release/host/config/sdl2_ttf.fpc
replacing `/usr/local` with just `/usr`. To preserved these modifications
across upgrades, you should also copy the files:

.. code-block:: bash
cp build/release/host/config/sdl2.fpc $HOME/.felix/config
cp build/release/host/config/sdl2_image.fpc $HOME/.felix/config
cp build/release/host/config/sdl2_ttf.fpc $HOME/.felix/config
I hope this problem can be reduced in future versions, but it is
likely to be an issue for some time because most developers will have
a libraries installed in both places, depending on whether they're
using a package manager to install them, or building from source.

To check your installation works, do this:

.. code-block:: bash
make tutopt-check
and a series of tests will run which use the Felix GUI and SDL2.

139 changes: 139 additions & 0 deletions doc/tutorial/gui02.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
GUI Basics
==========

We will now show how to do basic GUI programming.
The first thing we want to do is open a window!

.. code-block:: felix
include "gui/__init__";
open FlxGui;
println$ "Basic Window Test";
FlxGui::init();
var w = create_resizable_window("Felix:gui_01_window_01",100,100,400,400);
w.add$ mk_drawable FlxGuiSurface::clear lightgrey;
w.update();
w.show();
sleep(15.0);
The Felix gui is not included by default, so we have to first
include the library with

.. code-block:: felix
include "gui/__init__";
Although this makes the library available, we would have to prefix
the names of all functions in the library with :code:`FlxGui::` to use them.
Since programmers hate typing stuff, we will open the library, so the
functions are all in the current scope and can be used without
the prefix.

.. code-block:: felix
open FlxGui;
Next, we will print a diganostic to standard output so we know
which program is running, and then initialise library.
Initialisation is a requirement imposed by SDL, which has a lot
of work to do on some platforms to connect to the GUI devices
such as the screen, touch (haptic) inputs, joysticks, mice,
keyboards, audio, and other multi-media hardware.

.. code-block:: felix
println$ "Basic Window Test";
FlxGui::init();
Now it it time for the fun! We will create a resizable window:

.. code-block:: felix
var w = create_resizable_window("Felix:gui_01_window_01",100,100,400,400);
The first parameter is the title of the window, which should appear
on the titlebar (it doesn't on OSX! Because there is no pause to
accept input).

The next four parameters describe the window geometry.
The first two are the x and y coordinates. The SDL coordinate
system puts the origin in the top left corner, and x increases
down the screen.

The unit of measurement is approximately the pixel.
I say approximately because on a Mac with a Retina display,
each pixel is often four displayt elements on the screen.
To confuse the issue, the Mac can do hardware scaling.
You'll just have to experiment!

The second two values are the width and height
of the window's client area, this does not include the title bar.
However the x and y coordinates are the top left corner of the
whole window including the title bar!

What we have created is a data structure representing the window.
The next thing we want to do is put some coloured pixels in it.

.. code-block:: felix
w.add$ mk_drawable FlxGuiSurface::clear lightgrey;
This is an example of a fundamental operation, to add to a windows
display surface, the commands for drawing something.

The :code:`w.add` method adds a *drawable* to a list of drawables
kept for window :code:`w`.

The :code:`mk_drawable` method is a function which constructs a
drawable object. Its first argument is the actual drawing command,
:code:`FlxGuiSurface::clear` which clears a whole surface.
The second argument is an argument to that command, in this
case :code:`lightgrey`, which tells the clearing command what
colour to write on the surface it is clearing.

We have not actually drawn on the window at the point.
What we have done is packaged up the drawing instructions,
and *scheduled* them for drawing later.

To actually draw, we do this:

.. code-block:: felix
w.update();
Now we have drawn the objects we scheduled to be drawn
on the systems internal representation of the window's
surface but still, nothing appears on the screen!

This is because the window has not be shown yet.
We've been drawing on it whilst it was invisible.
So we now make it visible:


.. code-block:: felix
w.show();
FInally, we want the window to hang around for 15 seconds so
you can admire your fine art work.

.. code-block:: felix
sleep(15.0);
This causes the program to sleep for 15 seconds. The argument
is a double precision floating point number representing
a delay in seconds. The decimal point is mandatory and trailing
zero is mandatory!









149 changes: 149 additions & 0 deletions doc/tutorial/gui03.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
Putting Stuff in the Window
===========================

Now we have created a window, we want to put stuff on it!

.. code-block:: felix
include "gui/__init__";
open FlxGui;
println$ "Basic Drawing Test";
FlxGui::init();
var w = create_resizable_window("Felix:gui_03_draw_01",100,100,400,600);
w.add$ mk_drawable FlxGui::clear lightgrey;
var font_name = dflt_sans_serif_font();
var font : font_t = get_font(font_name, 12);
var lineskip = get_lineskip font;
w.add$ mk_drawable FlxGui::write (10,10,font,black,"Basic Drawing Test");
fun / (x:string, y:string) => Filename::join (x,y);
var imgfile = #Config::std_config.FLX_SHARE_DIR / "src" / "web" / "images" / "FelixWork.jpg";
var ppic : surface_t = surface (IMG_Load imgfile.cstr);
w.add$ mk_drawable blit (20,20, ppic.get_sdl_surface ());
w.add$ mk_drawable draw_line (RGB(0,0,255), 100,110,200,110);
w.add$ mk_drawable draw_line (RGB(0,0,255), 100,210,200,210);
w.add$ mk_drawable draw_line (RGB(0,0,255), 100,110,100,210);
w.add$ mk_drawable draw_line (RGB(0,0,255), 200,110,200,210);
w.update();
w.show();
sleep(15.0);
Here, the program is as before, except we now do three basic
ways to draw on a window.

First, we want to be able to put ordinary text on the window.
To do that, we have to first create a font to write the text
with:

.. code-block:: felix
var font_name = dflt_sans_serif_font();
var font : font_t = get_font(font_name, 12);
var lineskip = get_lineskip font;
The first line gets the name of a default sans serif font
file which is packaged with Felix so you don't have to figure
out where all the fonts on your system are.

The second line actually creates the font from the file
at a particular size, in this case 12 point. The size is
a conventional printers measure. You'll just have to get used
to what it means!

The third line helps tell how big the font it. We retrieve
from the font the distance in pixels we should allow
between lines, for readable text. Anything less and
the characters would bump into each other.

Now we have a font, we schedule drawing some text on the window:

.. code-block:: felix
w.add$ mk_drawable FlxGui::write (10,10,font,black,"Basic Drawing Test");
This is our usual machinery for adding a drawable object to the
windows list of drawables, to be drawn when we say to `update`.
The drawing function is :code:`FlxGui::write`. Notice we used
the fully qualified name of the function, to avoid confusiuon
with other functions named `write`.

The argument to write is the x and y coordinates of the initial
base point, the font to use, the colour to write in, and the
actual text to write.

Text is always written with respect to a base point.
The base point is origin of the first character which is
approximately the left edge of the character, and the
point at which an invisible underline would occur:
in other words, under the main body of the character,
but on top of any descender that letter like `g` have.

The exact location is font dependent. Font rendering
is an arcane art, not an exact science so you will have
to practice to get text to appear where you it has
the correct visual significance.


Now we are going to put a picture in the window.
The image is a JPEG image, and is supplied for testing
purposed in Felix at a known location.

First we define a little helper function:

.. code-block:: felix
fun / (x:string, y:string) => Filename::join (x,y);
What this says is that when we try to divide one string
by another string, we actually mean to join the strings
together using :code:`Filename::join` which is a standard
function which sticks a `/` character between strings on unix
platforms, and a slosh on Windows.

The file is here:

.. code-block:: felix
var imgfile = #Config::std_config.FLX_SHARE_DIR / "src" / "web" / "images" / "FelixWork.jpg";
The prefix of this code finds the share subdirectory of the
Felix installation, which contains the picture we went in the
images subdirectory of the web subdirectory of the src subdirectory.


Now to schedule the drawing we do this:

.. code-block:: felix
var ppic : surface_t = surface (IMG_Load imgfile.cstr);
w.add$ mk_drawable blit (20,20, ppic.get_sdl_surface ());
The first line loads the image file into memoy using a low
level primitive from SDL2_image. That primitve requires
a C char pointer, not a C++ string, which is what Felix uses,
so we use :code:`cstr` to convert. Then the `surface` function
translates the loaded file into an SDL surface object.

In the second line we add the drawable to the window based
on the :code:`blit` function. This copies one surface to another.
We copy the image surface to the window surface at position 20,20
in the window, and use the :code:`get_sdl_surface()` method to
translate the Felix surface object into a lower level SDL surface.

Its all a bit mysterious, so you just have to so some thing
by copying the patterns that work.

Finally, we draw a blue rectangle on top of the picture.
I'm sure you can figure out how that works!




3 changes: 3 additions & 0 deletions doc/tutorial/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ Contents:

hello
pythagoras
gui01
gui02
gui03

Indices and tables
==================
Expand Down

0 comments on commit 541d36c

Please sign in to comment.