============================================================
How to write presentations using Bruce the Presentation Tool
============================================================

Bruce presentations are written as plain-text files in the
ReStructuredText format with some extensions. If you have
access to this HOWTO file in its original text format you
may view it using Bruce (the HTML version is produced using
the standard rst2html conversion tool.)

See the examples folder \*.rst files for some samples, the
simplest being "simple.rst" which displays plain text sentences
centered on a white background (using the "big-centered" style)::

    .. load-style:: big-centered

    Text displayed centered on the default white background.

    ----

    A new page, separated from the previous using the four
    dashes.

    Ut enim ad minim veniam.

    A Page Title
    ------------

    Pages may optionally have titles which are displayed
    centered at the top by default.

and so on. Blank pages are possible using ``.. blank::`` in place
of page content.

There's a lot of examples in the examples/ directory, showing off
most of Bruce's features.


More Detail
-----------

Pages in Bruce are defined as being the text contained in a section
or between transitions (horizontal rules, ``----``). It is important
that a blank surrounds the transition line, otherwise ReST might
try to interpret it as a title (which will often mean resulting in
a parsing error). See "examples/test_sectioning.rst" for a file
that mixes section-based and transition-based page delimiting.

There is also a "bullet mode" which treats each bullet point in a
top-level bullet list as a single page. See "examples/test_bullet_mode.rst"
for a file that uses this mode.

Bruce supports a large amount of ReStructuredText and some additional features:

- inline markup for emphasis, strong, superscript, subscript and literal
- literal blocks
- line blocks
- block quotes
- bullet and enumerated lists (including nesting)
- definition lists
- images - inline and stand-alone
- tables (though no row / column spanning yet)
- page titles (section headings)
- syntax highlighting of code if Pygments__ is installed
- interactive Python interpreter sessions
- styling
- backgrounds
- transitions between pages
- blank pages
- plugins to create your own inline elements

__ http://pygments.org/

**titles**
    Bruce will not line-wrap title text (doing so messes with layout way too much),
    so make sure your title fits in one line!

**images**
    A ``:width:`` and/or ``:height:`` may be specified to scale the image when displayed.
    If only one is specified then the image's other dimension will be scaled
    to ensure the image aspect ration is retained.

**tables**
    No row or column spanning is implemented yet. Tables may have pretty much
    any arbitrary content though.

**video**
    Embedded in the same manner as images, and may be scaled in the same way.
    Additionally video may be asked to loop using the ``:loop:`` flag.

**code**
    Syntax-highlighting of code blocks if Pygments is installed. The range of
    languages supported by Pygments is at http://pygments.org/docs/lexers/

**blank pages**
    The ``.. blank::`` directive allows you to have blank pages in place of
    page content, for example::

       Lorem ipsum dolor sit amet, consectetuer adipiscing elit.

       ----

       .. blank::

       ----

       Donec auctor vestibulum risus. Vestibulum porttitor purus sed magna.

**interpreter**
    Embeds a Python interpreter in the page. The options available are ``:width:`` and
    ``:height:`` (default 800 by 300). You may also have the optional flag ``:sysver:``
    which will cause the standard Python interactive intepreter greeting with the
    Python version to be displayed.

**plugins**
    Enables the author to compose a new inline element in Python code. See
    the section below on `writing plugins`_.


Style Changes
-------------

The rendering stylesheet may be altered on the fly using the ``.. style::``
directive. Changes made in this way are immediate and affect all subsequent
text. The exception to this is the "layout" style which applies to the
entire current and subsequent pages.

The stylesheet is broken up into sections: default, literal, emphasis, strong,
title, footer, block_quote, line_block, literal_block, layout and transition.

Default, title and footer may specify a horizontal alignment.

Default, literal_block and line_block may specify margin_left, margin_right,
margin_top and margin_bottom.

All sections except layout, transition and literal_block may specify character
styling in color, background_color, font_size, font_name, old and italic.

The layout section specifies the background_color and vertical alignment for
page contents.

The transition section specifies the name of the page transition and time
to run it for.

**color**
    Specified as an HTML-like RGB or RGBA hex value, eg. ``#ff00ff`` for red=255,
    green=0 and blue=255, ie. purple. May also use the common HTML color names
    like ``red``, ``white``, ``gray`` etc.
**background_color**
    Specified as per color above, indicates the color to place behind the text.
**font_size**
    Size in points of the font.
**font_name**
    Name of the font. Must be loadable using pyglet.resource.font, so must be
    discoverable using pyglet.resource. Use the inspect_font.py tool in the
    pyglet distribution to discover a font file's name and other attributes
    if you're not sure. You may add new fonts using the resource directive.
**bold**
    Use a font's bold variant. Use ``yes`` or ``no``.
**italic**
    Use a font's italic variant. Use ``yes`` or ``no``.
**alignment**
    One of ``left`` (default), ``center`` or ``right``.
**margin_left, margin_right, margin_top and margin_bottom**
    Margins surrounding paragraphs specified in pixels.
**valign**
    Only valid in the **layout** section; one of ``top`` (default), ``center``
    or ``bottom``.
**name**
    Only valid in the **transition** section; one of the `transition names`_
    listed below. Default is ``none``.
**duration**
    Only valid in the **transition** section; gives the duration in seconds
    to run the current transition for. Default is ``0.5``.

The default stylesheet contains::

    default.font_name = Arial
    default.font_size = 20
    default.margin_bottom = 12
    default.align = left
    default.color = black
    emphasis.italic = yes
    strong.bold = yes
    literal.font_name = Courier New
    literal.font_size = 20
    literal.background_color = #e0e0e0
    literal_block.margin_left = 20
    line_block.margin_left = 40
    block_quote.italic
    title.font_size = 28
    title.align = center
    title.bold = yes
    footer.font_size = 16
    footer.align = center
    footer.italic = yes
    layout.background_color = white
    layout.valign = top
    transition.name = none
    transition.duration = 0.5
    table.heading_background_color = #d2d2d2
    table.even_background_color = #f0f0f0
    table.odd_background_color = #f0f0f0
    table.cell_align = left
    table.cell_valign = top
    table.top_padding = 2
    table.bottom_padding = 2
    table.left_padding = 4
    table.right_padding = 4
    table.border = yes
    table.border_color = black
    code_keyword.color = #008000
    code_name.bold = yes
    code_name_class.bold = yes
    code_name_class.color = #baba21
    code_name_function.bold = yes
    code_name_function.color = #baba21
    code_literal.color = #ba2121
    code_operator.color = #666666
    code_comment.italic = yes
    code_comment.color = #404080

The "default" group is used as a fallback when a particular style is looked up and
no explicit attribute is set. Thus all text is rendered in ``Arial`` by default, except
in literal text where ``Courier New`` is used. You may set ``title.font_name`` to override
the font used in the title or ``default.font_name`` to override the font used everywhere
(except literal text). You may refer to defaults using bare style attributes, so
``default.font_name`` and ``font_name`` are both equivalent.

Style changes are specified using the style directive. To change the font to
64-point bold, you would::

   .. style::
      :font_size: 64
      :bold: yes

To change a single style element you may have the declaration on a single line::

   .. style:: :font_size: 64

The ``code_*`` style names control the output of the Pygments rendering so if
you've not got that installed you may ignore them. The complete set of names
is (with the ``code_`` prefix removed): ``keyword``, ``text``, ``generic``,
``name``, ``name_class``, ``name_function``, ``literal``, ``punctuation``,
``operator`` and ``comment``.


Transition Names
""""""""""""""""

none
  No transition effect. Immediate page change, no delay.
fade
  Fades to background color and then to next page.
jump_zoom
  Zoom out current page and zoom in new page.
shrink_grow
  Like jump_zoom but smoother.
roto_zoom
  Rotate and zoom our current page, rotate and zoom in new page.
move_in_left, move_in_right, move_in_bottom, move_in_top
  Move the next page in from the specified side.
slide_in_left, slide_in_right, slide_in_bottom, slide_in_top
  Slide the current page off and new page on from the specified side.

The following do not work on all machines:

- flip_x, flip_y, flip_angle
- shuffle
- turn_off_tiles
- fade_top_right, fade_bottom_left, fade_up, fade_down
- corner_move
- envelope
- split_rows, split_cols


Page Layout
-----------

The page layout may also be defined on the fly. Unlike the stylesheet
which may be modified, the page layout must be specified entirely with
each directive. The layout directive applies to the current and subsequent
pages. The layout also controls the placement of the page title.

A blank layout directive ``.. layout::`` will result in
the default layout having a white layout and the page title centered
at the top of the page.

Layout controls a few elements of display:

**title positioning**
   The position of the title is controlled here. The style of the title is controlled
   by the stylesheet. The title is specified as::

        title:x,y;hanchor;vanchor

   The default ``title`` is::

        title:w//2,h;center;top

   Which positions the title at the top-center of the viewport, anchored
   in the center/top of the text.

**footer positioning**
   The position of the footer is controlled here. The style of the footer is controlled
   by the stylesheet. The footer is specified as::

        footer:x,y;hanchor;vanchor

   The default ``footer`` is::

        footer:w,0;right;bottom

   Which positions the foorer at the bottom-right of the viewport, anchored
   in the right/bottom of the text.

**viewport**
   You may restrict the size of the display usable by pages. By default some space
   is allocated so the page contents don't overwrite the page title and footer, if they
   are present and positioned in the usual top and bottom places. The viewport is
   specified as::

        viewport:x,y,width,height

   Giving the bottom-left corner x,y position and the width and height.

**quad-based decoration**
   You may draw quads on the page which will appear under any content. The quads may
   have gradients by specifying different colors for each corner. The syntax for
   specifying a quad is::

        quad:C<color spec>;Vx1,y1;Vx2,y2;Vx3,y3;Vx4,y4

   Quad vertex color carries over if it's not specified for each vertex,
   allowing either solid color or blending.

   Colors are specified in HTML format with either three or four channels
   (if three then the fourth, alpha channel is set to 255).

All positions (quad vertexes, title position, etc) may be Python expressions which will
be evaluated. The expressions have the variables "w" and "h" available which are
the width and height of the presentation viewport. To center the title, for example,
the width could be specified as ``w//2``.

Which will divide the width by two producing an integer (always try to produce an
integer as it will result in more pleasing rendering).


Resource Discovery
------------------

Bruce can display images and video found in the same directory as the
presentation source. You may enable Bruce to search additional paths
to find images and video. Additionally you may load new fonts for display 
by referring to TrueType Font files. You do so using the ``.. resource::``
directive.

**adding a directory of resources**::

    .. resource:: <path to directory>

**adding a font file**::

    .. resource:: <font filename>.ttf

To refer to the font later you'll need to know its name, which may differ
from the filename. You may use the inspect_font.py tool in the pyglet
source to do so.


Writing Plugins
---------------

A plugin is used with the ``.. plugin::`` directive. For example::

    .. plugin:: test_plugin
       :width: 300
       :height: 300

The directive is referring to the plugin implemented in the file ``test_plugin.py``
which is found using normal `resource discovery`_. That file must contain:

1. a class called Plugin which derives from bruce.plugin.Plugin, and
2. an implementation of any or all of the methods described below.

If your plugin is animated you may request a regular tick from the clock by setting
the property needs_tick either on your class or in your __init__ method.

**__init__(self, width=800, height=400)__**
    Invoked when the presentation is parsed.
    Passed the width and height as specified in the presentation.

**resize(self, width, height)**
    Invoked when the page the element is on is scaled.

**place(self, layout, x, y)**
    Invoked when the page layout needs to position the element on screen. Passed a
    pyglet.text.IncrementalTextLayout instance and the pixel position of the bottom
    left of the element in that layout. This position almost always has a negative
    y value.

**remove(self, layout)**
    Invoked when page layout removes the element from display.

**tick(self, dt)**
    Invoked if the element defines needs_tick **before enter is invoked**.
    Will be called once per "clock tick" with dt being the time in seconds since
    the last call.

Plugin contents should be rendered using the pyglet.graphics API with the Batch
instance on the layout passed into the place() method.

Additionally any graphics elements added to the batch should use the group
layout.top_group as the base group. This group defines positioning transformations
without which your plugin content will most likely not be visible.

Again note you'll almost always receive a negative y position in the place() call.
The transforms in layout.top_group adjust for this (the top of the layout is typically
at y=0).

If you wish to alter the OpenGL context to turn on environment features such as
texturing, or even just to perform additional transformations then you should
define your own pyglet.graphics.Group. When you instantiate this group you should
then pass it layout.top_group.

The following is an example plugin file used in test_plugin.rst in Bruce's source::

    import pyglet
    from pyglet.gl import *

    from bruce import plugin

    class TestGroup(pyglet.graphics.Group):
        angle = 0

        def set_state(self):
            glPushMatrix()
            x, y = self.center
            glTranslatef(x, y, 0)
            glRotatef(self.angle, 0, 0, 1)
            glTranslatef(-x, -y, 0)

        def unset_state(self):
            glPopMatrix()

    class Plugin(plugin.Plugin):
        needs_tick = True
        def resize(self, w, h):
            self.w, self.h = w, h

        def tick(self, dt):
            self.group.angle += 1

        def place(self, layout, x, y):
            x1 = int(x)
            y1 = int(y)
            x2 = int(x + self.w)
            y2 = int(y + self.h)
            self.group = TestGroup(layout.top_group)
            self.group.center = (x+self.w/2, y+self.h/2)
            self.r = layout.batch.add(4, GL_QUADS, self.group,
                ('c3B', (255, 0, 0) * 4),
                ('v2i', (x1, y1, x2, y1, x2, y2, x1, y2)),
            )

        def remove(self, layout):
            self.r.delete()

