Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPootle daemon <pootle@pootle.sugarlabs.org>2012-04-21 04:33:16 (GMT)
committer Pootle daemon <pootle@pootle.sugarlabs.org>2012-04-21 04:33:16 (GMT)
commit09b59ae41764bc46cb4ca49befd696fee4613dfa (patch)
treecc9205580de0592e55eb5e3926aaa35871022438
parentb84bd17d2dd2c0c92f26af787802dd325526f912 (diff)
parent92183f99594e935abad1fff0ccb80043d5f8ddc8 (diff)
Merge branch 'master' of git.sugarlabs.org:visualmatch/mainline
-rw-r--r--NEWS15
-rw-r--r--VisualMatchActivity.py170
-rw-r--r--activity/activity.info2
-rw-r--r--game.py420
-rw-r--r--grid.py5
-rw-r--r--helpbutton.py124
-rw-r--r--icons/help-toolbar.svg18
-rw-r--r--images/help-11.svg145
-rw-r--r--images/help-12.svg145
-rw-r--r--images/help-13.svg145
-rw-r--r--images/help-14.svg145
-rw-r--r--images/help-15.svg145
-rw-r--r--images/help-16.svg145
-rw-r--r--images/help-17.svg145
-rw-r--r--images/help-18.svg145
-rw-r--r--images/help-19.svg145
-rw-r--r--images/help-20.svg145
-rw-r--r--images/help-21.svg170
-rwxr-xr-xvisualmatch.py10
19 files changed, 2145 insertions, 239 deletions
diff --git a/NEWS b/NEWS
index 19d46dc..8c12fb7 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+37
+
+BUG FIX:
+* Fixed typo that prevented help animation from terminating
+
+ENHANCEMENT:
+* Autoadvance levels when play improves
+
36
ENHANCEMENTS:
@@ -6,7 +14,14 @@ ENHANCEMENTS:
* Cursor when editing cards
* New help animation on first load
* Copy scores to clipboard (for import into Simple Graph)
+* Notification when loading new games
+* Slight delay after match before dealing new cards to allow for some
+ scrutiny of results
+* Addition of toolbar help menus
+* Rebranding as Dimensions (a more apt name)
+* Updated wiki page (See http://wiki.sugarlabs.org/go/Activities/Dimensions)
* New translations
+(Tip of the hat to Mark Battley for great feedback and suggestions.)
35
diff --git a/VisualMatchActivity.py b/VisualMatchActivity.py
index 399dd87..d6f7ebc 100644
--- a/VisualMatchActivity.py
+++ b/VisualMatchActivity.py
@@ -1,4 +1,4 @@
-#Copyright (c) 2009,10 Walter Bender
+#Copyright (c) 2009-12 Walter Bender
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@ if _NEW_SUGAR_SYSTEM:
from sugar.activity.widgets import ActivityToolbarButton
from sugar.activity.widgets import StopButton
from sugar.graphics.toolbarbox import ToolbarButton
-
+from sugar.graphics.alert import NotifyAlert
from sugar.datastore import datastore
import telepathy
@@ -33,6 +33,7 @@ from dbus.service import signal
from dbus.gobject_service import ExportedGObject
from sugar.presence import presenceservice
from sugar.presence.tubeconn import TubeConnection
+from sugar.graphics import style
from gettext import gettext as _
import os.path
@@ -58,10 +59,13 @@ from toolbar_utils import radio_factory, button_factory, label_factory, \
from constants import DECKSIZE, PRODUCT, HASH, ROMAN, WORD, CHINESE, MAYAN, \
INCAN, DOTS, STAR, DICE, LINES, DEAL
-
+from helpbutton import HelpButton, add_section, add_paragraph, help_windows, \
+ help_buttons
from game import Game
+help_palettes = {}
+
BEGINNER = 2
INTERMEDIATE = 0
EXPERT = 1
@@ -76,6 +80,11 @@ SERVICE = 'org.sugarlabs.VisualMatchActivity'
IFACE = SERVICE
PATH = '/org/augarlabs/VisualMatchActivity'
+PROMPT_DICT = {'pattern': _('New pattern game'),
+ 'number': _('New number game'),
+ 'word': _('New word game'),
+ 'custom': _('Import custom cards')}
+
class VisualMatchActivity(activity.Activity):
''' Dimension matching game '''
@@ -83,10 +92,10 @@ class VisualMatchActivity(activity.Activity):
''' Initialize the Sugar activity '''
super(VisualMatchActivity, self).__init__(handle)
+ self._prompt = ''
self._read_journal_data()
- datapath = self._find_datapath(activity)
self._setup_toolbars(_NEW_SUGAR_SYSTEM)
- canvas = self._setup_canvas(datapath)
+ canvas = self._setup_canvas()
self._setup_presence_service()
if not hasattr(self, '_saved_state'):
@@ -108,6 +117,8 @@ class VisualMatchActivity(activity.Activity):
if self.vmw.joiner(): # joiner cannot change level
return
self.vmw.card_type = card_type
+ self._prompt = PROMPT_DICT[card_type]
+ self._notify_new_game(self._prompt)
if card_type == 'custom' and self.vmw.custom_paths[0] is None:
self.image_import_cb()
else:
@@ -130,6 +141,7 @@ class VisualMatchActivity(activity.Activity):
if self.vmw.joiner(): # joiner cannot change level
return
self.vmw.level = level
+ self._notify_new_game(self._prompt)
self.set_level_label()
def set_level_label(self):
@@ -161,6 +173,7 @@ class VisualMatchActivity(activity.Activity):
return
self.vmw.numberO = numberO
self.vmw.card_type = 'number'
+ self._notify_new_game(self._prompt)
self.vmw.new_game()
def _number_card_C_cb(self, button, numberC):
@@ -169,6 +182,7 @@ class VisualMatchActivity(activity.Activity):
return
self.vmw.numberC = numberC
self.vmw.card_type = 'number'
+ self._notify_new_game(self._prompt)
self.vmw.new_game()
def _robot_time_spin_cb(self, button):
@@ -231,29 +245,11 @@ class VisualMatchActivity(activity.Activity):
'custom_' + str(i), None))
def _write_scores_to_clipboard(self, button=None):
- '''
- before = '{"chart_line_color": "#00588C", "title": \
-"%s", "x_label": "", "y_label": "", "chart_data": ' % (self.metadata['title'])
- scores = []
- for i, s in enumerate(self.vmw.all_scores):
- scores.append(['%s' % str(i + 1), s])
- jscores = self._data_dumper(scores)
- after = ', "chart_color": "#00A0FF", "current_chart.type": "line"}'
- _logger.debug(before + jscores + after)
- gtk.Clipboard().set_text(before + jscores + after)
- '''
+ ''' SimpleGraph will plot the cululative results '''
jscores = ''
for i, s in enumerate(self.vmw.all_scores):
jscores += '%s: %s\n' % (str(i + 1), s)
- gtk.Clipboard().set_text(before + jscores + after)
-
- def _find_datapath(self, activity):
- ''' Find the datapath for saving card files. '''
- if hasattr(activity, 'get_activity_root'):
- return os.path.join(activity.get_activity_root(), 'data')
- else:
- return os.path.join(os.environ['HOME'], '.sugar', 'default',
- SERVICE, 'data')
+ gtk.Clipboard().set_text(jscores)
def _setup_toolbars(self, new_sugar_system):
''' Setup the toolbars.. '''
@@ -264,49 +260,54 @@ class VisualMatchActivity(activity.Activity):
if new_sugar_system:
toolbox = ToolbarBox()
- activity_button = ActivityToolbarButton(self)
+ self.activity_toolbar_button = ActivityToolbarButton(self)
- toolbox.toolbar.insert(activity_button, 0)
- activity_button.show()
+ toolbox.toolbar.insert(self.activity_toolbar_button, 0)
+ self.activity_toolbar_button.show()
- games_toolbar_button = ToolbarButton(
+ self.game_toolbar_button = ToolbarButton(
page=games_toolbar,
icon_name='new-game')
games_toolbar.show()
- toolbox.toolbar.insert(games_toolbar_button, -1)
- games_toolbar_button.show()
+ toolbox.toolbar.insert(self.game_toolbar_button, -1)
+ self.game_toolbar_button.show()
- numbers_toolbar_button = ToolbarButton(
+ self.numbers_toolbar_button = ToolbarButton(
page=numbers_toolbar,
icon_name='number-tools')
numbers_toolbar.show()
- toolbox.toolbar.insert(numbers_toolbar_button, -1)
- numbers_toolbar_button.show()
+ toolbox.toolbar.insert(self.numbers_toolbar_button, -1)
+ self.numbers_toolbar_button.show()
- tools_toolbar_button = ToolbarButton(
+ self.tools_toolbar_button = ToolbarButton(
page=tools_toolbar,
icon_name='view-source')
tools_toolbar.show()
- toolbox.toolbar.insert(tools_toolbar_button, -1)
- tools_toolbar_button.show()
+ toolbox.toolbar.insert(self.tools_toolbar_button, -1)
+ self.tools_toolbar_button.show()
self._set_labels(toolbox.toolbar)
separator_factory(toolbox.toolbar, True, False)
+ help_button = HelpButton(self)
+ toolbox.toolbar.insert(help_button, -1)
+ help_button.show()
+ self._setup_toolbar_help()
+
stop_button = StopButton(self)
stop_button.props.accelerator = '<Ctrl>q'
toolbox.toolbar.insert(stop_button, -1)
stop_button.show()
export_scores = button_factory(
- 'score-copy', activity_button,
+ 'score-copy', self.activity_toolbar_button,
self._write_scores_to_clipboard,
tooltip=_('Export scores to clipboard'))
self.set_toolbar_box(toolbox)
toolbox.show()
- games_toolbar_button.set_expanded(True)
+ self.game_toolbar_button.set_expanded(True)
else:
toolbox = activity.ActivityToolbox(self)
self.set_toolbox(toolbox)
@@ -318,16 +319,16 @@ class VisualMatchActivity(activity.Activity):
self.button_pattern = button_factory(
'new-pattern-game', games_toolbar, self._select_game_cb,
- cb_arg='pattern', tooltip=_('New pattern game'))
+ cb_arg='pattern', tooltip=PROMPT_DICT['pattern'])
self.button_number = button_factory(
'new-number-game', games_toolbar, self._select_game_cb,
- cb_arg='number', tooltip=_('New number game'))
+ cb_arg='number', tooltip=PROMPT_DICT['number'])
self.button_word = button_factory(
'new-word-game', games_toolbar, self._select_game_cb,
- cb_arg='word', tooltip=_('New word game'))
+ cb_arg='word', tooltip=PROMPT_DICT['word'])
self.button_custom = button_factory(
'no-custom-game', games_toolbar, self._select_game_cb,
- cb_arg='custom', tooltip=_('Import custom cards'))
+ cb_arg='custom', tooltip=PROMPT_DICT['custom'])
if new_sugar_system:
self._set_extras(games_toolbar, games_toolbar=True)
@@ -490,7 +491,7 @@ class VisualMatchActivity(activity.Activity):
separator_factory(toolbar, False, True)
self.clock_label = label_factory(toolbar, '-')
- def _setup_canvas(self, datapath):
+ def _setup_canvas(self):
''' Create a canvas.. '''
canvas = gtk.DrawingArea()
canvas.set_size_request(gtk.gdk.screen_width(),
@@ -499,7 +500,7 @@ class VisualMatchActivity(activity.Activity):
canvas.show()
self.show_all()
- self.vmw = Game(canvas, datapath, self)
+ self.vmw = Game(canvas, self)
self.vmw.level = self._play_level
LEVEL_BUTTONS[self._play_level].set_active(True)
self.vmw.card_type = self._card_type
@@ -615,6 +616,85 @@ class VisualMatchActivity(activity.Activity):
io = StringIO(data)
return jload(io)
+ def _notify_new_game(self, prompt):
+ ''' Called from New Game button since loading a new game can
+ be slooow!! '''
+ alert = NotifyAlert(3)
+ alert.props.title = prompt
+ alert.props.msg = _('A new game is loading.')
+
+ def _notification_alert_response_cb(alert, response_id, self):
+ self.remove_alert(alert)
+
+ alert.connect('response', _notification_alert_response_cb, self)
+ self.add_alert(alert)
+ alert.show()
+
+ def _new_help_box(self, name, button=None):
+ help_box = gtk.VBox()
+ help_box.set_homogeneous(False)
+ help_palettes[name] = help_box
+ if button is not None:
+ help_buttons[name] = button
+ help_windows[name] = gtk.ScrolledWindow()
+ help_windows[name].set_size_request(
+ int(gtk.gdk.screen_width() / 3),
+ gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 3)
+ help_windows[name].set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+ help_windows[name].add_with_viewport(help_palettes[name])
+ help_palettes[name].show()
+ return help_box
+
+ def _setup_toolbar_help(self):
+ ''' Set up a help palette for the main toolbars '''
+ help_box = self._new_help_box('custom-toolbar',
+ self.tools_toolbar_button)
+ add_section(help_box, _('Tools'), icon='view-source')
+ add_section(help_box, _('Edit word lists.'), icon='word-tools')
+ add_section(help_box, _('Import image cards'), icon='image-tools')
+
+ help_box = self._new_help_box('activity-toolbar',
+ self.activity_toolbar_button)
+ add_section(help_box, _('Visual Match'), icon='activity-visualmatch')
+ add_paragraph(help_box, _('Export scores to clipboard'), icon='score-copy')
+
+ help_box = self._new_help_box('game-toolbar',
+ self.game_toolbar_button)
+ add_section(help_box, _('Game'), icon='new-game')
+ add_paragraph(help_box, PROMPT_DICT['pattern'], icon='new-pattern-game')
+ add_paragraph(help_box, PROMPT_DICT['number'], icon='new-number-game')
+ add_paragraph(help_box, PROMPT_DICT['word'], icon='new-word-game')
+ add_paragraph(help_box, PROMPT_DICT['custom'], icon='new-custom-game')
+ add_paragraph(help_box, _('Play with the computer'), icon='robot-off')
+ add_paragraph(help_box, _('robot pause time'))
+ add_paragraph(help_box, _('beginner'), icon='beginner')
+ add_paragraph(help_box, _('intermediate'), icon='intermediate')
+ add_paragraph(help_box, _('expert'), icon='expert')
+
+ help_box = self._new_help_box('numbers-toolbar',
+ self.numbers_toolbar_button)
+ add_section(help_box, _('Numbers'), icon='number-tools')
+ add_paragraph(help_box, _('product'), icon='product')
+ add_paragraph(help_box, _('Roman numerals'), icon='roman')
+ add_paragraph(help_box, _('word'), icon='word')
+ add_paragraph(help_box, _('Chinese'), icon='chinese')
+ add_paragraph(help_box, _('Mayan'), icon='mayan')
+ add_paragraph(help_box, _('Quipu'), icon='incan')
+ add_paragraph(help_box, _('hash marks'), icon='hash')
+ add_paragraph(help_box, _('dots in a circle'), icon='dots')
+ add_paragraph(help_box, _('points on a star'), icon='star')
+ add_paragraph(help_box, _('dice'), icon='dice')
+ add_paragraph(help_box, _('dots in a line'), icon='lines')
+
+ help_box = self._new_help_box('main-toolbar')
+ add_section(help_box, _('Visual Match'), icon='activity-visualmatch')
+ add_paragraph(help_box, _('Game'), icon='new-game')
+ add_paragraph(help_box, _('Numbers'), icon='number-tools')
+ add_paragraph(help_box, _('Tools'), icon='view-source')
+ add_paragraph(help_box, _('number of cards remaining in deck'))
+ add_paragraph(help_box, _('number of matches'))
+ add_paragraph(help_box, _('elapsed time'))
+
def _setup_presence_service(self):
''' Setup the Presence Service. '''
self.pservice = presenceservice.get_instance()
diff --git a/activity/activity.info b/activity/activity.info
index df3b0e4..674b39c 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,7 +1,7 @@
[Activity]
#TRANS: Please translate Visual Match as Dimensions
name = Visual Match
-activity_version = 36
+activity_version = 37
license = GPLv3
bundle_id = org.sugarlabs.VisualMatchActivity
exec = sugar-activity VisualMatchActivity.VisualMatchActivity
diff --git a/game.py b/game.py
index 6995524..ff5ef4f 100644
--- a/game.py
+++ b/game.py
@@ -43,9 +43,6 @@ from constants import LOW, MEDIUM, HIGH, MATCHMASK, ROW, COL, \
NOISE_KEYS, WORD_CARD_MAP, KEYMAP, CARD_HEIGHT, CARD_WIDTH, DEAL, \
DIFFICULTY_LEVEL, BACKGROUNDMASK, DECKSIZE, CUSTOM_CARD_INDICIES
-CURSOR = '█'
-
-
from grid import Grid
from deck import Deck
from card import Card
@@ -54,6 +51,8 @@ from gencards import generate_match_card, \
generate_smiley, generate_frowny_texture, generate_frowny_shape, \
generate_frowny_color, generate_frowny_number
+CURSOR = '█'
+
def _distance(pos1, pos2):
''' simple distance function '''
@@ -86,7 +85,7 @@ def _construct_a_name(before, i, after):
class Click():
- ''' A class to hold a clicked card '''
+ ''' A simple class to hold a clicked card '''
def __init__(self):
self.spr = None
@@ -106,65 +105,71 @@ class Click():
class Game():
''' The game play -- called from within Sugar or GNOME '''
- def __init__(self, canvas, path, parent=None):
+ def __init__(self, canvas, parent=None):
''' Initialize the playing surface '''
- self.path = path
self.activity = parent
if parent is None: # Starting from command line
- self.sugar = False
- self.canvas = canvas
+ self._sugar = False
+ self._canvas = canvas
else: # Starting from Sugar
- self.sugar = True
- self.canvas = canvas
+ self._sugar = True
+ self._canvas = canvas
parent.show_all()
- self.canvas.set_flags(gtk.CAN_FOCUS)
- self.canvas.connect('expose-event', self._expose_cb)
- self.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK)
- self.canvas.connect('button-press-event', self._button_press_cb)
- self.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
- self.canvas.connect('button-release-event', self._button_release_cb)
- self.canvas.add_events(gtk.gdk.POINTER_MOTION_MASK)
- self.canvas.connect("motion-notify-event", self._mouse_move_cb)
- self.canvas.connect('key_press_event', self._keypress_cb)
- self.width = gtk.gdk.screen_width()
- self.height = gtk.gdk.screen_height() - GRID_CELL_SIZE
- self.scale = 0.8 * self.height / (CARD_HEIGHT * 5.5)
- self.card_width = CARD_WIDTH * self.scale
- self.card_height = CARD_HEIGHT * self.scale
+ self._canvas.set_flags(gtk.CAN_FOCUS)
+ self._canvas.connect('expose-event', self._expose_cb)
+ self._canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ self._canvas.connect('button-press-event', self._button_press_cb)
+ self._canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
+ self._canvas.connect('button-release-event', self._button_release_cb)
+ self._canvas.add_events(gtk.gdk.POINTER_MOTION_MASK)
+ self._canvas.connect("motion-notify-event", self._mouse_move_cb)
+ self._canvas.connect('key_press_event', self._keypress_cb)
+ self._width = gtk.gdk.screen_width()
+ self._height = gtk.gdk.screen_height() - GRID_CELL_SIZE
+ self._scale = 0.8 * self._height / (CARD_HEIGHT * 5.5)
+ self._card_width = CARD_WIDTH * self._scale
+ self._card_height = CARD_HEIGHT * self._scale
self.custom_paths = [None, None, None, None, None, None, None, None,
None]
- self.sprites = Sprites(self.canvas)
- self.press = None
- self.match_display_area = []
+ self._sprites = Sprites(self._canvas)
+ self._press = None
+ self.matches = 0
+ self.robot_matches = 0
+ self._match_display_area = []
self._matches_on_display = False
- self.smiley = []
- self.frowny = []
- self.help = []
+ self._smiley = []
+ self._frowny = []
+ self._help = []
self._failure = None
self.clicked = []
self.last_click = None
- self.dragpos = [0, 0]
- self.startpos = [0, 0]
+ self._drag_pos = [0, 0]
+ self._start_pos = [0, 0]
self.low_score = [-1, -1, -1]
self.all_scores = []
- self.robot = False
+ self.robot = False
+ self.robot_time = 0
+ self.total_time = 0
self.numberC = 0
self.numberO = 0
self.word_lists = None
self.editing_word_list = False
self.editing_custom_cards = False
- self.edit_card = None
- self.dead_key = None
+ self._edit_card = None
+ self._dead_key = None
self._found_a_match = False
+ self.level = 0
+ self.card_type = 'pattern'
+ self.buddies = []
def new_game(self, saved_state=None, deck_index=0):
''' Start a new game '''
# If we were editing the word list, time to stop
self.editing_word_list = False
self.editing_custom_cards = False
- self.edit_card = None
+ self._edit_card = None
# If there is already a deck, hide it.
if hasattr(self, 'deck'):
@@ -172,100 +177,98 @@ class Game():
# The first time through, initialize the grid, and overlays.
if not hasattr(self, 'grid'):
- self.grid = Grid(self.width, self.height, self.card_width,
- self.card_height)
+ self.grid = Grid(self._width, self._height, self._card_width,
+ self._card_height)
for i in range(3):
self.clicked.append(Click())
for i in range(3):
- self.match_display_area.append(Card(self.sprites,
- generate_match_card(self.scale),
+ self._match_display_area.append(Card(self._sprites,
+ generate_match_card(self._scale),
[MATCHMASK, 0, 0, 0]))
- self.match_display_area[-1].spr.move(self.grid.match_to_xy(i))
+ self._match_display_area[-1].spr.move(self.grid.match_to_xy(i))
for i in range((ROW - 1) * COL):
- self.smiley.append(
- Card(self.sprites, generate_smiley(self.scale),
+ self._smiley.append(
+ Card(self._sprites, generate_smiley(self._scale),
[BACKGROUNDMASK, 0, 0, 0]))
- self.smiley[-1].spr.move(self.grid.grid_to_xy(i))
- self.smiley.append(Card(self.sprites, generate_smiley(self.scale),
+ self._smiley[-1].spr.move(self.grid.grid_to_xy(i))
+ self._smiley.append(Card(self._sprites,
+ generate_smiley(self._scale),
[BACKGROUNDMASK, 0, 0, 0]))
- self.smiley[-1].spr.move(self.grid.match_to_xy(3))
- self.smiley[-1].spr.hide()
+ self._smiley[-1].spr.move(self.grid.match_to_xy(3))
+ self._smiley[-1].spr.hide()
# A different frowny face for each type of error
- self.frowny.append(
- Card(self.sprites, generate_frowny_shape(self.scale),
+ self._frowny.append(
+ Card(self._sprites, generate_frowny_shape(self._scale),
[BACKGROUNDMASK, 0, 0, 0]))
- self.frowny[-1].spr.move(self.grid.match_to_xy(3))
- self.frowny.append(
- Card(self.sprites, generate_frowny_color(self.scale),
+ self._frowny[-1].spr.move(self.grid.match_to_xy(3))
+ self._frowny.append(
+ Card(self._sprites, generate_frowny_color(self._scale),
[BACKGROUNDMASK, 0, 0, 0]))
- self.frowny[-1].spr.move(self.grid.match_to_xy(3))
- self.frowny.append(
- Card(self.sprites, generate_frowny_texture(self.scale),
+ self._frowny[-1].spr.move(self.grid.match_to_xy(3))
+ self._frowny.append(
+ Card(self._sprites, generate_frowny_texture(self._scale),
[BACKGROUNDMASK, 0, 0, 0]))
- self.frowny[-1].spr.move(self.grid.match_to_xy(3))
- self.frowny.append(
- Card(self.sprites, generate_frowny_number(self.scale),
+ self._frowny[-1].spr.move(self.grid.match_to_xy(3))
+ self._frowny.append(
+ Card(self._sprites, generate_frowny_number(self._scale),
[BACKGROUNDMASK, 0, 0, 0]))
- self.frowny[-1].spr.move(self.grid.match_to_xy(3))
-
- for i in range(11):
- path = os.path.join(activity.get_bundle_path(),
- 'images', 'help-%d.svg' % i)
- svg_str = svg_from_file(path)
- pixbuf = svg_str_to_pixbuf(svg_str, int(self.width),
- int(self.height))
- self.help.append(Sprite(self.sprites, 0, 0, pixbuf))
- self.help[-1].hide()
+ self._frowny[-1].spr.move(self.grid.match_to_xy(3))
+
+ if self._sugar:
+ for i in range(22):
+ path = os.path.join(activity.get_bundle_path(),
+ 'images', 'help-%d.svg' % i)
+ svg_str = svg_from_file(path)
+ pixbuf = svg_str_to_pixbuf(svg_str, int(self._width),
+ int(self._height))
+ self._help.append(Sprite(self._sprites, 0, 0, pixbuf))
+ self._help[-1].hide()
for c in self.clicked:
c.hide()
- # Restore saved state on resume or share.
- if not hasattr(self, 'card_type'):
- return
-
self._matches_on_display = False
- for c in self.frowny:
+ for c in self._frowny:
c.spr.hide()
- self.smiley[-1].spr.hide()
+ self._smiley[-1].spr.hide()
if saved_state is not None:
_logger.debug('Restoring state: %s' % (str(saved_state)))
if self.card_type == 'custom':
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC], self.custom_paths,
- self.scale, DIFFICULTY_LEVEL[self.level])
+ self._scale, DIFFICULTY_LEVEL[self.level])
else:
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC], self.word_lists,
- self.scale, DIFFICULTY_LEVEL[self.level])
+ self._scale, DIFFICULTY_LEVEL[self.level])
self.deck.hide()
self.deck.index = deck_index
- _deck_start = ROW * COL + 3
- _deck_stop = _deck_start + self.deck.count()
- self._restore_word_list(saved_state[_deck_stop + \
+ deck_start = ROW * COL + 3
+ deck_stop = deck_start + self.deck.count()
+ self._restore_word_list(saved_state[deck_stop + \
3 * self.matches:])
- self.deck.restore(saved_state[_deck_start: _deck_stop])
+ self.deck.restore(saved_state[deck_start: deck_stop])
self.grid.restore(self.deck, saved_state[0: ROW * COL])
- self._restore_matches(saved_state[_deck_stop: _deck_stop + \
+ self._restore_matches(saved_state[deck_stop: deck_stop + \
3 * self.matches])
self._restore_clicked(saved_state[ROW * COL: ROW * COL + 3])
elif not self.joiner():
_logger.debug('Starting new game.')
if self.card_type == 'custom':
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC],
- self.custom_paths, self.scale,
+ self.custom_paths, self._scale,
DIFFICULTY_LEVEL[self.level])
else:
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC], self.word_lists,
- self.scale, DIFFICULTY_LEVEL[self.level])
+ self._scale, DIFFICULTY_LEVEL[self.level])
self.deck.hide()
self.deck.shuffle()
self.grid.deal(self.deck)
@@ -291,11 +294,11 @@ class Game():
self._timer_reset()
for i in range((ROW - 1) * COL):
- self.smiley[i].hide_card()
+ self._smiley[i].hide_card()
def _sharing(self):
''' Are we sharing? '''
- if self.sugar and hasattr(self.activity, 'chattube') and \
+ if self._sugar and hasattr(self.activity, 'chattube') and \
self.activity.chattube is not None:
return True
return False
@@ -326,17 +329,17 @@ class Game():
if len(self.custom_paths) < 3:
for i in range(len(self.custom_paths), 81):
self.custom_paths.append(None)
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC],
self.custom_paths,
- self.scale, DIFFICULTY_LEVEL.index(HIGH))
+ self._scale, DIFFICULTY_LEVEL.index(HIGH))
self.deck.hide()
self.matches = 0
self.robot_matches = 0
self.match_list = []
self.total_time = 0
- self.edit_card = None
- self.dead_key = None
+ self._edit_card = None
+ self._dead_key = None
if hasattr(self, 'timeout_id') and self.timeout_id is not None:
gobject.source_remove(self.timeout_id)
@@ -358,16 +361,16 @@ class Game():
c.hide()
self.deck.hide()
self.card_type = 'word'
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC], self.word_lists,
- self.scale, DIFFICULTY_LEVEL.index(HIGH))
+ self._scale, DIFFICULTY_LEVEL.index(HIGH))
self.deck.hide()
self.matches = 0
self.robot_matches = 0
self.match_list = []
self.total_time = 0
- self.edit_card = None
- self.dead_key = None
+ self._edit_card = None
+ self._dead_key = None
if hasattr(self, 'timeout_id') and self.timeout_id is not None:
gobject.source_remove(self.timeout_id)
# Fill the grid with word cards.
@@ -380,16 +383,17 @@ class Game():
def _button_press_cb(self, win, event):
''' Look for a card under the button press and save its position. '''
win.grab_focus()
+
+ # Turn off help animation
+ self._stop_help = True
+
# Keep track of starting drag position.
x, y = map(int, event.get_coords())
- self.dragpos = [x, y]
- self.startpos = [x, y]
+ self._drag_pos = [x, y]
+ self._start_pos = [x, y]
# Find the sprite under the mouse.
- spr = self.sprites.find_sprite((x, y))
-
- # Turn off help animation
- self.stop_help = True
+ spr = self._sprites.find_sprite((x, y))
# If there is a match showing, hide it.
if self._matches_on_display:
@@ -397,111 +401,123 @@ class Game():
elif self._failure is not None: # Return last card clicked to grid
self.clean_up_no_match(spr, share=True)
+ # Nothing else to do.
if spr is None:
return True
+ # Don't grab cards in the match pile.
+ if spr in self.match_list:
+ return True
+
+ # Don't grab a card being animated.
+ if True in self.grid.animation_lock:
+ _logger.debug('waiting on animation lock')
+ return True
+
# We are only interested in cards in the deck.
if self.deck.spr_to_card(spr) is not None:
- self.press = spr
+ self._press = spr
# Save its starting position so we can restore it if necessary
if self._where_in_clicked(spr) is None:
i = self._none_in_clicked()
if i is None:
- self.press = None
+ self._press = None
else:
self.clicked[i].spr = spr
self.clicked[i].pos = spr.get_xy()
self.last_click = i
else:
- self.press = None
+ self._press = None
return True
def clean_up_match(self, share=False):
- # Unselect clicked cards
+ ''' Unselect clicked cards that are now in the match pile '''
for c in self.clicked:
c.hide()
- self.smiley[-1].spr.hide()
+ self._smiley[-1].spr.hide()
self._matches_on_display = False
if share and self._sharing():
self.activity._send_event('r:')
def clean_up_no_match(self, spr, share=False):
+ ''' Return last card played to grid '''
if self.clicked[2].spr is not None and self.clicked[2].spr != spr:
self.return_card_to_grid(2)
self.last_click = 2
if share and self._sharing():
self.activity._send_event('R:2')
- for c in self.frowny:
+ for c in self._frowny:
c.spr.hide()
self._failure = None
def _mouse_move_cb(self, win, event):
''' Drag the card with the mouse. '''
- if self.press is None or \
+ if self._press is None or \
self.editing_word_list or \
self.editing_custom_cards:
- self.dragpos = [0, 0]
+ self._drag_pos = [0, 0]
return True
win.grab_focus()
x, y = map(int, event.get_coords())
- dx = x - self.dragpos[0]
- dy = y - self.dragpos[1]
- self.press.set_layer(5000)
- self.press.move_relative((dx, dy))
- self.dragpos = [x, y]
+ dx = x - self._drag_pos[0]
+ dy = y - self._drag_pos[1]
+ self._press.set_layer(5000)
+ self._press.move_relative((dx, dy))
+ self._drag_pos = [x, y]
def _button_release_cb(self, win, event):
''' Lots of possibilities here between clicks and drags '''
win.grab_focus()
# Maybe there is nothing to do.
- if self.press is None:
- self.dragpos = [0, 0]
+ if self._press is None:
+ self._drag_pos = [0, 0]
return True
- self.press.set_layer(2000)
+ self._press.set_layer(2000)
# Determine if it was a click, a drag, or an aborted drag
x, y = map(int, event.get_coords())
- d = _distance((x, y), (self.startpos[0], self.startpos[1]))
- if d < self.card_width / 10: # click
+ d = _distance((x, y), (self._start_pos[0], self._start_pos[1]))
+ if d < self._card_width / 10: # click
move = 'click'
- elif d < self.card_width / 2: # aborted drag
+ elif d < self._card_width / 2: # aborted drag
move = 'abort'
else:
move = 'drag'
# Determine status of card
- status = self.grid.spr_to_grid(self.press)
+ status = self.grid.spr_to_grid(self._press)
if move == 'click':
if self.editing_word_list:
if self.editing_word_list:
# Only edit one card at a time, so unselect other cards
for i, c in enumerate(self.clicked):
- if c.spr is not None and c.spr != self.press:
+ if c.spr is not None and c.spr != self._press:
c.spr.set_label(
c.spr.labels[0].replace(CURSOR, ''))
c.spr = None # Unselect
elif self.editing_custom_cards:
pass
else:
- self.process_click(self.press)
+ self.process_click(self._press)
elif move == 'abort':
- self.press.move(self.clicked[i].pos)
+ i = self._where_in_clicked(self._press)
+ self._press.move(self.clicked[i].pos)
else: # move == 'drag'
- move = self._process_drag(self.press, x, y)
+ move = self._process_drag(self._press, x, y)
if move == 'abort':
- self.press = None
+ self._press = None
return
if self._sharing():
- if self.deck.spr_to_card(self.press) is not None:
+ if self.deck.spr_to_card(self._press) is not None:
# Tell everyone about the card we just clicked
self.activity._send_event(
- 'B:%d' % (self.deck.spr_to_card(self.press).index))
- i = self._where_in_clicked(self.press)
+ 'B:%d' % (self.deck.spr_to_card(self._press).index))
+ i = self._where_in_clicked(self._press)
if i is not None:
self.activity._send_event('S:%d' % (i))
elif self.last_click is not None:
@@ -509,8 +525,8 @@ class Game():
else:
_logger.debug('WARNING: Cannot find last click')
self.last_click = None
- self.process_selection(self.press)
- self.press = None
+ self.process_selection(self._press)
+ self._press = None
return
def process_click(self, spr):
@@ -520,12 +536,12 @@ class Game():
if i is not None:
self.return_card_to_grid(i)
self.last_click = i
- for c in self.frowny:
+ for c in self._frowny:
c.spr.hide()
else:
i = self._where_in_clicked(spr)
if i is None:
- spr.move((self.startpos))
+ spr.move((self._start_pos))
else:
spr.set_layer(5000)
self.grid.grid[self.grid.spr_to_grid(spr)] = None
@@ -545,7 +561,7 @@ class Game():
i = self._where_in_clicked(spr)
self.last_click = i
self.clicked[i].reset()
- for c in self.frowny:
+ for c in self._frowny:
c.spr.hide()
else: # Move a click to a different match slot
i = self._where_in_clicked(spr)
@@ -565,7 +581,7 @@ class Game():
i = self._where_in_clicked(spr)
if x < self.grid.left: # Moving a card to the match area
self.grid.grid[self.grid.spr_to_grid(spr)] = None
- spr.move(self.match_display_area[i].spr.get_xy())
+ spr.move(self._match_display_area[i].spr.get_xy())
else: # Shuffle positions in match area
j = self.grid.xy_to_grid((x, y))
k = self.grid.xy_to_grid(self.clicked[i].pos)
@@ -589,7 +605,7 @@ class Game():
def process_selection(self, spr):
''' After a card has been selected... '''
if self.editing_word_list: # Edit label of selected card
- self.edit_card = self.deck.spr_to_card(spr)
+ self._edit_card = self.deck.spr_to_card(spr)
spr.set_label(spr.labels[0] + CURSOR)
elif self.editing_custom_cards:
# Only edit one card at a time, so unselect other cards
@@ -597,12 +613,12 @@ class Game():
if c.spr is not None and c.spr != spr:
c.spr = None
# Choose an image from the Journal for a card
- self.edit_card = self.deck.spr_to_card(spr)
+ self._edit_card = self.deck.spr_to_card(spr)
self._choose_custom_card()
# Regenerate the deck with the new card definitions
- self.deck = Deck(self.sprites, self.card_type,
+ self.deck = Deck(self._sprites, self.card_type,
[self.numberO, self.numberC],
- self.custom_paths, self.scale,
+ self.custom_paths, self._scale,
DIFFICULTY_LEVEL[1])
self.deck.hide()
self.grid.restore(self.deck, CUSTOM_CARD_INDICIES)
@@ -610,25 +626,28 @@ class Game():
# If we have three cards selected, test for a match.
self._test_for_a_match()
if self._matches_on_display:
- self.smiley[-1].spr.set_layer(100)
+ self._smiley[-1].spr.set_layer(100)
_logger.debug('Found a match')
- else:
- self.frowny[self._failure].spr.set_layer(100)
+ elif self._failure is not None:
+ self._frowny[self._failure].spr.set_layer(100)
return
def _none_in_clicked(self):
+ ''' Look for room on the click list '''
for i, c in enumerate(self.clicked):
if c.spr is None:
return i
return None
def _where_in_clicked(self, spr):
+ ''' Is the card already selected? '''
for i, c in enumerate(self.clicked):
if c.spr == spr:
return i
return None
def add_to_clicked(self, spr, pos=[0, 0]):
+ ''' Add a card to the selected list '''
i = self._where_in_clicked(spr)
if i is not None:
self.last_click = i
@@ -643,6 +662,7 @@ class Game():
self.last_click = i
def return_card_to_grid(self, i):
+ ''' "Unclick" '''
j = self.grid.find_an_empty_slot()
if j is not None:
self.grid.return_to_grid(self.clicked[i].spr, j, i)
@@ -659,7 +679,7 @@ class Game():
int(self.total_time % 60)))
for i in range((ROW - 1) * COL):
if self.grid.grid[i] == None:
- self.smiley[i].show_card()
+ self._smiley[i].show_card()
self.match_timeout_id = gobject.timeout_add(
2000, self._show_matches, 0)
return True
@@ -688,12 +708,7 @@ class Game():
self.matches += 1
for c in self.clicked:
self.match_list.append(c.spr)
-
- # Deal three new cards.
- self.grid.replace(self.clicked, self.deck)
self._matches_on_display = True
- self.set_label('deck', '%d %s' %
- (self.deck.cards_remaining(), _('cards')))
# Test to see if the game is over.
if self._game_over():
@@ -706,17 +721,16 @@ class Game():
self.set_label('status', '%s (%d:%02d)' %
(_('New record'), int(self.total_time / 60),
int(self.total_time % 60)))
- self.all_scores.append(self.total_time)
- if not self.sugar:
+ # Round to nearest second
+ self.all_scores.append(int(self.total_time + 0.5))
+ if not self._sugar:
self.activity.save_score()
+ else:
+ self._auto_increase_difficulty()
return True
-
- # Consolidate the grid.
- self.grid.consolidate()
-
- # Test to see if we need to deal extra cards.
- if not self._find_a_match():
- self.grid.deal_extra_cards(self.deck)
+ else:
+ # Wait a few seconds before dealing new cards.
+ gobject.timeout_add(2000, self._deal_new_cards)
# Keep playing.
self._update_labels()
@@ -725,18 +739,46 @@ class Game():
else:
self._matches_on_display = False
+ def _auto_increase_difficulty(self):
+ ''' Auto advance levels '''
+ if self.level == 2 and len(self.all_scores) > 3:
+ sum = 0
+ for i in range(3):
+ sum += self.all_scores[-i - 1]
+ if sum < 120:
+ self.level = 0
+ self.activity.intermediate_button.set_active(True)
+ elif self.level == 0 and len(self.all_scores) > 8:
+ sum = 0
+ for i in range(3):
+ sum += self.all_scores[-i - 1]
+ if sum < 240:
+ self.level = 1
+ self.activity.expert_button.set_active(True)
+
+ def _deal_new_cards(self):
+ ''' Deal three new cards. '''
+ self.grid.replace(self.clicked, self.deck)
+ self.set_label('deck', '%d %s' %
+ (self.deck.cards_remaining(), _('cards')))
+ # Consolidate the grid.
+ self.grid.consolidate()
+ # Test to see if we need to deal extra cards.
+ if not self._find_a_match():
+ self.grid.deal_extra_cards(self.deck)
+
def _keypress_cb(self, area, event):
''' Keypress: editing word cards or selecting cards to play '''
k = gtk.gdk.keyval_name(event.keyval)
u = gtk.gdk.keyval_to_unicode(event.keyval)
- if self.editing_word_list and self.edit_card is not None:
+ if self.editing_word_list and self._edit_card is not None:
if k in NOISE_KEYS:
- self.dead_key = None
+ self._dead_key = None
return True
if k[0:5] == 'dead_':
- self.dead_key = k
+ self._dead_key = k
return True
- label = self.edit_card.spr.labels[0]
+ label = self._edit_card.spr.labels[0]
if len(label) > 0:
c = label.count(CURSOR)
if c == 0:
@@ -780,8 +822,8 @@ class Game():
elif k == 'Return':
newleft = oldleft + RETURN
else:
- if self.dead_key is not None:
- u = DEAD_DICTS[DEAD_KEYS.index(self.dead_key[5:])][k]
+ if self._dead_key is not None:
+ u = DEAD_DICTS[DEAD_KEYS.index(self._dead_key[5:])][k]
if k in WHITE_SPACE:
u = 32
if unichr(u) != '\x00':
@@ -789,10 +831,10 @@ class Game():
else:
newleft = oldleft + k
label = newleft + CURSOR + oldright
- self.edit_card.spr.set_label(label)
- (i, j) = WORD_CARD_MAP[self.edit_card.index]
+ self._edit_card.spr.set_label(label)
+ (i, j) = WORD_CARD_MAP[self._edit_card.index]
self.word_lists[i][j] = label.replace(CURSOR, '')
- self.dead_key = None
+ self._dead_key = None
else:
if k in KEYMAP:
self.process_selection(self.grid.grid_to_spr(KEYMAP.index(k)))
@@ -807,7 +849,7 @@ class Game():
def do_expose_event(self, event):
# Create the cairo context
- cr = self.canvas.window.cairo_create()
+ cr = self._canvas.window.cairo_create()
# Restrict Cairo to the exposed area; avoid extra work
cr.rectangle(event.area.x, event.area.y,
@@ -816,7 +858,7 @@ class Game():
# Refresh sprite list
if cr is not None:
- self.sprites.redraw_sprites(cr=cr)
+ self._sprites.redraw_sprites(cr=cr)
def _destroy_cb(self, win, event):
''' This is the end '''
@@ -844,7 +886,7 @@ class Game():
def set_label(self, label, s):
''' Update the toolbar labels '''
- if self.sugar:
+ if self._sugar:
if label == 'deck':
self.activity.deck_label.set_text(s)
elif label == 'status':
@@ -923,15 +965,10 @@ class Game():
if robot_match:
# Before robot finds a match: restore any cards in match area
if self._matches_on_display:
- '''
- self.match_list[-1].hide()
- self.match_list[-2].hide()
- self.match_list[-3].hide()
- '''
# And unselect clicked cards
for c in self.clicked:
c.hide()
- self.smiley[-1].spr.hide()
+ self._smiley[-1].spr.hide()
self._matches_on_display = False
else:
for j in range(3):
@@ -957,6 +994,7 @@ class Game():
return False
def _robot_match(self, i):
+ ''' Robot finds a match '''
for j in range(3):
self.clicked[j].spr = self.grid.grid[i[j]].spr
self.grid.grid[i[j]].spr.move(
@@ -1072,7 +1110,7 @@ class Game():
jobject.metadata['mime_type']
if not found_a_sequence:
- grid_index = self.grid.spr_to_grid(self.edit_card.spr)
+ grid_index = self.grid.spr_to_grid(self._edit_card.spr)
self.custom_paths[grid_index] = jobject
self.activity.metadata['custom_' + str(grid_index)] = \
jobject.object_id
@@ -1083,22 +1121,24 @@ class Game():
return
def help_animation(self):
- self.help_index = 0
- self.stop_help = False
- self.help[self.help_index].set_layer(5000)
- self.help_timeout_id = gobject.timeout_add(2000, self._help_next)
+ ''' Simple explanatory animation at start of play '''
+ self._help_index = 0
+ self._stop_help = False
+ self._help[self._help_index].set_layer(5000)
+ self._help_timeout_id = gobject.timeout_add(2000, self._help_next)
def _help_next(self):
- self.help[self.help_index].hide()
- if self.stop_help:
+ ''' Load the next frame in the animation '''
+ self._help[self._help_index].hide()
+ if self._stop_help:
return
- self.help_index += 1
- self.help_index %= len(self.help)
- self.help[self.help_index].set_layer(5000)
- if self.help_index in [0, 9, 10]:
- self.help_timeout_id = gobject.timeout_add(2000, self._help_next)
+ self._help_index += 1
+ self._help_index %= len(self._help)
+ self._help[self._help_index].set_layer(5000)
+ if self._help_index in [0, 9, 10, 20, 21]:
+ self._help_timeout_id = gobject.timeout_add(2000, self._help_next)
else:
- self.help_timeout_id = gobject.timeout_add(1000, self._help_next)
+ self._help_timeout_id = gobject.timeout_add(1000, self._help_next)
class Permutation:
diff --git a/grid.py b/grid.py
index 2bc3587..936b995 100644
--- a/grid.py
+++ b/grid.py
@@ -49,6 +49,7 @@ class Grid:
self.ex = [0, 0, 0, 0, 0, 0]
self.ey = [0, 0, 0, 0, 0, 0]
self.stop_animation = False
+ self.animation_lock = [False, False, False, False, False, False]
def deal(self, deck):
''' Deal an initial set of cards. '''
@@ -124,6 +125,7 @@ class Grid:
def return_to_grid(self, spr, i, j):
''' Move card to the match area. '''
self.stop_animation = False
+ self.animation_lock[j] = True
spr.set_layer(2000)
self.ex[j] = self.grid_to_xy(i)[0]
self.ey[j] = self.grid_to_xy(i)[1]
@@ -139,8 +141,10 @@ class Grid:
spr.move_relative((self.dx[i], self.dy[i]))
if self.stop_animation:
spr.move((self.sx[i], self.sy[i]))
+ self.animation_lock[i] = False
elif _distance_squared(spr.get_xy(), (self.ex[i], self.ey[i])) < 200:
spr.move((self.ex[i], self.ey[i]))
+ self.animation_lock[i] = False
else:
timeout_id = gobject.timeout_add(
100, self._move_to_position, spr, i)
@@ -175,6 +179,7 @@ class Grid:
(self.ex[animate + 3] - c.spr.get_xy()[0]) / 10)
self.dy[animate + 3] = int(
(self.ey[animate + 3] - c.spr.get_xy()[1]) / 10)
+ self.animation_lock[animate + 3] = True
timeout_id = gobject.timeout_add(100, self._move_to_position,
c.spr, animate + 3)
diff --git a/helpbutton.py b/helpbutton.py
new file mode 100644
index 0000000..6c4540b
--- /dev/null
+++ b/helpbutton.py
@@ -0,0 +1,124 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+# Copyright (C) 2012, Gonzalo Odiard <godiard@gmail.com>
+# Copyright (C) 2012, Walter Bender <walter@sugarlabs.org>
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+# HelpButton widget
+
+from gettext import gettext as _
+
+import gtk
+
+from sugar.graphics.toolbutton import ToolButton
+from sugar.graphics.icon import Icon
+from sugar.graphics import style
+
+help_windows = {}
+help_buttons = {}
+
+import logging
+_logger = logging.getLogger('visualmatch-activity')
+
+
+class HelpButton(gtk.ToolItem):
+
+ def __init__(self, activity):
+ self._activity = activity
+ self._current_palette = 'game'
+
+ gtk.ToolItem.__init__(self)
+
+ help_button = ToolButton('help-toolbar')
+ help_button.set_tooltip(_('Help'))
+ self.add(help_button)
+ help_button.show()
+
+ self._palette = help_button.get_palette()
+
+ help_button.connect('clicked', self.__help_button_clicked_cb)
+
+ def __help_button_clicked_cb(self, button):
+ for key in help_buttons.keys():
+ if help_buttons[key].is_expanded():
+ self._palette.set_content(help_windows[key])
+ help_windows[key].show_all()
+ self._palette.popup(immediate=True, state=1)
+ return
+ # No toolbar buttons expanded, so show help for main toolbar
+ self._palette.set_content(help_windows['main-toolbar'])
+ help_windows['main-toolbar'].show_all()
+ self._palette.popup(immediate=True, state=1)
+ '''
+ if self._activity.game_toolbar_button.is_expanded():
+ self._palette.set_content(help_windows['game-toolbar'])
+ help_windows['game-toolbar'].show_all()
+ elif self._activity.numbers_toolbar_button.is_expanded():
+ self._palette.set_content(help_windows['numbers-toolbar'])
+ help_windows['numbers-toolbar'].show_all()
+ elif self._activity.tools_toolbar_button.is_expanded():
+ self._palette.set_content(help_windows['custom-toolbar'])
+ help_windows['custom-toolbar'].show_all()
+ elif self._activity.activity_toolbar_button.is_expanded():
+ self._palette.set_content(help_windows['activity-toolbar'])
+ help_windows['activity-toolbar'].show_all()
+ else:
+ self._palette.set_content(help_windows['main-toolbar'])
+ help_windows['main-toolbar'].show_all()
+
+ self._palette.popup(immediate=True, state=1)
+ '''
+
+def add_section(help_box, section_text, icon=None):
+ ''' Add a section to the help palette. From helpbutton.py by
+ Gonzalo Odiard '''
+ max_text_width = int(gtk.gdk.screen_width() / 3) - 20
+ hbox = gtk.HBox()
+ label = gtk.Label()
+ label.set_use_markup(True)
+ label.set_markup('<b>%s</b>' % section_text)
+ label.set_line_wrap(True)
+ label.set_size_request(max_text_width, -1)
+ hbox.add(label)
+ if icon is not None:
+ _icon = Icon(icon_name=icon)
+ hbox.add(_icon)
+ label.set_size_request(max_text_width - 20, -1)
+ else:
+ label.set_size_request(max_text_width, -1)
+
+ hbox.show_all()
+ help_box.pack_start(hbox, False, False, padding=5)
+
+
+def add_paragraph(help_box, text, icon=None):
+ ''' Add an entry to the help palette. From helpbutton.py by
+ Gonzalo Odiard '''
+ max_text_width = int(gtk.gdk.screen_width() / 3) - 20
+ hbox = gtk.HBox()
+ label = gtk.Label(text)
+ label.set_justify(gtk.JUSTIFY_LEFT)
+ label.set_line_wrap(True)
+ hbox.add(label)
+ if icon is not None:
+ _icon = Icon(icon_name=icon)
+ hbox.add(_icon)
+ label.set_size_request(max_text_width - 20, -1)
+ else:
+ label.set_size_request(max_text_width, -1)
+
+ hbox.show_all()
+ help_box.pack_start(hbox, False, False, padding=5)
diff --git a/icons/help-toolbar.svg b/icons/help-toolbar.svg
new file mode 100644
index 0000000..787b797
--- /dev/null
+++ b/icons/help-toolbar.svg
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55"
+ viewBox="0 0 55 55"
+ id="svg2" >
+ <path
+ d="m 50,27.625 c 0,12.3431 -10.1569,22.5 -22.5,22.5 C 15.1569,50.125 5,39.9681 5,27.625 5,15.2819 15.1569,5.125 27.5,5.125 c 12.3431,0 22.5,10.1569 22.5,22.5 z"
+ style="fill:#FFFFFF" />
+ <path
+ d="m 23.956,27.167 c 0,-1.621 1.8,-1.89 3.645,-2.386 1.8,-0.495 3.6,-1.215 3.6,-3.825 0,-1.98 -1.845,-3.42 -3.734,-3.42 -3.78,0 -4.365,4.455 -7.246,4.455 -1.62,0 -2.745,-1.26 -2.745,-3.24 0,-4.726 5.94,-7.425 9.991,-7.425 5.806,0 10.756,3.6 10.756,9.631 0,4.995 -3.15,7.921 -7.785,9.091 l 0,1.619 c 0,1.801 -1.351,3.105 -3.241,3.105 -2.025,0 -3.24,-1.305 -3.24,-3.105 l 0,-4.5 -0.001,0 z m -0.27,13.77 c 0,-1.935 1.575,-3.51 3.51,-3.51 1.936,0 3.51,1.575 3.51,3.51 0,1.936 -1.574,3.512 -3.51,3.512 -1.935,-10e-4 -3.51,-1.577 -3.51,-3.512 z"
+ style="fill:#282828;stroke:#282828;stroke-width:0.25;stroke-miterlimit:4;" />
+</svg>
diff --git a/images/help-11.svg b/images/help-11.svg
new file mode 100644
index 0000000..7dc56a1
--- /dev/null
+++ b/images/help-11.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,84.913792,9.7413793)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,49.741379)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-12.svg b/images/help-12.svg
new file mode 100644
index 0000000..b59aabe
--- /dev/null
+++ b/images/help-12.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,84.913792,9.7413793)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,45.65047,38.125217)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-13.svg b/images/help-13.svg
new file mode 100644
index 0000000..641190e
--- /dev/null
+++ b/images/help-13.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,84.913792,9.7413793)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,33.024207,24.993904)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-14.svg b/images/help-14.svg
new file mode 100644
index 0000000..a2f9305
--- /dev/null
+++ b/images/help-14.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,84.913792,9.7413793)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-15.svg b/images/help-15.svg
new file mode 100644
index 0000000..d768ed5
--- /dev/null
+++ b/images/help-15.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,66.226923,20.094915)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-16.svg b/images/help-16.svg
new file mode 100644
index 0000000..0926583
--- /dev/null
+++ b/images/help-16.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,44.509751,28.428248)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-17.svg b/images/help-17.svg
new file mode 100644
index 0000000..1502539
--- /dev/null
+++ b/images/help-17.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,54.741379,29.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,29.74138)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-18.svg b/images/help-18.svg
new file mode 100644
index 0000000..7bc89bd
--- /dev/null
+++ b/images/help-18.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,43.630268,38.327238)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,29.74138)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-19.svg b/images/help-19.svg
new file mode 100644
index 0000000..55b955b
--- /dev/null
+++ b/images/help-19.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,25.44845,47.670672)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,29.74138)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-20.svg b/images/help-20.svg
new file mode 100644
index 0000000..60b4939
--- /dev/null
+++ b/images/help-20.svg
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,49.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,29.74138)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+</svg>
diff --git a/images/help-21.svg b/images/help-21.svg
new file mode 100644
index 0000000..f5b5ac2
--- /dev/null
+++ b/images/help-21.svg
@@ -0,0 +1,170 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="125"
+ height="75"
+ id="svg3001">
+ <metadata
+ id="metadata3011">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ <dc:title></dc:title>
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <defs
+ id="defs3009" />
+ <g
+ id="g3003">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="0"
+ x="2.75"
+ y="2.75"
+ id="rect3005"
+ style="fill:#f0f0f0;stroke:none" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,10.049669)"
+ id="g3392">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,30.049669)"
+ id="g3392-0">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-9"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.1986755,0,0,0.1986755,10.049669,50.049668)"
+ id="g3392-9">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect3394-8"
+ style="fill:#f0f0f0;stroke:#a0a0a0;stroke-width:6" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,49.741379)"
+ id="g4176">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4178"
+ style="fill:#ffc4b8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(15.5,-25)"
+ id="path4180"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ <path
+ d="m 22.5,76.1 -5.9,-5.9 -4.1,-4.1 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 l 4.1,4.1 14.1,-14.1 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 l -14.1,14.1 -5.7,5.9 z"
+ transform="translate(55.5,-25)"
+ id="path4182"
+ style="fill:#ff6040;stroke:#ff6040;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,9.7413796)"
+ id="g4740">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4742"
+ style="fill:#afe8a8;stroke:#a0a0a0;stroke-width:3" />
+ <path
+ d="m 33.4,62.5 10.1,10.1 c 0.8,0.8 1.2,1.8 1.2,2.9 0,2.3 -1.9,4.1 -4.1,4.1 -1.1,0 -2.2,-0.5 -2.9,-1.2 L 27.6,68.3 17.5,78.4 c -0.8,0.8 -1.8,1.2 -2.9,1.2 -2.3,0 -4.1,-1.9 -4.1,-4.1 0,-1.1 0.5,-2.2 1.2,-2.9 L 21.8,62.5 11.7,52.4 c -0.7,-0.7 -1.2,-1.8 -1.2,-2.9 0,-2.3 1.9,-4.1 4.1,-4.1 1.1,0 2.2,0.5 2.9,1.2 L 27.6,56.7 37.7,46.6 c 0.8,-0.7 1.8,-1.2 2.9,-1.2 2.3,0 4.1,1.9 4.1,4.1 0,1.1 -0.5,2.2 -1.2,2.9 L 33.4,62.5 z"
+ transform="translate(35.5,-25)"
+ id="path4744"
+ style="fill:#00b418;stroke:#00b418;stroke-width:1.79999995" />
+ </g>
+ <g
+ transform="matrix(0.20689655,0,0,0.20689655,9.5358534,29.74138)"
+ id="g4014">
+ <rect
+ width="119.5"
+ height="69.5"
+ rx="11"
+ ry="9"
+ x="2.75"
+ y="2.75"
+ id="rect4016"
+ style="fill:#acc8e4;stroke:#a0a0a0;stroke-width:3" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="16"
+ id="circle4018"
+ style="fill:#0060c8;stroke:#0060c8;stroke-width:1.79999995" />
+ <circle
+ cx="62.5"
+ cy="38"
+ r="8"
+ id="circle4020"
+ style="fill:#acc8e4;stroke:#0060c8;stroke-width:1.79999995" />
+ </g>
+ <rect
+ width="24.724138"
+ height="14.379311"
+ rx="2.275862"
+ ry="1.8620689"
+ x="62.890457"
+ y="30.310345"
+ id="rect4742-5"
+ style="fill:#000000;fill-opacity:1;stroke:#a0a0a0;stroke-width:0.62068963" />
+ <text
+ x="62.885025"
+ y="39.117004"
+ id="text3231"
+ xml:space="preserve"
+ style="font-size:8.11673546px;font-style:normal;font-weight:normal;line-height:125%;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;font-family:Sans"><tspan
+ x="62.885025"
+ y="39.117004"
+ id="tspan3233"
+ style="fill:#ffff00;fill-opacity:1"><tspan
+ id="tspan3237"
+ style="font-size:4.42731047px;fill:#ffff00;fill-opacity:1">☹ </tspan><tspan
+ id="tspan3235"
+ style="font-size:4.42731047px;font-weight:bold;fill:#ffff00;fill-opacity:1">1 1 2</tspan><tspan
+ id="tspan3239"
+ style="font-size:4.42731047px;fill:#ffff00;fill-opacity:1"> ☹ </tspan></tspan></text>
+</svg>
diff --git a/visualmatch.py b/visualmatch.py
index e32008a..809f556 100755
--- a/visualmatch.py
+++ b/visualmatch.py
@@ -1,6 +1,6 @@
#!/usr/bin/env python
-#Copyright (c) 2009,10 Walter Bender
+#Copyright (c) 2009-12 Walter Bender
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -21,7 +21,7 @@ import os
from game import Game
from constants import PRODUCT, HASH, ROMAN, WORD, CHINESE, MAYAN, DICE, DOTS, \
- STAR, LINES
+ STAR, LINES, INCAN
class VisualMatchMain:
@@ -112,6 +112,10 @@ class VisualMatchMain:
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_O_cb, MAYAN)
menu_items.show()
+ menu_items = gtk.MenuItem(_("Quipu"))
+ menu3.append(menu_items)
+ menu_items.connect("activate", self._number_card_O_cb, INCAN)
+ menu_items.show()
menu_items = gtk.MenuItem(_("Hash"))
menu3.append(menu_items)
menu_items.connect("activate", self._number_card_C_cb, HASH)
@@ -156,7 +160,7 @@ class VisualMatchMain:
self.win.show_all()
# Join the activity
- self.vmw = Game(canvas, os.path.join(os.path.abspath('.'), 'images/'))
+ self.vmw = Game(canvas)
self.vmw.win = self.win
self.vmw.activity = self
self.vmw.card_type = 'pattern'