===============================
Play with the KezMenu's effects
===============================

Introduction
============

From version 0.3.0 the inner KezMenu structure is changed a lot. One of the first
news is that every line has it's own `pygame.font.Font`__ to use.

__ http://www.pygame.org/docs/ref/font.html#pygame.font.Font

This will give us a lot of freedom for menu's entries display effects.

   >>> import pygame
   >>> from pygame.locals import *
   >>> import pygame.font
   >>> pygame.font.init()
   >>> screen = pygame.display.set_mode((640,480), 0, 32)
   >>> screen.fill( (50,50,50,255) )
   <rect(0, 0, 640, 480)>

   >>> click_count = 0
   >>> def waitForUserAction(msg='???'):
   ...     global click_count
   ...     click_count+=1
   ...     pygame.display.set_caption("Example %s - %s" % (click_count, msg))
   ...     while True:
   ...         for event in pygame.event.get():
   ...             if event.type==KEYDOWN:
   ...                 return

   >>> def updateCaption(msg='???'):
   ...     global click_count
   ...     click_count+=1
   ...     pygame.display.set_caption("Example %s - %s" % (click_count, msg))

   >>> from kezmenu import KezMenu
   >>> def drawMenu():
   ...     screen.fill( (50,50,50,255) )
   ...     menu.draw(screen)
   ...     pygame.display.flip()

   >>> option_selected = 0
   >>> def optSelected():
   ...     global option_selected
   ...     option_selected=1

   >>> menu = KezMenu(
   ...            ["First option!", optSelected],
   ...            ["sEcond", optSelected],
   ...            ["Again!", optSelected],
   ...            ["Lambda", optSelected],
   ...            ["Quit", optSelected],
   ...        )
   >>> menu.font = pygame.font.Font(None, 20)
   >>> menu.color = (255,255,255)
   >>> menu.position = (10,10)

Lets show the actual menu height:
   
   >>> menu.height
   70

Here again a standard menu.

   >>> drawMenu()
   >>> waitForUserAction("The same boring menu")

Now we want a bigger font for 'sEcond' entry:

   >>> menu.options[1]['font'] = pygame.font.Font(None, 26)
   >>> drawMenu()
   >>> waitForUserAction("Bigger entry 2")

Lets who now that manually play with the options menu can lead to some errors
in the menu itself, because KezMenu instance is not warn of changed parameters:

   >>> menu.height
   70

So even if we display a new well drawn menu, the saved size is not changed.
This is bad. We can fix this simply calling an internal KezMenu method, that
commonly KezMenu objects call for us:

   >>> menu._fixSize()
   >>> menu.height
   74

This introduction was only a taste of what there's inside KezMenu effect's ways to do things.

The KezMenu available effects
=============================

Here a list and example of usage of all available effects.
Effects are enabled using the *enableEffect* method, and must be used for
existing effects, or a KeyError is raised:

   >>> menu.enableEffect('not-existing-effect-just-for-raise-error')
   Traceback (most recent call last):
   ...
   KeyError: "KezMenu don't know an effect of type not-existing-effect-just-for-raise-error"

In all the following example we need a timer, and so can use the
`pygame.time.Clock`__:

__ http://www.pygame.org/docs/ref/time.html#pygame.time.Clock

   >>> clock = pygame.time.Clock()

To enable an effect, we must use the *enableEffect* method, passing to it the
name of the effect and optionally some keyword arguments.

**Important thing**: effects can be (sometimes) combined!

raise-line-padding-on-focus
---------------------------

This effect raise the padding above and below the focused element while time
is passing. Padding on the last element will only raise the top padding.
Padding on the first element will only raise the bottom padding.

`padding`
    Default: 10px. The number of pixel that will be added above and below the
    selected menu entry.

`enlarge_time`
    Default: 500 millisec. Time needed (in seconds) to reach the max padding.

::

   >>> updateCaption('raise-line-padding-on-focus')
   >>> option_selected = 0
   >>> menu.enableEffect('raise-line-padding-on-focus')
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break

We can call this effect with new custom values:

   >>> updateCaption('raise-line-padding-on-focus (custom)')
   >>> option_selected = 0
   >>> menu.enableEffect('raise-line-padding-on-focus', padding=30, enlarge_time=1.)
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break
   >>> menu.disableEffect('raise-line-padding-on-focus')

raise-col-padding-on-focus
--------------------------

This effect raise the padding on the left of the focused element while time is
passing.

`padding`
    Default: 10px. The number of pixel that will be added on the left of the
    selected menu entry.

`enlarge_time`
    Default: 500 millisec. Time needed (in seconds) to reach the max padding.

::

   >>> updateCaption('raise-col-padding-on-focus')
   >>> option_selected = 0
   >>> menu.enableEffect('raise-col-padding-on-focus')
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break

We can call this effect with new custom values:

   >>> updateCaption('raise-col-padding-on-focus (custom)')
   >>> option_selected = 0
   >>> menu.enableEffect('raise-col-padding-on-focus', padding=20, enlarge_time=3.)
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break
   >>> menu.disableEffect('raise-col-padding-on-focus')

enlarge-font-on-focus
---------------------

This effect will raise the font size of the selected element on the menu of a
given multiply factor. The Font class of Pygame has a limitation (not a bug):
is not possible to obtain the font data (family, size) after the font creation.

So for use this effect is needed to pass to the init method all font data, and
a new font will be created (the standard menu 'font' property will be
overrided).

`font`
    Required. A font name of path, same as you are passing it to Pygame
    Font constructor, so can also be None.

`size`
    Required. The size of the font, same as you are passing it to Pygame Font
    constructor.

`enlarge_factor`
    Default: 2.(200%). The multiply factor of the font size at the maximum
    extension, as a real value.

`enlarge_time`
    Default: 500 millisec. Time needed (in seconds) to reach the max font
    size.

::

   >>> updateCaption('enlarge-font-on-focus')
   >>> option_selected = 0
   >>> menu.enableEffect('enlarge-font-on-focus', font=None, size=18)
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break

Lets now customized all the data:

   >>> updateCaption('enlarge-font-on-focus (focus)')
   >>> option_selected = 0
   >>> menu.enableEffect('enlarge-font-on-focus', font=None, size=18, enlarge_factor=5., enlarge_time=2.)
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break
	>>> menu.disableEffect('enlarge-font-on-focus')

Combining KezMenu effects
=========================

The primary scope of KezMenu effects is to be enough flexible to be activated
in same time.
As the effects available will raise in future, sometimes can be that effects
will fall in conflict each other, but in general I'll try to integrate them.

Activate more that one effects in the same time is very simple: just activate it!

   >>> updateCaption('Combined effects example')
   >>> option_selected = 0
   >>> menu.enableEffect('raise-line-padding-on-focus', padding=30, enlarge_time=1.)
   >>> menu.enableEffect('raise-col-padding-on-focus', padding=20, enlarge_time=1.)
   >>> menu.enableEffect('enlarge-font-on-focus', font=None, size=16, enlarge_factor=3.)
   >>> while True:
   ...     time_passed = clock.tick() / 1000.
   ...     events = pygame.event.get()
   ...     menu.update(events, time_passed)
   ...     drawMenu()
   ...     if option_selected:
   ...         break
   >>> menu.disableEffect('raise-line-padding-on-focus')
   >>> menu.disableEffect('raise-col-padding-on-focus')
   >>> menu.disableEffect('enlarge-font-on-focus')

Wanna write a new effect?
=========================

If anyone is interested in develop a new effect, I will be happy to integrate
it in KezMenu!
