3
# Copyright (C) 2003, 2008 Bruno Coudoin
5
# This program is free software; you can redistribute it and/or modify
6
# it under the terms of the GNU General Public License as published by
7
# the Free Software Foundation; either version 3 of the License, or
8
# (at your option) any later version.
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
# GNU General Public License for more details.
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, see <http://www.gnu.org/licenses/>.
18
from gcompris import gcompris_gettext as _
19
# PythonTest Board module
31
class Gcompris_redraw:
32
"""The Re-drawing activity"""
35
def __init__(self, gcomprisBoard):
37
self.gcomprisBoard = gcomprisBoard
39
# These are used to let us restart only after the bonus is displayed.
40
# When the bonus is displayed, it call us first with pause(1) and then with pause(0)
41
self.board_paused = 0;
46
["RECT", "anim/tool-rectangle.png", "anim/tool-rectangle_on.png", gcompris.CURSOR_RECT],
47
["FILL_RECT", "anim/tool-filledrectangle.png", "anim/tool-filledrectangle_on.png", gcompris.CURSOR_FILLRECT],
48
["CIRCLE", "anim/tool-circle.png", "anim/tool-circle_on.png", gcompris.CURSOR_CIRCLE],
49
["FILL_CIRCLE", "anim/tool-filledcircle.png", "anim/tool-filledcircle_on.png", gcompris.CURSOR_FILLCIRCLE],
50
["LINE", "anim/tool-line.png", "anim/tool-line_on.png", gcompris.CURSOR_LINE],
51
["DEL", "anim/tool-del.png", "anim/tool-del_on.png", gcompris.CURSOR_DEL],
52
["FILL", "anim/tool-fill.png", "anim/tool-fill_on.png", gcompris.CURSOR_FILL],
53
["SELECT", "anim/tool-select.png", "anim/tool-select_on.png", gcompris.CURSOR_SELECT]
59
self.color_fill = 0xA0
60
self.color_stroke = 0xFF
61
self.colors = [ 0x00000000L,
70
self.current_color = 0
73
self.current_drawing = []
74
self.image_target = []
76
# Define the coord of each drawing area
77
self.drawing_area = [140.0, 20.0, 420.0, 500.0]
78
self.target_area = [440.0, 20.0, 720.0, 500.0]
80
# Global used for the select event
81
self.in_select_ofx = -1
82
self.in_select_ofy = -1
85
self.root_erroritem = []
87
# Set it to 1 to let you create new forms
88
# Once set, draw your shape in the right area. Then clic on OK to display
89
# the data for the form (in the console). Then copy the data in the list at the end of
90
# this file in init_item_list
91
# Set self.editing_mode = None to forbid drawing in the right area
92
self.editing_mode = None
93
#self.editing_mode = 1
97
self.gcomprisBoard.level=1
98
self.gcomprisBoard.maxlevel=1
99
self.gcomprisBoard.sublevel=1
100
self.gcomprisBoard.number_of_sublevel=1
102
gcompris.bar_set(gcompris.BAR_LEVEL)
103
gcompris.set_default_background(self.gcomprisBoard.canvas.get_root_item())
104
gcompris.bar_set_level(self.gcomprisBoard)
105
gcompris.bar_location(4, -1, 0.6)
107
# Create our rootitem. We put each canvas item in it so at the end we
108
# only have to kill it. The canvas deletes all the items it contains automaticaly.
109
self.rootitem = goocanvas.Group(parent = self.gcomprisBoard.canvas.get_root_item())
111
item = goocanvas.Image(
112
parent = self.rootitem,
113
pixbuf = gcompris.utils.load_pixmap(self.gcomprisBoard.name + "/" +
114
self.gcomprisBoard.icon_name),
116
bounds = item.get_bounds()
117
scale = 60.0 / (bounds.x2 - bounds.x1)
118
item.scale(scale, scale)
119
item.set_properties(x = (gcompris.BOARD_WIDTH - 65) / scale,
124
self.draw_drawing_area(20)
126
self.init_item_list()
127
self.display_current_level()
132
# Remove the root item removes all the others inside it
133
gcompris.set_cursor(gcompris.CURSOR_DEFAULT);
134
self.rootitem.remove()
135
self.root_drawingitem.remove()
136
self.root_targetitem.remove()
137
# Delete error previous mark if any
138
if(self.root_erroritem):
139
self.root_erroritem.remove()
143
def pause(self, pause):
145
self.board_paused = pause
147
# When the bonus is displayed, it call us first with pause(1) and then with pause(0)
149
if(self.gamewon == 1 and pause == 0):
150
self.root_targetitem.props.visibility = goocanvas.ITEM_VISIBLE
157
# Save a copy of the target drawing future comparison
158
target = list(self.image_target)
159
target2 = list(self.image_target)
161
# Save a copy of the drawing cause we need to remove empty items
162
source = list(self.current_drawing)
164
# Remove all empty items
171
if self.editing_mode != None :
172
print("To add item in this activity, Copy the following data in init_item_list in redraw.py (near the end)")
173
print("-------------------------------------------------------------------------------")
175
print("-------------------------------------------------------------------------------")
177
# Need to check if target image equals drawing image
188
if(len(target) == 0 and len(source) == 0):
190
self.erase_drawing_area()
191
self.increment_level()
193
gcompris.bonus.display(gcompris.bonus.WIN, gcompris.bonus.FLOWER)
194
self.display_current_level()
195
self.root_targetitem.props.visibility = goocanvas.ITEM_INVISIBLE
198
# Delete previous mark if any
199
if(self.root_erroritem):
200
self.root_erroritem.remove()
202
# Create our rootitem for error items mark
203
self.root_erroritem = goocanvas.Group(
204
parent = self.gcomprisBoard.canvas.get_root_item())
206
self.display_error(target, 1)
207
self.display_error(source, 0)
210
# display where there is errors
211
# if in_target is set then error are displayed in the target area
212
def display_error(self, target, in_target):
214
# Bad Icon Width and Height / 2
218
if self.gcomprisBoard.mode == 'symmetrical' and in_target:
219
target = self.get_symmetry(target)
221
# The images target are always drawn on the drawing area to ease the final comparison
223
xofset = self.target_area[0] - self.drawing_area[0]
228
if(t.has_key('points')):
230
parent = self.root_erroritem,
231
pixbuf = gcompris.utils.load_pixmap("redraw/mini_bad.png"),
232
x = t['points'][0] + (t['points'][2]-t['points'][0])/2 - icw + xofset,
233
y = t['points'][1] + (t['points'][3]-t['points'][1])/2 -ich
235
elif(t.has_key('width')):
237
parent = self.root_erroritem,
238
pixbuf = gcompris.utils.load_pixmap("redraw/mini_bad.png"),
239
x = t['x'] + t['width']/2 - icw + xofset,
240
y = t['y'] + t['height']/2 - ich
242
elif(t.has_key('radius_x')):
244
parent = self.root_erroritem,
245
pixbuf = gcompris.utils.load_pixmap("redraw/mini_bad.png"),
246
x = t['center_x'] -icw + xofset,
247
y = t['center_y'] -ich
251
# Called by gcompris when the user click on the level icon
252
def set_level(self, level):
253
self.gcomprisBoard.level=level;
254
self.gcomprisBoard.sublevel=1;
256
self.erase_drawing_area()
257
self.display_current_level()
266
def key_press(self, keyval, commit_str, preedit_str):
269
# Erase any displayed items (drawing and target)
270
def erase_drawing_area(self):
271
self.root_targetitem.remove()
272
self.root_drawingitem.remove()
273
if(self.root_erroritem):
274
self.root_erroritem.remove()
276
# Display the current level target
277
def display_current_level(self):
278
# Calc the index in drawlist
279
i = (self.gcomprisBoard.level-1) * self.gcomprisBoard.number_of_sublevel+ \
280
(self.gcomprisBoard.sublevel-1)
282
if(i >= len(self.drawlist)):
283
# Wrap to the first level when completed
286
# Set the level in the control bar
287
gcompris.bar_set_level(self.gcomprisBoard);
289
self.draw_image_target(self.drawlist[i])
291
self.display_sublevel()
293
# Prepare an item for the coord display
294
self.coorditem = goocanvas.Text(
295
parent = self.root_targetitem,
296
font = gcompris.skin.get_font("gcompris/content"),
297
x = gcompris.BOARD_WIDTH / 2,
298
y = gcompris.BOARD_HEIGHT - 20,
299
fill_color_rgba = 0x000000FFL,
300
anchor = gtk.ANCHOR_NE
303
# Create our rootitem for drawing items
304
self.root_drawingitem = goocanvas.Group(
305
parent = self.gcomprisBoard.canvas.get_root_item())
308
self.current_drawing = []
310
# Code that increments the sublevel and level
311
# And stays at the last level
312
def increment_level(self):
313
self.gcomprisBoard.sublevel += 1
315
if(self.gcomprisBoard.sublevel>self.gcomprisBoard.number_of_sublevel):
317
self.gcomprisBoard.sublevel=1
318
self.gcomprisBoard.level += 1
319
if(self.gcomprisBoard.level>self.gcomprisBoard.maxlevel) or self.gcomprisBoard.level*self.gcomprisBoard.sublevel>=len(self.drawlist):
320
self.gcomprisBoard.level = self.gcomprisBoard.maxlevel
323
# display current/sublevel number
324
def display_sublevel(self):
327
parent = self.root_targetitem,
328
text = _("Level") + " " + str(self.gcomprisBoard.sublevel) + "/" \
329
+ str(self.gcomprisBoard.number_of_sublevel),
330
font = gcompris.skin.get_font("gcompris/content"),
331
x = gcompris.BOARD_WIDTH - 10,
332
y = gcompris.BOARD_HEIGHT - 20,
333
fill_color_rgba = 0x000000FFL,
334
anchor = gtk.ANCHOR_NE
338
def draw_tools(self):
341
parent = self.rootitem,
342
pixbuf = gcompris.utils.load_pixmap("anim/tool-selector.png"),
354
for i in range(0,len(self.tools)):
360
item = goocanvas.Image(
361
parent = self.rootitem,
362
pixbuf = gcompris.utils.load_pixmap(self.tools[i][1]),
366
item.connect("button_press_event", self.tool_item_event, i)
370
# The last item is select, we select it by default
371
self.current_tool = i
372
self.old_tool_item = item
373
self.old_tool_item.props.pixbuf = gcompris.utils.load_pixmap(self.tools[i][2])
374
gcompris.set_cursor(self.tools[i][3]);
377
item = goocanvas.Svg(parent = self.rootitem,
378
svg_handle = gcompris.skin.svg_get(),
381
item.translate(item.get_bounds().x1 * -1
383
item.get_bounds().y1 * -1
384
+ gcompris.BOARD_HEIGHT - 100)
386
item.connect("button_press_event", self.ok_event)
387
gcompris.utils.item_focus_init(item, None)
389
gcompris.bar_set_level(self.gcomprisBoard)
392
# Event when a tool is selected
393
def tool_item_event(self, item, target, event, tool):
394
if event.type == gtk.gdk.BUTTON_PRESS:
395
if event.button == 1:
396
gcompris.sound.play_ogg("sounds/bleep.wav")
397
# Deactivate old button
398
self.old_tool_item.props.pixbuf = gcompris.utils.load_pixmap(self.tools[self.current_tool][1])
400
# Activate new button
401
self.current_tool = tool
402
self.old_tool_item = item
403
self.old_tool_item.props.pixbuf = gcompris.utils.load_pixmap(self.tools[self.current_tool][2])
404
gcompris.set_cursor(self.tools[self.current_tool][3]);
406
# Display the color selector
407
def draw_colors(self):
415
for i in range(0,len(self.colors)):
421
item = goocanvas.Rect(
422
parent = self.rootitem,
423
fill_color_rgba = self.colors[i] | self.color_stroke,
429
stroke_color_rgba= 0x144B9DFFL
431
item.connect("button_press_event", self.color_item_event, i)
435
# The last item is the one we select by default
436
self.current_color = i
437
self.old_color_item = item
438
self.old_color_item.props.line_width = 4.0
439
self.old_color_item.props.stroke_color_rgba = 0x16EC3DFFL
442
def color_item_event(self, item, target, event, color):
443
if event.type == gtk.gdk.BUTTON_PRESS:
444
if event.button == 1:
445
gcompris.sound.play_ogg("sounds/drip.wav")
446
# Deactivate old button
447
self.old_color_item.props.line_width = 0.0
448
self.old_color_item.props.stroke_color_rgba = 0x144B9DFFL
450
# Activate new button
451
self.current_color = color
452
self.old_color_item = item
453
self.old_color_item.props.line_width = 4.0
454
self.old_color_item.props.stroke_color_rgba= 0x16EC3DFFL
457
# Display the drawing area
458
def draw_drawing_area(self, step):
460
self.current_step = step
462
x1=self.drawing_area[0]
463
y1=self.drawing_area[1]
464
x2=self.drawing_area[2]
465
y2=self.drawing_area[3]
467
item = goocanvas.Rect(
468
parent = self.rootitem,
473
fill_color_rgba = 0xF0F0F0FFL,
475
stroke_color_rgba = 0x111199FFL
477
item.connect("button_press_event", self.create_item_event)
478
item.connect("button_release_event", self.create_item_event)
479
item.connect("motion_notify_event", self.create_item_event)
480
item.connect("leave_notify_event", self.target_item_event)
482
self.draw_grid(x1,x2,y1,y2,step)
484
x1=self.target_area[0]
485
y1=self.target_area[1]
486
x2=self.target_area[2]
487
y2=self.target_area[3]
489
item =goocanvas.Rect(
490
parent = self.rootitem,
495
fill_color_rgba=0xF0F0F0FFL,
497
stroke_color_rgba=0x111199FFL
499
item.connect("motion_notify_event", self.target_item_event)
500
item.connect("leave_notify_event", self.target_item_event)
502
self.draw_grid(x1,x2,y1,y2,step)
505
# Given coord are returned swapped
506
# Work fine for rect and ellipse but not line
507
# so that y2 > y1 and x2 > x1
509
def reorder_coord(self, x1, y1, x2, y2):
521
# Take a drawing and return a symmetrical one
523
def get_symmetry(self, drawing_source):
524
# Make a deepcopy of the list
525
drawing = copy.deepcopy(drawing_source)
531
for k, v in item.items():
534
item[k] = (self.drawing_area[2] - (v[0] - self.drawing_area[0])+xofset, v[1],
535
self.drawing_area[2] - (v[2] - self.drawing_area[0])+xofset, v[3])
537
item[k] = self.drawing_area[2] - (v - self.drawing_area[0]) + xofset - item['width']
538
elif k == 'center_x':
539
item[k] = self.drawing_area[2] - (v - self.drawing_area[0]) + xofset
543
# Draw the image target
544
# depending on self.gcomprisBoard.level drawing is 'normal' or 'symmetric'
546
def draw_image_target(self, drawing):
548
# Save the drawing in image_target for future comparison
549
self.image_target = drawing
551
# Create our rootitem for target items
552
self.root_targetitem = goocanvas.Group(
553
parent = self.gcomprisBoard.canvas.get_root_item())
555
if self.gcomprisBoard.mode == 'symmetrical':
556
drawing = self.get_symmetry(drawing)
558
# The images target are always drawn on the drawing area to ease the final comparison
559
xofset = self.target_area[0] - self.drawing_area[0]
562
# Can specify the item type to draw via a real GTK type or a TOOL string
563
if(i.has_key('type')):
565
self.root_targetitem.add_child (item, -1)
566
item.connect("motion_notify_event", self.target_item_event)
568
elif(i.has_key('tool')):
569
if(i['tool'] == "RECT"):
570
item = goocanvas.Rect();
571
self.root_targetitem.add_child (item, -1)
572
elif(i['tool'] == "FILL_RECT"):
573
item = goocanvas.Rect();
574
self.root_targetitem.add_child (item, -1)
575
elif(i['tool'] == "CIRCLE"):
576
item = goocanvas.Ellipse();
577
self.root_targetitem.add_child (item, -1)
578
elif(i['tool'] == "FILL_CIRCLE"):
579
item = goocanvas.Ellipse();
580
self.root_targetitem.add_child (item, -1)
581
elif(i['tool'] == "LINE"):
582
item = goocanvas.Polyline();
583
self.root_targetitem.add_child (item, -1)
585
print ("ERROR: incorrect type in draw_image_target", i)
586
item.connect("motion_notify_event", self.target_item_event)
588
for k, v in i.items():
589
if k == 'fill_color' :
590
item.props.fill_color = v
591
elif k == 'fill_color_rgba' :
592
item.props.fill_color_rgba = v
594
item.props.height = v
595
elif k == 'stroke_color' :
596
item.props.stroke_color = v
597
elif k == 'stroke_color_rgba' :
598
item.props.stroke_color_rgba = v
600
item.props.points = goocanvas.Points([(v[0]+xofset, v[1]),
601
(v[2]+xofset, v[3])])
602
elif k == 'line_width' :
603
item.props.line_width = v
604
elif k == 'width_pixels' :
605
item.props.width_pixels = v
609
item.props.x = v + xofset
612
elif k == 'center_x' :
613
item.props.center_x = v + xofset
614
elif k == 'center_y' :
615
item.props.center_y = v
616
elif k == 'radius_x' :
617
item.props.radius_x = v
618
elif k == 'radius_y' :
619
item.props.radius_y = v
624
def draw_grid(self, x1, x2, y1, y2, step):
626
# Coord of the written numbers
627
if(x1<self.target_area[0]):
634
# We manage a 2 colors grid
639
for i in range(int(x1), int(x2), int(step)):
646
item = goocanvas.Polyline(
647
parent = self.rootitem,
648
points = goocanvas.Points([(i , y1), (i , y2)]),
649
stroke_color_rgba = color,
654
parent = self.rootitem,
655
text = int((i-x1) / step),
656
font = gcompris.skin.get_font("gcompris/board/tiny"),
659
fill_color_rgba = 0x000000FFL
662
# Clicking on lines let you create object
663
if(x1<self.target_area[0]):
664
item.connect("button_press_event", self.create_item_event)
665
item.connect("button_release_event", self.create_item_event)
666
item.connect("motion_notify_event", self.create_item_event)
668
item.connect("motion_notify_event", self.target_item_event)
670
for i in range(int(y1), int(y2), int(step)):
677
item = goocanvas.Polyline(
678
parent = self.rootitem,
679
points = goocanvas.Points([(x1, i), (x2 , i)]),
680
stroke_color_rgba = color,
686
parent = self.rootitem,
687
text = int((i-y1) / step),
688
font = gcompris.skin.get_font("gcompris/board/tiny"),
691
fill_color_rgba=0x000000FFL
694
# Clicking on lines let you create object
695
if(x1<self.target_area[0]):
696
item.connect("button_press_event", self.create_item_event)
697
item.connect("button_release_event", self.create_item_event)
698
item.connect("motion_notify_event", self.create_item_event)
700
# Given x,y return a new x,y snapped to the grid
701
def snap_to_grid(self, x, y):
703
tmp = round(((x+(self.current_step)) -
704
self.drawing_area[0])/self.current_step) - 1
705
result.append(float(self.drawing_area[0] + tmp*self.current_step))
707
tmp = round(((y+(self.current_step)) -
708
self.drawing_area[1])/self.current_step) - 1
709
result.append(float(self.drawing_area[1] + tmp*self.current_step))
713
# Event when a click on any item. Perform the move
714
def move_item_event(self, item, target, event, item_index):
716
if self.tools[self.current_tool][0] != "SELECT":
719
if (event.type == gtk.gdk.BUTTON_PRESS
720
and event.button == 1):
721
gcompris.sound.play_ogg("sounds/smudge.wav")
726
# Save the ofset between the mouse pointer and the
727
# upper left corner of the object
728
if(self.current_drawing[item_index].has_key('center_x')):
729
self.in_select_ofx = x - self.current_drawing[item_index]['center_x']
730
self.in_select_ofy = y - self.current_drawing[item_index]['center_y']
732
bounds = item.get_bounds()
733
self.in_select_ofx = x - bounds.x1
734
self.in_select_ofy = y - bounds.y1
738
if event.type == gtk.gdk.BUTTON_RELEASE:
739
if event.button == 1:
740
gcompris.sound.play_ogg("sounds/smudge.wav")
743
if event.state & gtk.gdk.BUTTON1_MASK:
747
# Workaround for bad line positionning
748
if(self.current_drawing[item_index].has_key('points')):
749
item.props.line_width = 1.0
751
bounds = item.get_bounds()
753
if(self.current_drawing[item_index].has_key('center_x')):
754
x = x - self.in_select_ofx - item.props.radius_x
755
y = y - self.in_select_ofy - item.props.radius_y
757
x -= self.in_select_ofx
758
y -= self.in_select_ofy
760
x,y = self.snap_to_grid(x,y)
762
# Check drawing boundaries
763
if(x < self.drawing_area[0]):
764
x = self.drawing_area[0]
765
if(x > (self.drawing_area[2]-(bounds.x2-bounds.x1))):
766
x = self.drawing_area[2]-(bounds.x2-bounds.x1)
767
# We need to realign x cause the bounds values are not precise enough
768
x,n = self.snap_to_grid(x,y)
769
if(y < self.drawing_area[1]):
770
y = self.drawing_area[1]
771
if(y > (self.drawing_area[3]-(bounds.y2-bounds.y1))):
772
y = self.drawing_area[3]-(bounds.y2-bounds.y1)
773
# We need to realign y cause the bounds values are not precise enough
774
n,y = self.snap_to_grid(x,y)
776
# Need to update current_drawing
777
if(self.current_drawing[item_index].has_key('center_x')):
778
new_x = x + item.props.radius_x
779
new_y = y + item.props.radius_y
780
self.current_drawing[item_index]['center_x'] = new_x
781
self.current_drawing[item_index]['center_y'] = new_y
782
item.props.center_x = new_x
783
item.props.center_y = new_y
784
elif(self.current_drawing[item_index].has_key('x')):
786
ox = x - self.current_drawing[item_index]['x']
787
oy = y - self.current_drawing[item_index]['y']
788
self.current_drawing[item_index]['x'] += ox
789
self.current_drawing[item_index]['y'] += oy
793
# It can only be a line
794
ox = x - min(self.current_drawing[item_index]['points'][0], self.current_drawing[item_index]['points'][2])
795
oy = y - min(self.current_drawing[item_index]['points'][1], self.current_drawing[item_index]['points'][3])
796
nx1 = self.current_drawing[item_index]['points'][0] + ox
797
ny1 = self.current_drawing[item_index]['points'][1] + oy
798
nx2 = self.current_drawing[item_index]['points'][2] + ox
799
ny2 = self.current_drawing[item_index]['points'][3] + oy
800
self.current_drawing[item_index]['points'] = (nx1, ny1, nx2, ny2)
801
item.props.points = goocanvas.Points([(nx1, ny1),
804
# Workaround for bad line positionning
805
if(self.current_drawing[item_index].has_key('points')):
806
item.props.line_width = 8.0
812
# Event when a click on an item happen on fill in type object
813
def fillin_item_event(self, item, target, event, drawing_item_index):
814
if event.type == gtk.gdk.BUTTON_PRESS:
815
if event.button == 1:
816
if self.tools[self.current_tool][0] == "FILL":
817
item.props.fill_color_rgba = self.colors[self.current_color] | self.color_fill
818
# Reset the item in our list
819
self.current_drawing[drawing_item_index]['fill_color_rgba'] = \
820
self.colors[self.current_color] | self.color_fill
821
gcompris.sound.play_ogg("sounds/paint1.wav")
825
# Event when a click on an item happen on border fill type object
826
def fillout_item_event(self, item, target, event, drawing_item_index):
827
if event.type == gtk.gdk.BUTTON_PRESS:
828
if event.button == 1:
829
if self.tools[self.current_tool][0] == "FILL":
830
item.props.stroke_color_rgba = self.colors[self.current_color] | self.color_stroke
831
# Reset the item in our list
832
self.current_drawing[drawing_item_index]['stroke_color_rgba'] = \
833
self.colors[self.current_color] | self.color_stroke
834
gcompris.sound.play_ogg("sounds/paint1.wav")
838
# Del an item and internal struct cleanup
839
def del_item(self, item, drawing_item_index):
841
# Warning, do not realy delete it or we bug the index of other items
842
self.current_drawing[drawing_item_index] = []
844
# Event when a click on an item happen
845
def del_item_event(self, item, target, event, drawing_item_index):
846
if (event.button == 1 and self.tools[self.current_tool][0] == "DEL") \
847
or (event.button == 3):
848
self.del_item(item, drawing_item_index);
849
gcompris.sound.play_ogg("sounds/eraser1.wav",
850
"sounds/eraser2.wav")
855
# Display the mouse coord in the drawing or target area
857
# 1 = in drawing area
859
# 3 = out of both area
861
def display_coord(self, x, y, type):
863
xl = self.drawing_area[0]
865
xl = self.target_area[0]
867
yl = self.drawing_area[1]
869
x = int(round(((x+(self.current_step/2)) - xl)/self.current_step) - 1)
870
y = int(round(((y+(self.current_step/2)) - yl)/self.current_step) - 1)
873
self.coorditem.props.text = ""
875
self.coorditem.props.text = _("Coordinate") + " = (" + str(x) + "/" + str(y) + ")"
878
# Event when an event on the target area happen
879
def target_item_event(self, item, target, event):
881
if event.type == gtk.gdk.LEAVE_NOTIFY:
882
self.display_coord(event.x,event.y, 3)
884
self.display_coord(event.x,event.y, 2)
887
# Event when an event on the drawing area happen
888
def create_item_event(self, item, target, event):
890
if event.type == gtk.gdk.LEAVE_NOTIFY:
891
self.display_coord(event.x,event.y, 3)
893
self.display_coord(event.x, event.y, 1)
896
if event.type == gtk.gdk.BUTTON_PRESS:
897
# Delete error previous mark if any
898
if(self.root_erroritem):
899
self.root_erroritem.remove()
901
if event.button != 1:
906
if (self.tools[self.current_tool][0] == "DEL" or
907
self.tools[self.current_tool][0] == "SELECT" or
908
self.tools[self.current_tool][0] == "FILL"):
909
# This event is treated in del_item_event to avoid
910
# operating on background item and grid
913
elif self.tools[self.current_tool][0] == "LINE":
915
gcompris.sound.play_ogg("sounds/bleep.wav")
917
x,y = self.snap_to_grid(event.x,event.y)
921
self.newitem = goocanvas.Polyline(
922
parent = self.root_drawingitem,
923
points = goocanvas.Points([(self.pos_x, self.pos_y),
925
stroke_color_rgba = self.colors[self.current_color] | self.color_stroke,
928
self.newitem.connect("button_press_event",
929
self.fillout_item_event, len(self.current_drawing))
930
self.newitem.connect("button_press_event",
931
self.move_item_event, len(self.current_drawing))
932
self.newitem.connect("button_release_event",
933
self.move_item_event, len(self.current_drawing))
934
self.newitem.connect("motion_notify_event",
935
self.move_item_event, len(self.current_drawing))
937
# Add the new item in our list
938
self.current_drawing.append({'tool': self.tools[self.current_tool][0],
939
'points':(self.pos_x, self.pos_y, x, y),
940
'stroke_color_rgba' : self.colors[self.current_color] | self.color_stroke,
943
elif self.tools[self.current_tool][0] == "RECT":
945
gcompris.sound.play_ogg("sounds/bleep.wav")
947
x,y = self.snap_to_grid(event.x,event.y)
951
self.newitem =goocanvas.Rect(
952
parent = self.root_drawingitem,
957
stroke_color_rgba = self.colors[self.current_color] | self.color_stroke,
960
self.newitem.connect("button_press_event",
961
self.fillout_item_event, len(self.current_drawing))
962
self.newitem.connect("button_press_event",
963
self.move_item_event, len(self.current_drawing))
964
self.newitem.connect("button_release_event",
965
self.move_item_event, len(self.current_drawing))
966
self.newitem.connect("motion_notify_event",
967
self.move_item_event, len(self.current_drawing))
969
# Add the new item in our list
970
self.current_drawing.append({'tool': self.tools[self.current_tool][0],
975
'stroke_color_rgba':self.colors[self.current_color] | self.color_stroke,
978
elif self.tools[self.current_tool][0] == "FILL_RECT":
980
gcompris.sound.play_ogg("sounds/bleep.wav")
982
x,y = self.snap_to_grid(event.x,event.y)
986
self.newitem = goocanvas.Rect(
987
parent = self.root_drawingitem,
992
fill_color_rgba = self.colors[self.current_color] | self.color_fill,
993
stroke_color_rgba = 0x000000FFL,
996
self.newitem.connect("button_press_event",
997
self.fillin_item_event, len(self.current_drawing))
998
self.newitem.connect("button_press_event",
999
self.move_item_event, len(self.current_drawing))
1000
self.newitem.connect("button_release_event",
1001
self.move_item_event, len(self.current_drawing))
1002
self.newitem.connect("motion_notify_event",
1003
self.move_item_event, len(self.current_drawing))
1005
# Add the new item in our list
1006
self.current_drawing.append({'tool': self.tools[self.current_tool][0],
1011
'fill_color_rgba':self.colors[self.current_color] | self.color_fill,
1012
'stroke_color_rgba':0x000000FFL,
1015
elif self.tools[self.current_tool][0] == "CIRCLE":
1017
gcompris.sound.play_ogg("sounds/bleep.wav")
1019
x,y = self.snap_to_grid(event.x,event.y)
1023
self.newitem = goocanvas.Ellipse(
1024
parent = self.root_drawingitem,
1025
center_x = self.pos_x,
1026
center_y = self.pos_y,
1029
stroke_color_rgba = self.colors[self.current_color] | self.color_stroke,
1032
self.newitem.connect("button_press_event",
1033
self.fillout_item_event, len(self.current_drawing))
1034
self.newitem.connect("button_press_event",
1035
self.move_item_event, len(self.current_drawing))
1036
self.newitem.connect("button_release_event",
1037
self.move_item_event, len(self.current_drawing))
1038
self.newitem.connect("motion_notify_event",
1039
self.move_item_event, len(self.current_drawing))
1041
# Add the new item in our list
1042
self.current_drawing.append({'tool': self.tools[self.current_tool][0],
1043
'center_x':self.pos_x,
1044
'center_y':self.pos_y,
1047
'stroke_color_rgba':self.colors[self.current_color] | self.color_stroke,
1050
elif self.tools[self.current_tool][0] == "FILL_CIRCLE":
1052
gcompris.sound.play_ogg("sounds/bleep.wav")
1054
x,y = self.snap_to_grid(event.x,event.y)
1058
self.newitem = goocanvas.Ellipse(
1059
parent = self.root_drawingitem,
1060
center_x = self.pos_x,
1061
center_y = self.pos_y,
1064
fill_color_rgba = self.colors[self.current_color] | self.color_fill,
1065
stroke_color_rgba = 0x000000FFL,
1068
self.newitem.connect("button_press_event",
1069
self.fillin_item_event, len(self.current_drawing))
1070
self.newitem.connect("button_press_event",
1071
self.move_item_event, len(self.current_drawing))
1072
self.newitem.connect("button_release_event",
1073
self.move_item_event, len(self.current_drawing))
1074
self.newitem.connect("motion_notify_event",
1075
self.move_item_event, len(self.current_drawing))
1077
# Add the new item in our list
1078
self.current_drawing.append({'tool': self.tools[self.current_tool][0],
1079
'center_x':self.pos_x,
1080
'center_y':self.pos_y,
1083
'fill_color_rgba':self.colors[self.current_color] | self.color_fill,
1084
'stroke_color_rgba':0x000000FFL,
1086
if self.newitem != 0:
1087
self.newitem.connect("button_press_event", self.create_item_event)
1088
self.newitem.connect("button_release_event", self.create_item_event)
1089
self.newitem.connect("motion_notify_event", self.create_item_event)
1090
self.newitem.connect("button_press_event", self.del_item_event, len(self.current_drawing)-1)
1097
if event.type == gtk.gdk.MOTION_NOTIFY:
1098
if event.state & gtk.gdk.BUTTON1_MASK:
1101
x,y = self.snap_to_grid(event.x,event.y)
1103
# Check drawing boundaries
1104
if(event.x<self.drawing_area[0]):
1105
x = self.drawing_area[0]
1106
if(event.x>self.drawing_area[2]):
1107
x = self.drawing_area[2]
1108
if(event.y<self.drawing_area[1]):
1109
y = self.drawing_area[1]
1110
if(event.y>self.drawing_area[3]):
1111
y = self.drawing_area[3]
1113
if self.tools[self.current_tool][0] == "LINE":
1114
self.newitem.props.points = goocanvas.Points([(self.pos_x, self.pos_y),
1116
# Reset the item in our list
1117
self.current_drawing[len(self.current_drawing)-1]['points'] = ( self.pos_x, self.pos_y, x, y)
1119
elif (self.tools[self.current_tool][0] == "RECT" or
1120
self.tools[self.current_tool][0] == "FILL_RECT"):
1121
if(x - self.pos_x < 0):
1122
self.newitem.props.x = x
1124
self.newitem.props.x = self.pos_x
1126
if(y - self.pos_y < 0):
1127
self.newitem.props.y = y
1129
self.newitem.props.y = self.pos_y
1131
self.newitem.props.width = abs(x - self.pos_x)
1132
self.newitem.props.height = abs(y - self.pos_y)
1134
self.current_drawing[len(self.current_drawing)-1]['x'] = \
1135
self.newitem.props.x
1136
self.current_drawing[len(self.current_drawing)-1]['y'] = \
1137
self.newitem.props.y
1138
self.current_drawing[len(self.current_drawing)-1]['width'] = \
1139
self.newitem.props.width
1140
self.current_drawing[len(self.current_drawing)-1]['height'] = \
1141
self.newitem.props.height
1143
elif (self.tools[self.current_tool][0] == "CIRCLE" or
1144
self.tools[self.current_tool][0] == "FILL_CIRCLE"):
1145
self.newitem.props.radius_x = abs(x - self.pos_x)/2
1146
self.newitem.props.center_x = self.pos_x + (x - self.pos_x)/2
1147
self.newitem.props.radius_y = abs(y - self.pos_y)/2
1148
self.newitem.props.center_y = self.pos_y + (y - self.pos_y)/2
1150
self.current_drawing[len(self.current_drawing)-1]['radius_x'] = \
1151
self.newitem.props.radius_x
1152
self.current_drawing[len(self.current_drawing)-1]['center_x'] = \
1153
self.newitem.props.center_x
1154
self.current_drawing[len(self.current_drawing)-1]['radius_y'] = \
1155
self.newitem.props.radius_y
1156
self.current_drawing[len(self.current_drawing)-1]['center_y'] = \
1157
self.newitem.props.center_y
1163
if event.type == gtk.gdk.BUTTON_RELEASE:
1164
if event.button == 1:
1165
# We have to remove empty created items (the kid did not drag enough)
1166
if self.tools[self.current_tool][0] == "LINE":
1167
bounds = self.current_drawing[len(self.current_drawing)-1]['points']
1168
if (bounds[0] == bounds[2]) and (bounds[1] == bounds[3]):
1170
self.del_item(self.newitem, len(self.current_drawing)-1)
1172
gcompris.sound.play_ogg("sounds/line_end.wav")
1173
# We need to reord the coord in increasing order to allow later comparison
1174
# I use a trick, I do x1*x1+y1 and x2*x2+y2, put the lower as the A point
1175
i = bounds[0]*bounds[0] + bounds[1]
1176
j = bounds[2]*bounds[2] + bounds[3]
1178
self.current_drawing[len(self.current_drawing)-1]['points'] = (bounds[0], bounds[1],
1179
bounds[2], bounds[3])
1181
self.current_drawing[len(self.current_drawing)-1]['points'] = (bounds[2], bounds[3],
1182
bounds[0], bounds[1])
1184
elif (self.tools[self.current_tool][0] == "RECT" or
1185
self.tools[self.current_tool][0] == "FILL_RECT"):
1187
width = self.current_drawing[len(self.current_drawing)-1]['width']
1188
height = self.current_drawing[len(self.current_drawing)-1]['height']
1189
if (width == 0) or (height == 0):
1191
self.del_item(self.newitem, len(self.current_drawing)-1)
1192
elif (self.tools[self.current_tool][0] == "CIRCLE" or
1193
self.tools[self.current_tool][0] == "FILL_CIRCLE"):
1195
radius_x = self.current_drawing[len(self.current_drawing)-1]['radius_x']
1196
radius_y = self.current_drawing[len(self.current_drawing)-1]['radius_y']
1197
if (radius_x == 0) or (radius_y == 0):
1199
self.del_item(self.newitem, len(self.current_drawing)-1)
1201
gcompris.sound.play_ogg("sounds/line_end.wav")
1207
# The list of items (data) for this game
1208
def init_item_list(self):
1210
if self.gcomprisBoard.mode == 'normal':
1214
[{'width': 280.0, 'line_width': 1.0, 'height': 20.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 80.0, 'tool': 'FILL_RECT', 'x': 140.0},
1215
{'width': 280.0, 'line_width': 1.0, 'height': 20.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 420.0, 'tool': 'FILL_RECT', 'x': 140.0}]
1218
[{'width': 160.0, 'height': 40.0, 'line_width': 1.0, 'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'y': 40.0, 'x': 200.0, 'tool': 'FILL_RECT'}]
1221
[{'width': 40.0, 'height': 40.0, 'line_width': 1.0,'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'y': 40.0, 'x': 160.0, 'tool': 'FILL_RECT'},
1222
{'width': 400.0-360.0, 'height': 80.0-40.0, 'line_width': 1.0,'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'y': 40.0, 'x': 360.0, 'tool': 'FILL_RECT'},
1223
{'width': 200.0-160.0, 'height': 480.0-440.0, 'line_width': 1.0, 'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'y': 440.0, 'x': 160.0, 'tool': 'FILL_RECT'},
1224
{'width': 400.0-360.0, 'height': 480.0-440.0, 'line_width': 1.0,'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'y': 440.0, 'x': 360.0, 'tool': 'FILL_RECT'}]
1226
# 4 non filled Rects organised in rect and shifted
1227
[{'width': 200.0-180.0, 'height': 360.0-200.0, 'stroke_color_rgba': 0x1010FFFFL, 'line_width': 4.0, 'y': 200.0, 'x': 180.0, 'tool': 'RECT'},
1228
{'width': 340.0-180.0, 'height': 400.0-380.0, 'stroke_color_rgba': 0x1010FFFFL, 'line_width': 4.0, 'y':380.0, 'x': 180.0, 'tool': 'RECT'},
1229
{'width': 380.0-360.0, 'height': 400.0-240.0, 'stroke_color_rgba': 0x1010FFFFL, 'line_width': 4.0, 'y': 240.0, 'x': 360.0, 'tool': 'RECT'},
1230
{'width': 380.0-220.0, 'height': 220.0-200.0, 'stroke_color_rgba': 0x1010FFFFL, 'line_width': 4.0, 'y': 200.0, 'x': 220.0, 'tool': 'RECT'}]
1233
[{'tool': 'LINE', 'points': (200.0, 120.0, 280.0, 120.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1234
{'tool': 'LINE', 'points': (280.0, 120.0, 280.0,240.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1235
{'tool': 'LINE', 'points': (200.0, 120.0, 200.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1236
{'tool': 'LINE', 'points': (200.0, 180.0, 280.0, 180.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL}]
1239
[{'tool': 'LINE', 'points': (240.0, 240.0, 320.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1240
{'tool': 'LINE', 'points': (300.0, 180.0, 320.0,200.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1241
{'tool': 'LINE', 'points': (300.0, 180.0, 320.0, 160.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1242
{'tool': 'LINE', 'points': (240.0, 180.0, 300.0, 180.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1243
{'tool': 'LINE', 'points': (320.0, 100.0, 320.0, 160.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1244
{'tool':'LINE', 'points': (240.0, 100.0, 320.0, 100.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1245
{'tool': 'LINE', 'points': (240.0, 100.0, 240.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1246
{'tool': 'LINE', 'points': (320.0, 200.0, 320.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL}]
1249
[{'width': 360.0-200.0, 'height': 360.0-180.0, 'stroke_color_rgba': 0x1010FFFFL, 'line_width': 4.0, 'y': 180.0, 'x': 200.0, 'tool': 'RECT'},
1250
{'radius_x': 20, 'radius_y': 20, 'line_width': 1.0, 'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'center_y': 280.0+20, 'center_x': 300.0+20, 'tool': 'FILL_CIRCLE'},
1251
{'width': 320.0-240.0, 'height': 260.0-200.0, 'line_width': 1.0, 'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'y': 200.0, 'x': 240.0, 'tool': 'FILL_RECT'}],
1252
# A top left kind of target
1253
[{'radius_x': 50, 'radius_y': 50, 'stroke_color_rgba': 0x1010FFFFL, 'center_y': 40.0+50, 'center_x': 160.0+50, 'tool': 'CIRCLE', 'line_width': 5.0},
1254
{'radius_x': 30, 'radius_y': 30, 'line_width': 1.0, 'fill_color_rgba': 0x1010FFA0L, 'stroke_color_rgba': 255L, 'center_y': 60.0+30, 'center_x': 180.0+30, 'tool': 'FILL_CIRCLE'}]
1256
# 4 Huge Diagonal lines
1257
[{'tool': 'LINE', 'points': (140.0, 260.0, 260.0, 20.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1258
{'tool': 'LINE', 'points': (140.0, 260.0, 260.0, 500.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1259
{'tool': 'LINE', 'points': (260.0, 500.0, 420.0, 260.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1260
{'tool': 'LINE', 'points': (260.0, 20.0, 420.0, 260.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL}]
1263
[{'tool': 'LINE', 'points': (220.0, 240.0, 220.0, 340.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1264
{'radius_x': 40, 'line_width': 1.0, 'radius_y': 50, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 140.0+50, 'tool': 'FILL_CIRCLE', 'center_x': 180.0+40},
1265
{'radius_x': 40, 'line_width': 1.0, 'radius_y': 50, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 80.0+50, 'tool': 'FILL_CIRCLE', 'center_x': 300.0+40},
1266
{'tool': 'LINE', 'points': (340.0, 180.0, 340.0, 280.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL}]
1269
[{'radius_x': 100, 'radius_y': 100, 'stroke_color_rgba': 0x1010FFFFL, 'line_width': 5.0, 'center_y': 140.0+100, 'tool': 'CIRCLE', 'center_x': 180.0+100},
1270
{'tool': 'LINE', 'points': (280.0, 160.0, 280.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1271
{'tool': 'LINE', 'points': (280.0, 240.0, 320.0, 200.0), 'line_width': 8.0, 'stroke_color_rgba': 352271359L},
1272
{'tool': 'LINE', 'points': (220.0, 280.0, 280.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 4294905087L}]
1275
[{'width': 280.0-260.0, 'line_width': 1.0, 'height': 120.0-100.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 100.0, 'x': 260.0, 'tool': 'FILL_RECT'},
1276
{'width': 300.0-240.0, 'line_width': 1.0, 'height': 140.0-120.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 120.0, 'x': 240.0, 'tool': 'FILL_RECT'},
1277
{'width': 320.0-220.0, 'line_width': 1.0, 'height': 160.0-140.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 140.0, 'tool': 'FILL_RECT', 'x': 220.0},
1278
{'width': 340.0-200.0, 'line_width': 1.0, 'height': 180.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 200.0},
1279
{'width': 360.0-180.0, 'line_width': 1.0, 'height': 200.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xC2C2C2A0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 180.0}]
1281
# Colored Rectangle bigger and bigger
1282
[{'width': 180.0-140.0, 'line_width': 1.0, 'height': 60.0-20.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 20.0, 'tool': 'FILL_RECT', 'x': 140.0},
1283
{'width': 240.0-180.0, 'line_width': 1.0, 'height': 120.0-60.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 60.0, 'tool': 'FILL_RECT', 'x': 180.0},
1284
{'width': 320.0-240.0, 'line_width': 1.0, 'height': 200.0-120.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 120.0, 'tool': 'FILL_RECT', 'x': 240.0},
1285
{'width': 420.0-320.0, 'line_width': 1.0, 'height': 300.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 320.0}]
1288
[{'width': 420.0-140.0, 'line_width': 1.0, 'height': 500.0-460.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x000000A0L, 'y': 460.0, 'tool': 'FILL_RECT', 'x': 140.0},
1289
{'width': 260.0-240.0, 'line_width': 1.0, 'height': 460.0-360.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 360.0, 'tool': 'FILL_RECT', 'x': 240.0},
1290
{'radius_x': 70, 'line_width': 1.0, 'radius_y': 40, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 280.0+40, 'tool': 'FILL_CIRCLE', 'center_x': 180.0+70}]
1292
# bipbip (big non flying bird)
1293
[{'width': 280.0-260.0, 'line_width': 1.0, 'height': 320.0-120.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 120.0, 'tool': 'FILL_RECT', 'x': 260.0},
1294
{'width': 300.0-260.0, 'line_width': 1.0, 'height': 120.0-80.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 80.0, 'tool': 'FILL_RECT', 'x': 260.0},
1295
{'width': 320.0-300.0, 'line_width': 1.0, 'height': 120.0-100.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 100.0, 'tool': 'FILL_RECT', 'x': 300.0},
1296
{'width': 280.0-200.0, 'line_width': 1.0, 'height': 380.0-320.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 320.0, 'tool': 'FILL_RECT', 'x': 200.0},
1297
{'width': 220.0-200.0, 'line_width': 1.0, 'height': 320.0-300.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 300.0, 'tool': 'FILL_RECT', 'x': 200.0},
1298
{'width': 260.0-240.0, 'line_width': 1.0, 'height': 460.0-380.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 380.0, 'tool': 'FILL_RECT', 'x': 240.0},
1299
{'width': 280.0-260.0, 'line_width': 1.0, 'height': 460.0-440.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 440.0, 'tool': 'FILL_RECT', 'x': 260.0}]
1302
[{'width': 180.0-160.0, 'line_width': 1.0, 'height': 200.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 160.0},
1303
{'width': 340.0-180.0, 'line_width': 1.0, 'height': 240.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 180.0},
1304
{'width': 200.0-180.0, 'line_width': 1.0, 'height': 280.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 180.0},
1305
{'width': 340.0-320.0,'line_width': 1.0, 'height': 280.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 320.0},
1306
{'width': 380.0-320.0, 'line_width': 1.0, 'height': 200.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 320.0}]
1309
[{'radius_x': 90, 'line_width': 1.0, 'radius_y': 60, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'center_y': 160.0+60, 'tool': 'FILL_CIRCLE', 'center_x': 180.0+90},
1310
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 200.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 320.0+10},
1311
{'width': 180.0-160.0, 'line_width': 1.0, 'height': 260.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 160.0}]
1314
[{'radius_x': 90, 'line_width': 1.0, 'radius_y': 100, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 100.0+100, 'tool': 'FILL_CIRCLE', 'center_x': 200.0+90},
1315
{'radius_x': 50, 'line_width': 1.0, 'radius_y': 30, 'stroke_color_rgba': 255L, 'stroke_color_rgba': 4294905087L, 'center_y': 320.0, 'tool': 'FILL_RECT', 'center_x': 240.0},
1316
{'tool': 'LINE', 'points': (220.0, 260.0, 260.0, 320.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L},
1317
{'tool': 'LINE', 'points': (320.0, 320.0, 360.0, 260.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L}]
1320
[{'width': 360.0-200.0, 'line_width': 1.0, 'height': 340.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 200.0},
1321
{'width': 280.0-240.0, 'line_width': 1.0, 'height': 340.0-280.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 280.0, 'tool': 'FILL_RECT', 'x': 240.0},
1322
{'width': 340.0-300.0, 'line_width': 1.0, 'height': 300.0-260.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 260.0, 'tool': 'FILL_RECT', 'x': 300.0},
1323
{'tool': 'LINE', 'points': (200.0, 240.0, 280.0, 160.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L},
1324
{'tool': 'LINE', 'points': (280.0, 160.0, 360.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L}]
1327
[{'radius_x': 20, 'line_width': 1.0, 'radius_y': 20, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 240.0+20, 'tool': 'FILL_CIRCLE', 'center_x': 180.0+20},
1328
{'radius_x': 20, 'line_width': 1.0, 'radius_y': 20, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 240.0+20, 'tool': 'FILL_CIRCLE', 'center_x': 280.0+20},
1329
{'width': 220.0-160.0, 'line_width': 1.0, 'height': 260.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 160.0},
1330
{'width': 300.0-220.0, 'line_width': 1.0, 'height': 260.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 220.0},
1331
{'width': 320.0-300.0, 'line_width': 1.0, 'height': 260.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 300.0},
1332
{'width': 280.0-240.0, 'line_width': 1.0, 'height': 260.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 240.0}]
1335
[{'radius_x': 20, 'line_width': 1.0, 'radius_y': 20, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 260.0+20, 'tool': 'FILL_CIRCLE', 'center_x': 160.0+20},
1336
{'radius_x': 20, 'line_width': 1.0, 'radius_y': 20, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 260.0+20, 'tool': 'FILL_CIRCLE', 'center_x': 320.0+20},
1337
{'width': 380.0-160.0, 'line_width': 1.0, 'height': 280.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 160.0},
1338
{'tool': 'LINE', 'points': (160.0, 200.0, 340.0, 180.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1339
{'width': 200.0-180.0, 'line_width': 1.0, 'height': 220.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 180.0},
1340
{'width': 360.0-320.0, 'line_width': 1.0, 'height': 260.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 320.0},
1341
{'width': 300.0-280.0, 'line_width': 1.0, 'height': 260.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 280.0}]
1345
{'line_width': 8.0, 'points': (180.0, 80.0, 180.0, 440.0), 'tool': 'LINE', 'stroke_color_rgba': 0x1010FFFFL},
1346
{'line_width': 8.0, 'points': (180.0, 460.0, 380.0, 460.0), 'tool': 'LINE', 'stroke_color_rgba': 0x1010FFFFL},
1347
{'line_width': 8.0, 'points': (380.0, 80.0, 380.0, 440.0), 'tool': 'LINE', 'stroke_color_rgba': 0x1010FFFFL},
1348
{'line_width': 8.0, 'points': (180.0, 60.0, 380.0, 60.0), 'tool': 'LINE', 'stroke_color_rgba': 0x1010FFFFL},
1349
{'line_width': 8.0, 'points': (280.0, 320.0, 280.0, 420.0), 'tool': 'LINE', 'stroke_color_rgba': 2199425535L},
1350
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 300.0+10, 'center_x': 260.0+10, 'tool': 'FILL_CIRCLE'},
1351
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'center_y': 100.0+10, 'center_x': 240.0+10, 'tool': 'FILL_CIRCLE'},
1352
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 100.0+10, 'center_x': 260.0+10, 'tool': 'FILL_CIRCLE'},
1353
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 100.0+10, 'center_x': 280.0+10, 'tool': 'FILL_CIRCLE'},
1354
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x000000A0L, 'center_y': 100.0+10, 'center_x': 300.0+10, 'tool': 'FILL_CIRCLE'},
1355
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xb9bc0dffL, 'center_y': 120.0+10, 'center_x': 260.0+10, 'tool': 'FILL_CIRCLE'},
1356
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 120.0+10, 'center_x': 280.0+10, 'tool': 'FILL_CIRCLE'}
1359
# Clara (my daughter)
1360
[{'width': 240.0-220.0, 'line_width': 1.0, 'height': 480.0-400.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 400.0, 'x': 220.0, 'tool': 'FILL_RECT'},
1361
{'width': 320.0-300.0, 'line_width': 1.0, 'height': 480.0-400.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 400.0, 'x': 300.0, 'tool': 'FILL_RECT'},
1362
{'width': 220.0-160.0, 'line_width': 1.0, 'height': 200.0-180.0,'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 180.0, 'x': 160.0, 'tool': 'FILL_RECT'},
1363
{'width': 380.0-320.0, 'line_width': 1.0, 'height': 200.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 180.0, 'x': 320.0, 'tool': 'FILL_RECT'},
1364
{'width': 380.0-360.0, 'line_width': 1.0, 'height': 180.0-120.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 120.0, 'x': 360.0, 'tool': 'FILL_RECT'},
1365
{'width': 180.0-160.0, 'line_width': 1.0, 'height': 260.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 200.0, 'x': 160.0, 'tool': 'FILL_RECT'},
1366
{'radius_x': 50, 'line_width': 1.0, 'radius_y': 50, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 60.0+50, 'center_x': 220.0+50, 'tool': 'FILL_CIRCLE'},
1367
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00a0L, 'center_y': 100.0+10, 'center_x': 240.0+10, 'tool': 'FILL_CIRCLE'},
1368
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00a0L, 'center_y': 100.0+10, 'center_x': 280.0+10, 'tool': 'FILL_CIRCLE'},
1369
{'line_width': 8.0, 'points': (260.0, 140.0, 280.0, 140.0), 'tool': 'LINE', 'stroke_color_rgba': 0xFF0000A0L},
1370
{'width': 300.0-240.0, 'line_width': 1.0, 'height': 180.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 160.0, 'x': 240.0, 'tool': 'FILL_RECT'},
1371
{'width': 320.0-220.0, 'line_width': 1.0, 'height': 320.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 180.0, 'x': 220.0, 'tool': 'FILL_RECT'},
1372
{'width': 340.0-200.0, 'line_width': 1.0, 'height': 400.0-320.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 320.0, 'x': 200.0, 'tool': 'FILL_RECT'}]
1375
[{'radius_x': 40, 'radius_y': 40, 'stroke_color_rgba': 4287383039L, 'line_width': 5.0, 'center_y': 260.0+40, 'tool': 'CIRCLE', 'center_x': 160.0+40},
1376
{'radius_x': 40, 'radius_y': 40, 'stroke_color_rgba': 4287383039L, 'line_width': 5.0, 'center_y': 260.0+40, 'tool': 'CIRCLE', 'center_x': 320.0+40},
1377
{'tool': 'LINE', 'points': (200.0, 300.0, 280.0, 300.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1378
{'tool': 'LINE', 'points': (280.0,300.0, 340.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1379
{'tool': 'LINE', 'points': (240.0, 240.0, 340.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1380
{'tool': 'LINE', 'points': (200.0, 300.0, 240.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1381
{'tool': 'LINE', 'points': (240.0, 220.0, 240.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 2199425535L},
1382
{'tool': 'LINE', 'points': (220.0, 220.0, 260.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 2199425535L},
1383
{'tool': 'LINE', 'points': (340.0, 200.0, 340.0, 240.0), 'line_width': 8.0, 'stroke_color_rgba': 2199425535L},
1384
{'tool': 'LINE', 'points': (320.0, 200.0, 340.0, 200.0), 'line_width': 8.0, 'stroke_color_rgba': 2199425535L},
1385
{'tool': 'LINE', 'points': (340.0, 240.0, 360.0, 300.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L}]
1388
[{'width': 420.0-140.0, 'line_width': 1.0, 'height': 500.0-420.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00a0L, 'y': 420.0, 'tool': 'FILL_RECT', 'x': 140.0},
1389
{'radius_x': 50, 'line_width': 1.0, 'radius_y': 50, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'center_y': 60.0+50, 'tool': 'FILL_CIRCLE', 'center_x': 160.0+50},
1390
{'radius_x': 50, 'line_width': 1.0, 'radius_y': 20, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 160.0+20, 'tool': 'FILL_CIRCLE', 'center_x': 260.0+50},
1391
{'radius_x': 30, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 200.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 300.0+30},
1392
{'radius_x': 20,'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba':0x1010FFA0L, 'center_y': 140.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 360.0+20},
1393
{'tool': 'LINE','points': (220.0, 400.0, 240.0, 420.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1394
{'tool': 'LINE', 'points': (240.0, 420.0, 280.0, 420.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1395
{'tool': 'LINE', 'points': (280.0, 420.0, 300.0, 400.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1396
{'tool': 'LINE', 'points': (220.0, 400.0, 300.0, 400.0), 'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1397
{'tool': 'LINE', 'points': (260.0, 280.0, 260.0, 400.0),'line_width': 8.0, 'stroke_color_rgba': 0xFF0000A0L},
1398
{'tool': 'LINE', 'points':(260.0, 280.0, 300.0, 380.0), 'line_width': 8.0, 'stroke_color_rgba': 2199425535L},
1399
{'tool': 'LINE', 'points': (260.0, 380.0, 300.0, 380.0), 'line_width': 8.0,'stroke_color_rgba': 2199425535L}]
1406
# 3 white box in triangle
1407
[{'width': 420.0-380.0, 'line_width': 1.0, 'height': 260.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 380.0},
1408
{'width': 380.0-340.0, 'line_width': 1.0, 'height': 220.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 340.0},
1409
{'width': 380.0-340.0, 'line_width': 1.0, 'height': 300.0-260.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 260.0, 'tool': 'FILL_RECT', 'x': 340.0}]
1412
[{'width': 420.0-140.0, 'line_width': 1.0, 'height': 460.0-420.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xC2C2C2A0L, 'y': 420.0, 'tool': 'FILL_RECT', 'x': 140.0},
1413
{'width': 420.0-180.0, 'line_width': 1.0, 'height': 420.0-380.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 380.0, 'tool': 'FILL_RECT', 'x': 180.0},
1414
{'width': 420.0-220.0, 'line_width': 1.0, 'height': 380.0-340.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 340.0, 'tool': 'FILL_RECT', 'x': 220.0},
1415
{'width': 420.0-260.0, 'line_width': 1.0, 'height': 340.0-300.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 300.0, 'tool': 'FILL_RECT', 'x': 260.0},
1416
{'width': 420.0-300.0, 'line_width': 1.0, 'height': 300.0-260.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 260.0, 'tool': 'FILL_RECT', 'x': 300.0},
1417
{'width': 420.0-340.0, 'line_width': 1.0, 'height': 260.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x000000A0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 340.0},
1418
{'width': 420.0-380.0, 'line_width': 1.0, 'height': 220.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x000000A0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 380.0}]
1421
[{'width': 420.0-380.0, 'line_width': 1.0, 'height': 380.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 380.0},
1422
{'tool': 'LINE', 'points': (360.0, 80.0, 400.0, 180.0), 'line_width': 8.0, 'stroke_color_rgba': 707406591L},
1423
{'radius_x': 100, 'line_width': 1.0, 'radius_y': 170, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 100.0+170, 'tool': 'FILL_CIRCLE', 'center_x': 180.0+100},
1424
{'radius_x': 50, 'line_width': 1.0, 'radius_y': 100, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'center_y': 180.0+100, 'tool': 'FILL_CIRCLE', 'center_x': 260.0+50}]
1427
[{'width': 420.0-340.0, 'line_width': 1.0, 'height': 360.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 340.0},
1428
{'width': 380.0-340.0, 'line_width': 1.0, 'height': 500.0-360.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 360.0, 'tool': 'FILL_RECT', 'x': 340.0},
1429
{'width': 340.0-260.0, 'line_width': 1.0, 'height': 200.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 260.0},
1430
{'width': 300.0-260.0, 'line_width': 1.0, 'height': 280.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 260.0},
1431
{'width': 420.0-380.0, 'line_width': 1.0, 'height': 160.0-140.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 140.0, 'tool': 'FILL_RECT', 'x': 380.0},
1432
{'width': 420.0-360.0, 'line_width': 1.0, 'height': 140.0-60.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00a0L, 'y': 60.0, 'tool': 'FILL_RECT', 'x': 360.0},
1433
{'width': 420.0-400.0, 'line_width': 1.0, 'height': 120.0-100.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xb9bc0dffL, 'y': 100.0, 'tool': 'FILL_RECT', 'x': 400.0},
1434
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 80.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 380.0+10}]
1437
[{'width': 420.0-300.0, 'line_width': 1.0, 'height': 260.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 300.0},
1438
{'tool': 'LINE', 'points': (180.0, 240.0, 300.0, 140.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L},
1439
{'tool': 'LINE', 'points': (180.0, 240.0, 180.0, 260.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L},
1440
{'tool': 'LINE', 'points': (180.0, 260.0, 300.0, 360.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L},
1441
{'tool': 'LINE', 'points': (300.0, 140.0, 300.0, 360.0), 'line_width': 8.0, 'stroke_color_rgba': 4287383039L}]
1444
[{'width': 420.0-200.0, 'line_width': 1.0, 'height': 460.0-440.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 440.0, 'tool': 'FILL_RECT', 'x': 200.0},
1445
{'width': 220.0-200.0, 'line_width': 1.0, 'height': 440.0-280.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 280.0, 'tool': 'FILL_RECT', 'x': 200.0},
1446
{'width': 420.0-200.0, 'line_width': 1.0, 'height': 280.0-260.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'y': 260.0, 'tool': 'FILL_RECT', 'x': 200.0},
1447
{'width': 420.0-380.0, 'line_width': 1.0, 'height': 440.0-360.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 360.0, 'tool': 'FILL_RECT', 'x': 380.0},
1448
{'width': 360.0-240.0, 'line_width': 1.0, 'height': 400.0-300.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 300.0, 'tool': 'FILL_RECT', 'x': 240.0},
1449
{'tool': 'LINE', 'points': (200.0, 260.0, 420.0, 100.0), 'line_width': 8.0, 'stroke_color_rgba': 4294905087L}]
1452
[{'width': 420.0-360.0, 'line_width': 1.0, 'height': 380.0-140.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 140.0, 'tool': 'FILL_RECT', 'x': 360.0},
1453
{'width': 360.0-180.0, 'line_width': 1.0, 'height': 280.0-220.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 220.0, 'tool': 'FILL_RECT', 'x': 180.0},
1454
{'width': 260.0-240.0, 'line_width': 1.0, 'height': 220.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x000000A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 240.0},
1455
{'tool': 'LINE', 'points': (180.0, 200.0, 320.0, 200.0), 'line_width': 8.0, 'stroke_color_rgba': 4283674623L},
1456
{'width': 420.0-400.0, 'line_width': 1.0, 'height': 420.0-360.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 360.0, 'tool': 'FILL_RECT', 'x': 400.0},
1457
{'width': 420.0-380.0, 'line_width': 1.0, 'height': 180.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 380.0}]
1459
# bipbip (big non flying bird)
1460
[{'width': 280.0-260.0, 'line_width': 1.0, 'height': 320.0-120.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 120.0, 'tool': 'FILL_RECT', 'x': 260.0},
1461
{'width': 300.0-260.0, 'line_width': 1.0, 'height': 120.0-80.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 80.0, 'tool': 'FILL_RECT', 'x': 260.0},
1462
{'width': 320.0-300.0, 'line_width': 1.0, 'height': 120.0-100.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 100.0, 'tool': 'FILL_RECT', 'x': 300.0},
1463
{'width': 280.0-200.0, 'line_width': 1.0, 'height': 380.0-320.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 320.0, 'tool': 'FILL_RECT', 'x': 200.0},
1464
{'width': 220.0-200.0, 'line_width': 1.0, 'height': 320.0-300.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 300.0, 'tool': 'FILL_RECT', 'x': 200.0},
1465
{'width': 260.0-240.0, 'line_width': 1.0, 'height': 460.0-380.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 380.0, 'tool': 'FILL_RECT', 'x': 240.0},
1466
{'width': 280.0-260.0, 'line_width': 1.0, 'height': 460.0-440.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'y': 440.0, 'tool': 'FILL_RECT', 'x': 260.0}]
1469
[{'width': 180.0-160.0, 'line_width': 1.0, 'height': 200.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 160.0},
1470
{'width': 340.0-180.0, 'line_width': 1.0, 'height': 240.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 180.0},
1471
{'width': 200.0-180.0, 'line_width': 1.0, 'height': 280.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 180.0},
1472
{'width': 340.0-320.0, 'line_width': 1.0, 'height': 280.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 320.0},
1473
{'width': 380.0-320.0, 'line_width': 1.0, 'height': 200.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x831891A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 320.0}]
1476
[{'radius_x': 90, 'line_width': 1.0, 'radius_y': 60, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'center_y': 160.0+60, 'tool': 'FILL_CIRCLE', 'center_x': 180.0+90},
1477
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x1010FFA0L, 'center_y': 200.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 320.0+10},
1478
{'width': 180.0-160.0, 'line_width': 1.0, 'height': 260.0-180.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xffff0cA0L, 'y': 180.0, 'tool': 'FILL_RECT', 'x': 160.0}]
1481
[{'tool': 'LINE', 'points': (260.0, 340.0, 420.0, 340.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1482
{'tool': 'LINE', 'points': (220.0, 260.0, 260.0, 340.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1483
{'tool': 'LINE', 'points': (220.0, 260.0, 420.0, 260.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1484
{'tool': 'LINE', 'points': (340.0, 260.0, 360.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1485
{'tool': 'LINE', 'points': (360.0, 220.0, 420.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1486
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 280.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 300.0+10},
1487
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 280.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 340.0+10},
1488
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'center_y': 280.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 380.0+10}]
1491
[{'tool': 'LINE', 'points': (220.0, 400.0, 340.0, 400.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1492
{'tool': 'LINE', 'points': (340.0, 400.0, 360.0, 420.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1493
{'tool': 'LINE', 'points': (360.0, 320.0, 360.0, 420.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1494
{'tool': 'LINE', 'points': (340.0, 300.0, 360.0, 320.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1495
{'tool': 'LINE', 'points': (340.0, 100.0, 340.0, 300.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1496
{'tool': 'LINE', 'points': (200.0, 420.0, 220.0, 400.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1497
{'tool': 'LINE', 'points': (200.0, 320.0, 200.0, 420.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1498
{'tool': 'LINE', 'points': (200.0, 320.0, 220.0, 300.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1499
{'tool': 'LINE', 'points': (220.0, 100.0, 220.0, 300.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1500
{'tool': 'LINE', 'points': (220.0, 100.0, 280.0, 20.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1501
{'tool': 'LINE', 'points': (280.0, 20.0, 340.0, 100.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1502
{'tool': 'LINE', 'points': (220.0, 100.0, 340.0, 100.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1503
{'tool': 'LINE', 'points': (220.0, 120.0, 340.0, 120.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1504
{'tool': 'LINE', 'points': (220.0, 300.0, 340.0, 300.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1505
{'tool': 'LINE', 'points': (280.0, 300.0, 280.0, 420.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL}]
1508
[{'tool': 'LINE', 'points': (280.0, 260.0, 280.0, 440.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1509
{'tool': 'LINE', 'points': (280.0, 260.0, 340.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1510
{'tool': 'LINE', 'points': (340.0, 160.0, 340.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1511
{'tool': 'LINE', 'points': (280.0, 120.0, 340.0, 160.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1512
{'tool': 'LINE', 'points': (220.0, 160.0, 280.0, 120.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1513
{'tool': 'LINE', 'points': (220.0, 160.0, 220.0, 200.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1514
{'tool': 'LINE', 'points': (220.0, 200.0, 260.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL}]
1516
# Flying toy (cerf volant in french)
1517
[{'tool': 'LINE', 'points': (160.0, 140.0, 260.0, 100.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1518
{'tool': 'LINE', 'points': (160.0, 140.0, 160.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1519
{'tool': 'LINE', 'points': (160.0, 220.0, 260.0, 380.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1520
{'tool': 'LINE', 'points': (260.0, 380.0, 360.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1521
{'tool': 'LINE', 'points': (360.0, 140.0, 360.0, 220.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1522
{'tool': 'LINE', 'points': (260.0, 100.0, 360.0, 140.0), 'line_width': 8.0, 'stroke_color_rgba': 0x1010FFFFL},
1523
{'tool': 'LINE', 'points': (220.0, 500.0, 260.0, 380.0), 'line_width': 8.0, 'stroke_color_rgba': 707406591L},
1524
{'width': 240.0-220.0, 'line_width': 1.0, 'height': 180.0-160.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 160.0, 'tool': 'FILL_RECT', 'x': 220.0},
1525
{'width': 300.0-280.0, 'line_width': 1.0, 'height': 220.0-200.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 200.0, 'tool': 'FILL_RECT', 'x': 280.0},
1526
{'width': 240.0-220.0, 'line_width': 1.0, 'height': 260.0-240.0, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0xFF0000A0L, 'y': 240.0, 'tool': 'FILL_RECT', 'x': 220.0},
1527
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 160.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 280.0+10},
1528
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 200.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 220.0+10},
1529
{'radius_x': 10, 'line_width': 1.0, 'radius_y': 10, 'stroke_color_rgba': 255L, 'fill_color_rgba': 0x33FF00A0L, 'center_y': 240.0+10, 'tool': 'FILL_CIRCLE', 'center_x': 280.0+10}]
1533
# No more than 9 level allowed in gcompris
1534
self.gcomprisBoard.number_of_sublevel=math.ceil(len(self.drawlist)/9.0)
1535
self.gcomprisBoard.maxlevel=min(9, math.ceil(float(len(self.drawlist))/self.gcomprisBoard.number_of_sublevel))
1537
def ok_event(self, widget, target, event=None):