XO ImageQuiz/Plugins: Difference between revisions

From OLPC
Jump to navigation Jump to search
(How to write a ImageQuiz-Plugin)
 
(new services)
 
(3 intermediate revisions by the same user not shown)
Line 25: Line 25:
/* Interaction */
/* Interaction */
- ask(question) .............................................. Draws Text-Input field and returns var. use: answer = ask('name:')
- add_event_hook(event, onclick) ............................. Hook a Plugin's function to an [[#Events|event]] (here def onclick())
- add_event_hook(event, onclick) ............................. Hook a Plugin's function to an [[#Events|event]] (here def onclick())
- del_event_hook(event_id) ................................... Delete an event-hook
- add_react(x, y, width, height, onclick, display = False) ... Create a [[#Reacts_-_Reacting_Rectangles|React]] and hook in Plugin's function. Returns react's id
- add_react(x, y, width, height, onclick, display = False) ... Create a [[#Reacts_-_Reacting_Rectangles|React]] and hook in Plugin's function. Returns react's id
- del_react(id) .............................................. Remove [[#Reacts_-_Reacting_Rectangles|React]]
- del_react(id) .............................................. Remove [[#Reacts_-_Reacting_Rectangles|React]]
Line 31: Line 34:
/* Question Frame */
/* Question Frame */
- question_display() ......................................... Display last Question
- display_startpage() ........................................ Display the Startpage
- question_refresh_display() ................................. Refresh Layout & Menu, not Question Frame
- question_refresh_question_display() ........................ Refresh Question-Frame (saved in bg_question)
- question_frame_clear() ..................................... Clear Question Frame
- question_frame_clear() ..................................... Clear Question Frame
- question_frame_show_image(imgfn, x, y) ..................... Show Image in Question-Frame
- question_frame_show_image(imgfn, x, y) ..................... Show Image in Question-Frame
Line 50: Line 57:
Services can be accessed via the object ''__SERVICES__''
Services can be accessed via the object ''__SERVICES__''
print __SERVICES__.db.query('SELECT * FROM xoquiz WHERE 1')
print __SERVICES__.db.query('SELECT * FROM xoquiz WHERE 1')

== Easier-to-use Trick ==
In load() is's possible to assign a short name to any __SERVICES__-subclass. In the examples we're using this:
def load():
global sf
sf = __SERVICES__.frontend


= Reacts - Reacting Rectangles =
= Reacts - Reacting Rectangles =
[[Image:rect.jpg]]<br>
[[Image:rect.jpg]]<br>
Reacts are reacting, invisible or visible, rectangular areas on the screen. Created by the Plugins, they start a given function if clicked on. A found react (currently!) stops searching for other clickable objects below. A react can be build with this command:
Reacts are reacting, invisible or visible, rectangular areas on the screen. Created by the Plugins, they start a given function if clicked on. A found react can stop searching for other clickable objects below. A react can be build with this command:
react_id = __SERVICES__.frontend.add_react(x, y, width, height, start_function, display)
react_id = __SERVICES__.frontend.add_react(x, y, width, height, function, stopsearch, display)
* '''x, y, width, height'''
* start_function: a function of your plugin
* '''function''': a function of your plugin
* display: default is False. If you pass True, a visible rectangle will be created
* '''stopsearch''': True or False; by default False. Stop search for objects below if this react is found?
* '''display''': by default set to False, but if you explicitly say 'True', it will draw the rectangle on the screen. Mainly for development.
Reacts can be removed like this:
Reacts can be removed like this:
__SERVICES__.frontend.del_react(react_id)
__SERVICES__.frontend.del_react(react_id)
Line 75: Line 90:
== Minimum ==
== Minimum ==
This is the bare minimum of code, a plugin script requires:
This is the bare minimum of code, a plugin script requires:
__PLUGIN_NAME__ = ''
__PLUGIN_NAME__ = ""
def load():
def load():
pass
pass
Line 84: Line 99:
__PLUGIN_NAME__ = 'Demo Plugin'
__PLUGIN_NAME__ = 'Demo Plugin'
def click1():
def click1():
__SERVICES__.frontend.question_frame_clear()
sf.question_frame_clear()
__SERVICES__.frontend.question_frame_show_text('Hello World!', 0, 0)
sf.question_frame_show_text('Hello World!', 0, 0)
__SERVICES__.frontend.question_frame_show_image('../images/europe.gif', 0, 50)
sf.question_frame_show_image('images/europe.gif', 0, 50)
def load():
def load():
global sf
__SERVICES__.frontend.add_menu_dir('/tools', 'Tools')
__SERVICES__.frontend.add_menu_item('/tools', 'Hello', click1)
sf = __SERVICES__.frontend
sf.add_menu_dir('/tools', 'Tools')
sf.add_menu_item('/tools', 'Hello', click1)


== Hook to event 'onclick' ==
== Hook to event 'onclick' ==
Line 100: Line 118:
def click1():
def click1():
__SERVICES__.frontend.question_frame_clear()
sf.question_frame_clear()
__SERVICES__.frontend.question_frame_show_text('Hello World!', 0, 0)
sf.question_frame_show_text('Hello World!', 0, 0)
__SERVICES__.frontend.question_frame_show_image('../images/europe.gif', 0, 50)
sf.question_frame_show_image('images/europe.gif', 0, 50)
__SERVICES__.frontend.add_event_hook('onclick', event1)
sf.add_event_hook('onclick', event1)
def load():
def load():
global sf
__SERVICES__.frontend.add_menu_dir('/tools', 'Tools')
__SERVICES__.frontend.add_menu_item('/tools', 'Hello', click1)
sf = __SERVICES__.frontend
sf.add_menu_dir('/tools', 'Tools')
sf.add_menu_item('/tools', 'Hello', click1)


== Create a React and Toggle Fullscreen ==
== Create a React and Toggle Fullscreen ==
Line 122: Line 143:
def click1():
def click1():
__SERVICES__.frontend.question_frame_clear()
sf.question_frame_clear()
__SERVICES__.frontend.question_frame_show_text('Hello World!', 0, 0)
sf.question_frame_show_text('Hello World!', 0, 0)
__SERVICES__.frontend.question_frame_show_image('../images/europe.gif', 0, 50)
sf.question_frame_show_image('images/europe.gif', 0, 50)
def load():
def load():
global sf
__SERVICES__.frontend.add_menu_dir('/tools', 'Tools')
__SERVICES__.frontend.add_menu_item('/tools', 'Hello', click1)
sf = __SERVICES__.frontend
__SERVICES__.frontend.add_menu_item('/tools', 'Toggle Fullscreen', clickToggleFS)
sf.add_menu_dir('/tools', 'Tools')
sf.add_menu_item('/tools', 'Hello', click1)
sf.add_menu_item('/tools', 'Toggle Fullscreen', clickToggleFS)
__SERVICES__.frontend.add_react(0, 0, 100, 100, clickReact)
sf.add_react(0, 0, 100, 100, clickReact, True, False)
__SERVICES__.frontend.add_react(100, 100, 200, 200, clickReact2, True)
sf.add_react(100, 100, 200, 200, clickReact2, True, True)
The function takes this parameters:
'''add_react (x, y, width, height, function, stopsearch=False, display=False)''' takes these parameters:
* add_react (x, y, width, height, function, display=False)
* '''x, y, width, height'''
* '''function''': a function of your plugin
The parameter display is set to False by default, but if you explicitly say 'True', it will draw the rectangle on the screen. Mainly for development.
* '''stopsearch''': True or False; by default False. Stop search for objects below if this react is found?
* '''display''': by default set to False, but if you explicitly say 'True', it will draw the rectangle on the screen. Mainly for development.

Latest revision as of 20:19, 29 November 2007

This page is all about how to write Plugins for the XO ImageQuiz. You can get the latest source code here:

git clone git://dev.laptop.org/projects/xo-quiz

Services

Overview

Here's an overview of all services:

/*** Styles and Layout: Use with Layout. ***\

- Have a look at layout.py. Very self-explanatory. Any wishes?
/*** DB Services: Use with db. ***\

- query(q) ................................................... Returns result of db-query in a list
- commit(q) .................................................. Executes query and following commit()
/*** Frontend Services: Use with frontend. ***\

/* Menu */

- add_menu_dir (path, caption, part = 3) ..................... Add menu directory
- add_menu_item(path, caption, onclick, part = 3) ............ Add menu item
- change_dir(dir) ............................................ Change menu directory and update menu

/* Interaction */

- ask(question) .............................................. Draws Text-Input field and returns var. use: answer = ask('name:') 
- add_event_hook(event, onclick) ............................. Hook a Plugin's function to an event (here def onclick())
- del_event_hook(event_id) ................................... Delete an event-hook

- add_react(x, y, width, height, onclick, display = False) ... Create a React and hook in Plugin's function. Returns react's id
- del_react(id) .............................................. Remove React

/* Question Frame */

- display_startpage() ........................................ Display the Startpage

- question_refresh_display() ................................. Refresh Layout & Menu, not Question Frame
- question_refresh_question_display() ........................ Refresh Question-Frame (saved in bg_question)
 
- question_frame_clear() ..................................... Clear Question Frame
- question_frame_show_image(imgfn, x, y) ..................... Show Image in Question-Frame
- question_frame_show_surface(surface, x, y).................. Show Surface in Question-Frame
- question_frame_show_text(text, x, y) ....................... Show Text in Question-Frame

/* PyGame & Other Tools */

- image_load(img_fn) ......................................... Load and convert() image. Return image, image_rect
- sound_load(snd_fn) ......................................... Loads a sound, return sound object
- point_inside_polygon(x, y, poly) ........................... True if x and y inside the polygon

Events

A Plugin can attach functions to some events. Currently supported events (list is growing):

* onclick

How to use services

Services can be accessed via the object __SERVICES__

print __SERVICES__.db.query('SELECT * FROM xoquiz WHERE 1')

Easier-to-use Trick

In load() is's possible to assign a short name to any __SERVICES__-subclass. In the examples we're using this:

def load():
	global sf
	sf = __SERVICES__.frontend

Reacts - Reacting Rectangles

Rect.jpg
Reacts are reacting, invisible or visible, rectangular areas on the screen. Created by the Plugins, they start a given function if clicked on. A found react can stop searching for other clickable objects below. A react can be build with this command:

react_id = __SERVICES__.frontend.add_react(x, y, width, height, function, stopsearch, display)
  • x, y, width, height
  • function: a function of your plugin
  • stopsearch: True or False; by default False. Stop search for objects below if this react is found?
  • display: by default set to False, but if you explicitly say 'True', it will draw the rectangle on the screen. Mainly for development.

Reacts can be removed like this:

__SERVICES__.frontend.del_react(react_id) 

Put together it looks like that:

def test():
	pass

react_id = __SERVICES__.frontend.add_react(100, 100, 400, 200, test)
// do stuff
__SERVICES__.frontend.del_react(react_id)

Examples

git clone git://dev.laptop.org/projects/xo-quiz

Then change to the directory xo-quiz/ImageQuiz.activity/imagequiz.

  • Plugins are .py files saved in the directory 'plugins/'
  • A filename beginning with '_' prevents loading.

Minimum

This is the bare minimum of code, a plugin script requires:

__PLUGIN_NAME__ = ""
def load():
	pass

Hello World

  • Creates a menu-item linked to the local function click1()
  • This button clears the Question Frame and prints 'Hello World' with an Image below
__PLUGIN_NAME__ = 'Demo Plugin'
def click1():
	sf.question_frame_clear()
	sf.question_frame_show_text('Hello World!', 0, 0)
	sf.question_frame_show_image('images/europe.gif', 0, 50)

def load():
	global sf
	sf = __SERVICES__.frontend
	
 	sf.add_menu_dir('/tools', 'Tools')
	sf.add_menu_item('/tools', 'Hello', click1)

Hook to event 'onclick'

  • Extends the Hello-World example, that it reacts on a mouse click
__PLUGIN_NAME__ = 'Demo Plugin'
def event1(var):
 	x, y = var
	print 'click at ', x, '-', y

def click1():
	sf.question_frame_clear()
	sf.question_frame_show_text('Hello World!', 0, 0)
	sf.question_frame_show_image('images/europe.gif', 0, 50)

	sf.add_event_hook('onclick', event1)

def load():
	global sf
	sf = __SERVICES__.frontend
	
 	sf.add_menu_dir('/tools', 'Tools')
	sf.add_menu_item('/tools', 'Hello', click1)

Create a React and Toggle Fullscreen

  • Extend the Hello-World example, that uses a React, and toggles fullscreen
import pygame
__PLUGIN_NAME__ = 'Demo Plugin'

def clickReact(): print "Clicked on my first React"
def clickReact2(): print "Clicked on my second React"

def clickToggleFS():
	pygame.display.toggle_fullscreen()

def click1():
	sf.question_frame_clear()
	sf.question_frame_show_text('Hello World!', 0, 0)
	sf.question_frame_show_image('images/europe.gif', 0, 50)

def load():
	global sf
	sf = __SERVICES__.frontend
	
 	sf.add_menu_dir('/tools', 'Tools')
	sf.add_menu_item('/tools', 'Hello', click1)
	sf.add_menu_item('/tools', 'Toggle Fullscreen', clickToggleFS)

	sf.add_react(0, 0, 100, 100, clickReact, True, False)
	sf.add_react(100, 100, 200, 200, clickReact2, True, True)

add_react (x, y, width, height, function, stopsearch=False, display=False) takes these parameters:

  • x, y, width, height
  • function: a function of your plugin
  • stopsearch: True or False; by default False. Stop search for objects below if this react is found?
  • display: by default set to False, but if you explicitly say 'True', it will draw the rectangle on the screen. Mainly for development.