From ee39c04deb56799d0c20cbfd9c32886236ea3e7f Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Tue, 08 May 2012 12:22:19 +0000 Subject: sync with TurtleBlocks 139 --- diff --git a/NEWS b/NEWS index d64e5d2..db575ab 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,12 @@ +10 + +ENHANCEMENTS +* Added help for all levels +* Sync up with Turtle Blocks 139 +* New translations + 9 + ENHANCEMENTS * Added new help files written by Ignacio Rodriguez * Sync with current Turtle Blocks diff --git a/TurtleArt/sprites.py b/TurtleArt/sprites.py index fdf0105..c400d88 100644 --- a/TurtleArt/sprites.py +++ b/TurtleArt/sprites.py @@ -83,6 +83,7 @@ import pango import pangocairo import cairo + class Sprites: ''' A class for the list of sprites and everything they share in common ''' @@ -130,12 +131,12 @@ class Sprites: if spr in self.list: self.list.remove(spr) - def find_sprite(self, pos): + def find_sprite(self, pos, region=False): ''' Search based on (x, y) position. Return the 'top/first' one. ''' list = self.list[:] list.reverse() for spr in list: - if spr.hit(pos): + if spr.hit(pos, readpixel=not region): return spr return None @@ -350,7 +351,7 @@ class Sprite: if len(self.labels) > 0: self.draw_label(cr) - def hit(self, pos): + def hit(self, pos, readpixel=False): ''' Is (x, y) on top of the sprite? ''' x, y = pos if x < self.rect.x: @@ -361,6 +362,12 @@ class Sprite: return False if y > self.rect.y + self.rect.height: return False + if readpixel: + r, g, b, a = self.get_pixel(pos) + if r == g == b == a == 0: + return False + if a == -1: + return False return self._sprites.find_in_list(self) def draw_label(self, cr): @@ -396,14 +403,14 @@ class Sprite: x = int(self.rect.x + self._margins[0] + (my_width - w) / 2) elif self._horiz_align[i] == 'left': x = int(self.rect.x + self._margins[0]) - else: # right + else: # right x = int(self.rect.x + self.rect.width - w - self._margins[2]) h = pl.get_size()[1] / pango.SCALE if self._vert_align[i] == "middle": y = int(self.rect.y + self._margins[1] + (my_height - h) / 2) elif self._vert_align[i] == "top": y = int(self.rect.y + self._margins[1]) - else: # bottom + else: # bottom y = int(self.rect.y + self.rect.height - h - self._margins[3]) cr.save() cr.translate(x, y) @@ -448,16 +455,13 @@ class Sprite: if x < 0 or x > (self.rect.width - 1) or \ y < 0 or y > (self.rect.height - 1): return(-1, -1, -1, -1) - - # create a new 1x1 cairo surface - cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1); + # Create a new 1x1 cairo surface. + cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) cr = cairo.Context(cs) cr.set_source_surface(self.cached_surfaces[i], -x, -y) - cr.rectangle(0,0,1,1) + cr.rectangle(0, 0, 1, 1) cr.set_operator(cairo.OPERATOR_SOURCE) cr.fill() - cs.flush() # ensure all writing is done - # Read the pixel - pixels = cs.get_data() + cs.flush() # Ensure all the writing is done. + pixels = cs.get_data() # Read the pixel. return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0) - diff --git a/TurtleArt/tabasics.py b/TurtleArt/tabasics.py index 60b8d91..cf309cd 100644 --- a/TurtleArt/tabasics.py +++ b/TurtleArt/tabasics.py @@ -553,6 +553,7 @@ tasetshade :shade \r') style='number-style', label='+', special_name=_('plus'), + string_or_number=True, prim_name='plus', logo_command='sum', help_string=_('adds two alphanumeric inputs')) @@ -662,6 +663,7 @@ operators')) style='compare-porch-style', label='>', special_name=_('greater than'), + string_or_number=True, prim_name='greater?', logo_command='greater?', help_string=_('logical greater-than operator')) @@ -678,6 +680,7 @@ operators')) style='compare-porch-style', label='<', special_name=_('less than'), + string_or_number=True, prim_name='less?', logo_command='less?', help_string=_('logical less-than operator')) @@ -692,6 +695,7 @@ operators')) hidden=True, style='compare-style', label='=', + string_or_number=True, special_name=_('equal'), prim_name='equal?', logo_command='equal?', @@ -899,6 +903,7 @@ buttons')) style='number-style-1strarg', label=_('box'), prim_name='box', + string_or_number=True, default=_('my box'), logo_command='box', help_string=_('named variable (numeric value)')) @@ -909,6 +914,7 @@ buttons')) hidden=True, style='basic-style-2arg', label=[_('store in'), _('box'), _('value')], + string_or_number=True, prim_name='storeinbox', logo_command='storeinbox', default=[_('my box'), 100], @@ -923,6 +929,7 @@ variable')) style='basic-style-head-1arg', label=_('action'), prim_name='nop3', + string_or_number=True, default=_('action'), logo_command='to action', help_string=_('top of nameable action stack')) @@ -949,6 +956,7 @@ variable')) hidden=True, style='basic-style-1arg', label=_('action'), + string_or_number=True, prim_name='stack', logo_command='action', default=_('action'), diff --git a/TurtleArt/tablock.py b/TurtleArt/tablock.py index b809930..f835994 100644 --- a/TurtleArt/tablock.py +++ b/TurtleArt/tablock.py @@ -512,7 +512,7 @@ class Block: if self.name in BOX_COLORS: self.colors = BOX_COLORS[self.name] elif self.name in special_block_colors: - self.colors = special_block_colors[self.name] + self.colors = special_block_colors[self.name] else: for p in range(len(palette_blocks)): if self.name in palette_blocks[p]: diff --git a/TurtleArt/tacanvas.py b/TurtleArt/tacanvas.py index bf22248..6a78a17 100644 --- a/TurtleArt/tacanvas.py +++ b/TurtleArt/tacanvas.py @@ -73,7 +73,8 @@ def calc_gray(c, g, invert=False): colors = {} -DEGTOR = 2 * pi / 360 +DEGTOR = pi / 180. +RTODEG = 180. / pi COLOR_TABLE = ( 0xFF0000, 0xFF0D00, 0xFF1A00, 0xFF2600, 0xFF3300, @@ -106,12 +107,12 @@ class TurtleGraphics: self.tw = tw self.width = width self.height = height - + # Build a cairo.Context from a cairo.XlibSurface self.canvas = cairo.Context(self.tw.turtle_canvas) cr = gtk.gdk.CairoContext(self.canvas) cr.set_line_cap(1) # Set the line cap to be round - + self.cr_svg = None # Surface used for saving to SVG self.cx = 0 self.cy = 0 self.fgrgb = [255, 0, 0] @@ -127,16 +128,24 @@ class TurtleGraphics: self.gray = 100 self.fill = False self.poly_points = [] - self.svg = SVG() - self.svg.set_fill_color('none') - self.tw.svg_string = '' + + def setup_svg_surface(self): + ''' Set up a surface for saving to SVG ''' + if self.tw.running_sugar: + svg_surface = cairo.SVGSurface( + os.path.join(get_path(self.tw.activity, 'instance'), + 'output.svg'), self.width, self.height) + else: + svg_surface = cairo.SVGSurface( + os.path.join(os.getcwd(), 'output.svg'), + self.width, self.height) + self.cr_svg = cairo.Context(svg_surface) + self.cr_svg.set_line_cap(1) # Set the line cap to be round def start_fill(self): ''' Start accumulating points of a polygon to fill. ''' self.fill = True self.poly_points = [] - if self.tw.saving_svg: - self.tw.svg_string += '' def stop_fill(self): ''' Fill the polygon. ''' @@ -153,52 +162,48 @@ class TurtleGraphics: shared_poly_points])) self.tw.send_event(event) self.poly_points = [] - if self.tw.saving_svg: - self.tw.svg_string += '' def fill_polygon(self, poly_points): ''' Draw the polygon... ''' - self.canvas.new_path() - for i, p in enumerate(poly_points): - if p[0] == 'move': - self.canvas.move_to(p[1], p[2]) - elif p[0] == 'rarc': - self.canvas.arc(p[1], p[2], p[3], p[4], p[5]) - elif p[0] == 'larc': - self.canvas.arc_negative(p[1], p[2], p[3], p[4], p[5]) - else: # line - self.canvas.line_to(p[1], p[2]) - self.canvas.close_path() - self.canvas.fill() - if self.tw.saving_svg and self.pendown: - self.svg.set_fill_color('#%02x%02x%02x' % (self.fgrgb[0], - self.fgrgb[1], - self.fgrgb[2])) - self.tw.svg_string += self.svg.new_path(poly_points[0][0], - poly_points[0][1]) - for p in range(len(poly_points)): - if p > 0: - self.tw.svg_string += self.svg.line_to(poly_points[p][0], - poly_points[p][1]) - self.tw.svg_string += '"\n' - self.tw.svg_string += self.svg.style() - self.svg.set_fill_color('none') + def _fill_polygon(cr, poly_points): + cr.new_path() + for i, p in enumerate(poly_points): + if p[0] == 'move': + cr.move_to(p[1], p[2]) + elif p[0] == 'rarc': + cr.arc(p[1], p[2], p[3], p[4], p[5]) + elif p[0] == 'larc': + cr.arc_negative(p[1], p[2], p[3], p[4], p[5]) + else: # line + cr.line_to(p[1], p[2]) + cr.close_path() + cr.fill() + + _fill_polygon(self.canvas, poly_points) + self.inval() + if self.cr_svg is not None: + _fill_polygon(self.cr_svg, poly_points) def clearscreen(self, share=True): '''Clear the canvas and reset most graphics attributes to defaults.''' - self.canvas.move_to(0, 0) - self.canvas.set_source_rgb(self.bgrgb[0] / 255., - self.bgrgb[1] / 255., - self.bgrgb[2] / 255.) - self.canvas.rectangle(0, 0, self.width * 2, self.height * 2) - self.canvas.fill() + + def _clearscreen(cr): + cr.move_to(0, 0) + cr.set_source_rgb(self.bgrgb[0] / 255., + self.bgrgb[1] / 255., + self.bgrgb[2] / 255.) + cr.rectangle(0, 0, self.width * 2, self.height * 2) + cr.fill() + + _clearscreen(self.canvas) self.inval() + if self.cr_svg is not None: + _clearscreen(self.cr_svg) + self.setpensize(5, share) self.setgray(100, share) self.setcolor(0, share) self.setshade(50, share) - self.tw.svg_string = '' - self.svg.reset_min_max() self.fill = False self.poly_points = [] for turtle_key in iter(self.tw.turtles.dict): @@ -222,6 +227,10 @@ class TurtleGraphics: nn = n * self.tw.coord_scale self.canvas.set_source_rgb(self.fgrgb[0] / 255., self.fgrgb[1] / 255., self.fgrgb[2] / 255.) + if self.cr_svg is not None: + debug_output('in forward', True) + self.cr_svg.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., self.fgrgb[2] / 255.) oldx, oldy = self.xcor, self.ycor try: self.xcor += nn * sin(self.heading * DEGTOR) @@ -274,6 +283,9 @@ class TurtleGraphics: ''' Draw an arc ''' self.canvas.set_source_rgb(self.fgrgb[0] / 255., self.fgrgb[1] / 255., self.fgrgb[2] / 255.) + if self.cr_svg is not None: + self.cr_svg.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., self.fgrgb[2] / 255.) try: if a < 0: self.larc(-a, r) @@ -303,11 +315,15 @@ class TurtleGraphics: cy = self.ycor - r * sin(self.heading * DEGTOR) if self.pendown: x, y = self.turtle_to_screen_coordinates(cx, cy) - self.canvas.arc(x, y, r, - (self.heading - 180) * DEGTOR, - (self.heading - 180 + a) * DEGTOR) - self.canvas.stroke() + + def _rarc(cr, x, y, r, a, h): + cr.arc(x, y, r, (h - 180) * DEGTOR, (h - 180 + a) * DEGTOR) + cr.stroke() + + _rarc(self.canvas, x, y, r, a, self.heading) self.inval() + if self.cr_svg is not None: + _rarc(self.cr_svg, x, y, r, a, self.heading) if self.fill: if self.poly_points == []: @@ -319,13 +335,6 @@ class TurtleGraphics: self.right(a, False) self.xcor = cx - r * cos(self.heading * DEGTOR) self.ycor = cy + r * sin(self.heading * DEGTOR) - if self.tw.saving_svg and self.pendown: - x, y = self.turtle_to_screen_coordinates(oldx, oldy) - self.tw.svg_string += self.svg.new_path(x, y) - x, y = self.turtle_to_screen_coordinates(self.xcor, self.ycor) - self.tw.svg_string += self.svg.arc_to(x, y, r, a, 0, s) - self.tw.svg_string += '"\n' - self.tw.svg_string += self.svg.style() def larc(self, a, r): ''' draw a counter-clockwise arc ''' @@ -341,11 +350,15 @@ class TurtleGraphics: cy = self.ycor + r * sin(self.heading * DEGTOR) if self.pendown: x, y = self.turtle_to_screen_coordinates(cx, cy) - self.canvas.arc_negative(x, y, r, - (self.heading) * DEGTOR, - (self.heading - a) * DEGTOR) - self.canvas.stroke() + + def _larc(cr, x, y, r, a, h): + cr.arc_negative(x, y, r, h * DEGTOR, (h - a) * DEGTOR) + cr.stroke() + + _larc(self.canvas, x, y, r, a, self.heading) self.inval() + if self.cr_svg is not None: + _larc(self.cr_svg, x, y, r, a, self.heading) if self.fill: if self.poly_points == []: @@ -357,13 +370,6 @@ class TurtleGraphics: self.right(-a, False) self.xcor = cx + r * cos(self.heading * DEGTOR) self.ycor = cy - r * sin(self.heading * DEGTOR) - if self.tw.saving_svg and self.pendown: - x, y = self.turtle_to_screen_coordinates(oldx, oldy) - self.tw.svg_string += self.svg.new_path(x, y) - x, y = self.turtle_to_screen_coordinates(self.xcor, self.ycor) - self.tw.svg_string += self.svg.arc_to(x, y, r, a, 0, s) - self.tw.svg_string += '"\n' - self.tw.svg_string += self.svg.style() def setxy(self, x, y, share=True, pendown=True): ''' Move turtle to position x,y ''' @@ -381,6 +387,10 @@ class TurtleGraphics: self.canvas.set_source_rgb(self.fgrgb[0] / 255., self.fgrgb[1] / 255., self.fgrgb[2] / 255.) + if self.cr_svg is not None: + self.cr_svg.set_source_rgb(self.fgrgb[0] / 255., + self.fgrgb[1] / 255., + self.fgrgb[2] / 255.) self.draw_line(oldx, oldy, self.xcor, self.ycor) self.inval() self.move_turtle() @@ -402,7 +412,8 @@ class TurtleGraphics: return self.tw.active_turtle.set_pen_size(ps) self.canvas.set_line_width(ps) - self.svg.set_stroke_width(self.pensize) + if self.cr_svg is not None: + self.cr_svg.set_line_width(ps) if self.tw.sharing() and share: event = 'w|%s' % (data_to_string([self._get_my_nick(), round_int(ps)])) @@ -478,17 +489,19 @@ class TurtleGraphics: oldc, olds = self.color, self.shade self.setcolor(c, False) self.setshade(s, False) - self.canvas.set_source_rgb(self.fgrgb[0] / 255., - self.fgrgb[1] / 255., - self.fgrgb[2] / 255.) self.bgrgb = self.fgrgb[:] - self.canvas.rectangle(0, 0, self.width * 2, self.height * 2) - self.canvas.fill() + + def _fillscreen(cr, rgb, w, h): + cr.set_source_rgb(rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) + cr.rectangle(0, 0, w * 2, h * 2) + cr.fill() + + _fillscreen(self.canvas, self.fgrgb, self.width, self.height) self.inval() + if self.cr_svg is not None: + _fillscreen(self.cr_svg, self.fgrgb, self.width, self.height) self.setcolor(oldc, False) self.setshade(olds, False) - self.tw.svg_string = '' - self.svg.reset_min_max() self.fill = False self.poly_points = [] @@ -515,9 +528,6 @@ class TurtleGraphics: b = calc_gray(b, self.gray) b = calc_shade(b, sh) self.fgrgb = [r >> 8, g >> 8, b >> 8] - self.svg.set_stroke_color('#%02x%02x%02x' % (self.fgrgb[0], - self.fgrgb[1], - self.fgrgb[2])) def setpen(self, bool, share=True): ''' Lower or raise the pen ''' @@ -529,42 +539,39 @@ class TurtleGraphics: def draw_surface(self, surface, x, y, w, h): ''' Draw a surface ''' - cr = gtk.gdk.CairoContext(self.canvas) - cr.set_source_surface(surface, x, y) - cr.rectangle(x, y, w, h) - cr.fill() + + def _draw_surface(cr, surface, x, y, w, h): + cc = gtk.gdk.CairoContext(cr) + cc.set_source_surface(surface, x, y) + cc.rectangle(x, y, w, h) + cc.fill() + + _draw_surface(self.canvas, surface, x, y, w, h) self.inval() + if self.cr_svg is not None: + _draw_surface(self.cr_svg, surface, x, y, w, h) def draw_pixbuf(self, pixbuf, a, b, x, y, w, h, path, share=True): ''' Draw a pixbuf ''' - # Build a gtk.gdk.CairoContext from a cairo.Context to access - # the set_source_pixbuf attribute. - cr = gtk.gdk.CairoContext(self.canvas) - cr.save() - # center the rotation on the center of the image - cr.translate(x + w / 2., y + h / 2.) - cr.rotate(self.heading * DEGTOR) - cr.translate(-x - w / 2., -y - h / 2.) - cr.set_source_pixbuf(pixbuf, x, y) - cr.rectangle(x, y, w, h) - cr.fill() - cr.restore() + + def _draw_pixbuf(cr, pixbuf, a, b, x, y, w, h, heading): + # Build a gtk.gdk.CairoContext from a cairo.Context to access + # the set_source_pixbuf attribute. + cc = gtk.gdk.CairoContext(cr) + cc.save() + # center the rotation on the center of the image + cc.translate(x + w / 2., y + h / 2.) + cc.rotate(heading * DEGTOR) + cc.translate(-x - w / 2., -y - h / 2.) + cc.set_source_pixbuf(pixbuf, x, y) + cc.rectangle(x, y, w, h) + cc.fill() + cc.restore() + + _draw_pixbuf(self.canvas, pixbuf, a, b, x, y, w, h, self.heading) self.inval() - if self.tw.saving_svg: - if self.tw.running_sugar: - # In Sugar, we embed the images inside the SVG - tmp_file = os.path.join(get_path(self.tw.activity, 'instance'), - 'tmpfile.png') - pixbuf.save(tmp_file, 'png', {'quality': '100'}) - self.tw.svg_string += self.svg.image( - x, y, w, h, path, - image_to_base64(tmp_file, - get_path(self.tw.activity, 'instance'))) - os.remove(tmp_file) - else: - # In GNOME, we embed a path - self.tw.svg_string += self.svg.image( - x - self.width / 2, y, w, h, path) + if self.cr_svg is not None: + _draw_pixbuf(self.cr_svg, pixbuf, a, b, x, y, w, h, self.heading) if self.tw.sharing() and share: if self.tw.running_sugar: tmp_path = get_path(self.tw.activity, 'instance') @@ -590,31 +597,34 @@ class TurtleGraphics: def draw_text(self, label, x, y, size, w, share=True): ''' Draw text ''' w *= self.tw.coord_scale - cr = pangocairo.CairoContext(self.canvas) - pl = cr.create_layout() - fd = pango.FontDescription('Sans') - fd.set_size(int(size * self.tw.coord_scale) * pango.SCALE) - pl.set_font_description(fd) - if type(label) == str or type(label) == unicode: - pl.set_text(label.replace('\0', ' ')) - elif type(label) == float or type(label) == int: - pl.set_text(str(label)) - else: - pl.set_text(str(label)) - pl.set_width(int(w) * pango.SCALE) - cr.save() - cr.translate(x, y) - cr.rotate(self.heading * DEGTOR) - self.canvas.set_source_rgb(self.fgrgb[0] / 255., - self.fgrgb[1] / 255., - self.fgrgb[2] / 255.) - cr.update_layout(pl) - cr.show_layout(pl) - cr.restore() + + def _draw_text(cr, label, x, y, size, w, scale, heading, rgb): + cc = pangocairo.CairoContext(cr) + pl = cc.create_layout() + fd = pango.FontDescription('Sans') + fd.set_size(int(size * scale) * pango.SCALE) + pl.set_font_description(fd) + if type(label) == str or type(label) == unicode: + pl.set_text(label.replace('\0', ' ')) + elif type(label) == float or type(label) == int: + pl.set_text(str(label)) + else: + pl.set_text(str(label)) + pl.set_width(int(w) * pango.SCALE) + cc.save() + cc.translate(x, y) + cc.rotate(heading * DEGTOR) + cr.set_source_rgb(rgb[0] / 255., rgb[1] / 255., rgb[2] / 255.) + cc.update_layout(pl) + cc.show_layout(pl) + cc.restore() + + _draw_text(self.canvas, label, x, y, size, w, self.tw.coord_scale, + self.heading, self.fgrgb) self.inval() - if self.tw.saving_svg: # and self.pendown: - self.tw.svg_string += self.svg.text(x, # - self.width / 2, - y + size, size, w, label) + if self.cr_svg is not None: # and self.pendown: + _draw_text(self.cr_svg, label, x, y, size, w, self.tw.coord_scale, + self.heading, self.fgrgb) if self.tw.sharing() and share: event = 'W|%s' % (data_to_string([self._get_my_nick(), [label, round_int(x), @@ -640,21 +650,19 @@ class TurtleGraphics: x1, y1 = self.turtle_to_screen_coordinates(x1, y1) x2, y2 = self.turtle_to_screen_coordinates(x2, y2) - self.canvas.move_to(x1, y1) - self.canvas.line_to(x2, y2) - self.canvas.stroke() + def _draw_line(cr, x1, y1, x2, y2): + cr.move_to(x1, y1) + cr.line_to(x2, y2) + cr.stroke() + _draw_line(self.canvas, x1, y1, x2, y2) + if self.cr_svg is not None: + _draw_line(self.cr_svg, x1, y1, x2, y2) if self.fill: if self.poly_points == []: self.poly_points.append(('move', x1, y1)) self.poly_points.append(('line', x2, y2)) - if self.tw.saving_svg and self.pendown: - self.tw.svg_string += self.svg.new_path(x1, y1) - self.tw.svg_string += self.svg.line_to(x2, y2) - self.tw.svg_string += '"\n' - self.tw.svg_string += self.svg.style() - def turn_turtle(self): ''' Change the orientation of the turtle ''' self.tw.active_turtle.set_heading(self.heading) @@ -665,7 +673,8 @@ class TurtleGraphics: if self.tw.interactive_mode: self.tw.active_turtle.move( (int(self.cx + x - self.tw.active_turtle.spr.rect.width / 2.), - int(self.cy + y - self.tw.active_turtle.spr.rect.height / 2.))) + int(self.cy + y - self.tw.active_turtle.spr.rect.height / 2.)) + ) else: self.tw.active_turtle.move((int(self.cx + x), int(self.cy + y))) @@ -713,15 +722,14 @@ class TurtleGraphics: if x < 0 or x > (w - 1) or y < 0 or y > (h - 1): return(-1, -1, -1, -1) # create a new 1x1 cairo surface - cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1); + cs = cairo.ImageSurface(cairo.FORMAT_RGB24, 1, 1) cr = cairo.Context(cs) cr.set_source_surface(self.tw.turtle_canvas, -x, -y) - cr.rectangle(0,0,1,1) + cr.rectangle(0, 0, 1, 1) cr.set_operator(cairo.OPERATOR_SOURCE) cr.fill() - cs.flush() # ensure all writing is done - # Read the pixel - pixels = cs.get_data() + cs.flush() # ensure all writing is done + pixels = cs.get_data() # Read the pixel return (ord(pixels[2]), ord(pixels[1]), ord(pixels[0]), 0) else: return(-1, -1, -1, -1) @@ -754,14 +762,11 @@ class TurtleGraphics: def svg_close(self): ''' Close current SVG graphic ''' - if self.tw.svg_string == '': - return - self.svg.calc_w_h(False) - self.tw.svg_string = '%s %s %s %s' % ( - self.svg.header(True), - self.svg.background('#%02x%02x%02x' % ( - self.bgrgb[0], self.bgrgb[1], self.bgrgb[2])), - self.tw.svg_string, self.svg.footer()) + self.cr_svg.show_page() + + def svg_reset(self): + ''' Reset svg flags ''' + self.cr_svg = None def _get_my_nick(self): return self.tw.nick diff --git a/TurtleArt/taconstants.py b/TurtleArt/taconstants.py index 6bbaf69..7a82a42 100644 --- a/TurtleArt/taconstants.py +++ b/TurtleArt/taconstants.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -#Copyright (c) 2010-11 Walter Bender +#Copyright (c) 2010-12 Walter Bender #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to deal @@ -104,17 +104,6 @@ COLLAPSIBLE = ['sandwichbottom', 'sandwichcollapsed'] # OLD_DOCK = ['and', 'or', 'plus', 'minus', 'division', 'product', 'remainder'] -# -# Blocks that can interchange strings and numbers for their arguments -# -STRING_OR_NUMBER_ARGS = ['plus2', 'equal2', 'less2', 'greater2', 'box', - 'template1x1', 'template1x2', 'template2x1', 'list', - 'template2x2', 'template1x1a', 'templatelist', 'nop', - 'print', 'stack', 'hat', 'addturtle', 'myfunc', - 'myfunc1arg', 'myfunc2arg', 'myfunc3arg', 'comment', - 'sandwichtop', 'sandwichtop_no_arm', 'userdefined', - 'userdefined2args', 'userdefined3args', 'storein'] - CONTENT_ARGS = ['show', 'showaligned', 'push', 'storein', 'storeinbox1', 'storeinbox2'] diff --git a/TurtleArt/tagplay.py b/TurtleArt/tagplay.py index dbce7ed..72379c6 100644 --- a/TurtleArt/tagplay.py +++ b/TurtleArt/tagplay.py @@ -67,7 +67,7 @@ def play_movie_from_file(lc, filepath, x, y, w, h): def stop_media(lc): """ Called from Clean block and toolbar Stop button """ if lc.gplay == None: - return + return False if lc.gplay.player is not None: lc.gplay.player.stop() @@ -269,6 +269,7 @@ class GstPlayer(gobject.GObject): self.player.set_state(gst.STATE_NULL) self.playing = False logging.debug('stopped player') + return False def get_state(self, timeout=1): return self.player.get_state(timeout=timeout) diff --git a/TurtleArt/talogo.py b/TurtleArt/talogo.py index a2901eb..590797c 100644 --- a/TurtleArt/talogo.py +++ b/TurtleArt/talogo.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- #Copyright (c) 2007-8, Playful Invention Company. -#Copyright (c) 2008-11, Walter Bender +#Copyright (c) 2008-12, Walter Bender #Copyright (c) 2008-10, Raúl Gutiérrez Segalés #Permission is hereby granted, free of charge, to any person obtaining a copy @@ -62,10 +62,13 @@ class symbol: class logoerror(Exception): def __init__(self, value): + print value self.value = value def __str__(self): - return repr(self.value) + # return repr(self.value) + return str(self.value) + class HiddenBlock: @@ -82,6 +85,7 @@ class HiddenBlock: # Utility functions + def _just_stop(): """ yield False to stop stack """ yield False @@ -174,7 +178,6 @@ class LogoCode: self.stacks[k] = None self.stacks['stack1'] = None self.stacks['stack2'] = None - self.tw.saving_svg = False # Save state in case there is a hidden macro expansion self.save_blocks = None @@ -212,6 +215,7 @@ class LogoCode: x = b.connections[1].values[0] except IndexError: self.tw.showlabel('#nostack') + self.tw.showblocks() return None if type(convert(x, float, False)) == float: if int(float(x)) == x: @@ -249,8 +253,6 @@ class LogoCode: dock = blk.docks[0] if len(dock) > 4: # There could be a '(', ')', '[' or ']'. code.append(dock[4]) - if blk.name == 'savesvg': - self.tw.saving_svg = True if blk.primitive is not None: # make a tuple (prim, blk) # special case: expand 'while' and 'until' primitives try: @@ -265,8 +267,9 @@ class LogoCode: except ValueError: code.append(float(ord(blk.values[0][0]))) elif blk.name == 'string' or \ - blk.name == 'title': # deprecated block - if type(blk.values[0]) == float or type(blk.values[0]) == int: + blk.name == 'title': # deprecated block + if type(blk.values[0]) == float or \ + type(blk.values[0]) == int: if int(blk.values[0]) == blk.values[0]: blk.values[0] = int(blk.values[0]) code.append('#s' + str(blk.values[0])) @@ -342,13 +345,23 @@ class LogoCode: """ Step through the list. """ if self.tw.running_sugar: self.tw.activity.stop_turtle_button.set_icon("stopiton") + self.tw.activity.stop_turtle_button.set_tooltip( + _('Stop turtle')) elif self.tw.interactive_mode: self.tw.toolbar_shapes['stopiton'].set_layer(TAB_LAYER) self.running = True self.icall(self.evline, blklist) yield True if self.tw.running_sugar: - self.tw.activity.stop_turtle_button.set_icon("stopitoff") + # self.tw.activity.stop_turtle_button.set_icon("stopitoff") + if self.tw.step_time == 0 and self.tw.selected_blk is None: + self.tw.activity.stop_turtle_button.set_icon("hideshowoff") + self.tw.activity.stop_turtle_button.set_tooltip( + _('Show blocks')) + else: + self.tw.activity.stop_turtle_button.set_icon("stopitoff") + self.tw.activity.stop_turtle_button.set_tooltip( + _('Stop turtle')) elif self.tw.interactive_mode: self.tw.toolbar_shapes['stopiton'].hide() yield False @@ -403,6 +416,7 @@ class LogoCode: if self.bindex is not None: self.tw.block_list.list[self.bindex].highlight() + self.tw.showblocks() raise logoerror(str(self.iresult)) self.iline = oldiline self.ireturn() @@ -441,6 +455,7 @@ class LogoCode: self.cfun, self.arglist = token, [] if token.nargs == None: + self.tw.showblocks() raise logoerror("#noinput") for i in range(token.nargs): self._no_args_check() @@ -461,6 +476,7 @@ class LogoCode: result = self.cfun.fcn(self, *self.arglist) self.cfun, self.arglist = oldcfun, oldarglist if self.arglist is not None and result == None: + self.tw.showblocks() raise logoerror("%s %s %s" % \ (oldcfun.name, _("did not output to"), self.cfun.name)) self.ireturn(result) @@ -495,7 +511,8 @@ class LogoCode: self.tw.active_turtle.show() return False except logoerror, e: - self.tw.showlabel('syntaxerror', str(e)[1:-1]) + self.tw.showblocks() + self.tw.showlabel('syntaxerror', str(e)) self.tw.turtles.show_all() return False return True @@ -517,12 +534,14 @@ class LogoCode: errormsg = '' else: errormsg = "%s %s" % (_("I don't know how to"), _(token.name)) + self.tw.showblocks() raise logoerror(errormsg) def _no_args_check(self): """ Missing argument ? """ if self.iline and self.iline[0] is not self.symnothing: return + self.tw.showblocks() raise logoerror("#noinput") # @@ -542,7 +561,7 @@ class LogoCode: def prim_clear(self): """ Clear screen """ - self.tw.clear_plugins() + self.tw.clear_plugins() if self.tw.gst_available: from tagplay import stop_media # stop_media(self) # TODO: gplay variable @@ -562,6 +581,7 @@ class LogoCode: elif type(n) == str: return int(ord(n[0])) else: + self.tw.showblocks() raise logoerror("%s %s %s %s" \ % (self.cfun.name, _("doesn't like"), str(n), _("as input"))) @@ -660,8 +680,10 @@ class LogoCode: self.y2ty() - int(h / 2), w, h, self.filepath) elif offset: - self.tw.canvas.draw_pixbuf(self.pixbuf, 0, 0, self.x2tx(), - self.y2ty() - h, w, h, self.filepath) + self.tw.canvas.draw_pixbuf(self.pixbuf, 0, 0, + self.x2tx(), + self.y2ty() - h, + w, h, self.filepath) else: self.tw.canvas.draw_pixbuf(self.pixbuf, 0, 0, self.x2tx(), @@ -733,11 +755,11 @@ class LogoCode: # into trouble if any of these block types (forever, while, # until. ifelse, stopstack, or stack) is changed in tablock.py if b.name == 'while': - while_blk = True + while_blk = True else: while_blk = False if b.name == 'until': - until_blk = True + until_blk = True else: until_blk = False @@ -849,7 +871,8 @@ class LogoCode: c = whileflow.connections[0] whileflow.connections[0] = None code = self._blocks_to_code(whileflow) - self.stacks['stack3' + str(action_flow_name)] = self._readline(code) + self.stacks['stack3' + str(action_flow_name)] = \ + self._readline(code) whileflow.connections[0] = c # Save the connections so we can restore them later diff --git a/TurtleArt/tapalette.py b/TurtleArt/tapalette.py index da80386..ad96103 100644 --- a/TurtleArt/tapalette.py +++ b/TurtleArt/tapalette.py @@ -36,6 +36,7 @@ content_blocks = ['number', 'string', 'description', 'audio', 'video', hidden_proto_blocks = [] # proto blocks that are (at least initially) hidden value_blocks = [] # blocks whose labels are updated get added here special_block_colors = {} +string_or_number_args = [] block_styles = {'basic-style': [], 'blank-style': [], 'basic-style-head': [], @@ -86,6 +87,8 @@ from sugar.graphics import style from taconstants import EXPANDABLE_STYLE from tautils import debug_output +from util.helpbutton import add_section, add_paragraph + from gettext import gettext as _ help_strings = { @@ -101,26 +104,26 @@ class Palette(): self._name = name self._special_name = _(name) self._colors = colors - self._help = None self._max_text_width = int(gtk.gdk.screen_width() / 3) - 20 # Prepare a vbox for the help palette - if not (self._name in help_palettes): + if not self._name in help_palettes: self._help_box = gtk.VBox() self._help_box.set_homogeneous(False) help_palettes[self._name] = self._help_box + help_windows[self._name] = gtk.ScrolledWindow() + help_windows[self._name].set_size_request( + int(gtk.gdk.screen_width() / 3), + gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 3) + help_windows[self._name].set_policy( + gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) + help_windows[self._name].add_with_viewport( + help_palettes[self._name]) + help_palettes[self._name].show() + self._help = None else: self._help_box = help_palettes[self._name] - - help_windows[self._name] = gtk.ScrolledWindow() - help_windows[self._name].set_size_request( - int(gtk.gdk.screen_width() / 3), - gtk.gdk.screen_height() - style.GRID_CELL_SIZE * 3) - help_windows[self._name].set_policy( - gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC) - help_windows[self._name].add_with_viewport( - help_palettes[self._name]) - help_palettes[self._name].show() + self._help = 'deja vu' def add_palette(self, position=None): if self._name is None: @@ -141,7 +144,6 @@ class Palette(): palette_blocks.insert(i, []) block_colors.insert(i, self._colors) else: - # debug_output('Palette %s already defined' % (self._name)) return # Special name entry is needed for help hover mechanism @@ -151,48 +153,11 @@ class Palette(): else: help_strings[self._name] = '' - def add_section(self, section_text, icon=None): - ''' Add a section to the help palette. From helpbutton.py by - Gonzalo Odiard ''' - hbox = gtk.HBox() - label = gtk.Label() - label.set_use_markup(True) - label.set_markup('%s' % section_text) - label.set_line_wrap(True) - label.set_size_request(self._max_text_width, -1) - hbox.add(label) - if icon is not None: - _icon = Icon(icon_name=icon) - hbox.add(_icon) - label.set_size_request(self._max_text_width - 20, -1) - else: - label.set_size_request(self._max_text_width, -1) - - hbox.show_all() - self._help_box.pack_start(hbox, False, False, padding=5) - - def add_paragraph(self, text, icon=None): - ''' Add an entry to the help palette. From helpbutton.py by - Gonzalo Odiard ''' - 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(self._max_text_width - 20, -1) - else: - label.set_size_request(self._max_text_width, -1) - - hbox.show_all() - self._help_box.pack_start(hbox, False, False, padding=5) - def set_help(self, help): - self._help = help - if hasattr(self, '_help_box'): - self.add_section(self._help, icon=self._name + 'off') + if self._help is None: + self._help = help + if hasattr(self, '_help_box'): + add_section(self._help_box, self._help, icon=self._name + 'off') def set_special_name(self, name): self._special_name = name @@ -200,7 +165,8 @@ class Palette(): def add_block(self, block_name, style='basic-block', label=None, special_name=None, default=None, prim_name=None, help_string=None, value_block=False, content_block=False, - logo_command=None, hidden=False, colors=None): + logo_command=None, hidden=False, colors=None, + string_or_number=False): """ Add a new block to the palette """ block = Block(block_name) block.set_style(style) @@ -220,15 +186,23 @@ class Palette(): if help_string is not None: block.set_help(help_string) if not hidden: + first_arg = None if special_name is None: if type(label) == list: - self.add_paragraph('%s: %s' % (label[0], help_string)) + first_arg = label[0] else: - self.add_paragraph('%s: %s' % (label, help_string)) + first_arg = label + else: + first_arg = special_name + if first_arg is None or first_arg == '' or first_arg == ' ': + add_paragraph(self._help_box, '%s' % (help_string)) else: - self.add_paragraph('%s: %s' % (special_name, help_string)) + add_paragraph(self._help_box, '%s: %s' % (first_arg, + help_string)) if colors is not None: block.set_colors(colors) + if string_or_number: + block.set_string_or_number() block.set_value_block(value_block) block.set_content_block(content_block) block.set_palette(self._name) @@ -236,6 +210,7 @@ class Palette(): block.set_hidden() block.add_block() + def make_palette(palette_name, colors=None, help_string=None, position=None): """ Palette helper function """ if colors is None: @@ -279,6 +254,7 @@ class Block(): self._content_block = False self._colors = None self._hidden = False + self._string_or_number = False def add_block(self, position=None): if self._name is None: @@ -301,13 +277,17 @@ class Block(): if self._palette is not None: i = palette_names.index(self._palette) - if position is not None and type(position) is int and \ - position < len(palette_blocks[i]): - palette_blocks[i].insert(position, self._name) + if self._name in palette_blocks[i]: + debug_output('%s already in palette %s, skipping...' % ( + self._name, self._palette)) else: - palette_blocks[i].append(self._name) - if position is not None: - debug_output('Ignoring position (%s)' % (str(position))) + if position is not None and type(position) is int and \ + position < len(palette_blocks[i]): + palette_blocks[i].insert(position, self._name) + else: + palette_blocks[i].append(self._name) + if position is not None: + debug_output('Ignoring position (%s)' % (str(position))) if self._help is not None: help_strings[self._name] = self._help @@ -338,6 +318,9 @@ class Block(): if self._colors is not None: special_block_colors[self._name] = self._colors + if self._string_or_number: + string_or_number_args.append(self._name) + if self._hidden: hidden_proto_blocks.append(self._name) @@ -347,6 +330,9 @@ class Block(): def set_colors(self, colors=None): self._colors = colors + def set_string_or_number(self, flag=True): + self._string_or_number = flag + def set_value_block(self, value=True): self._value_block = value diff --git a/TurtleArt/tasprite_factory.py b/TurtleArt/tasprite_factory.py index b750aad..2b0e922 100755 --- a/TurtleArt/tasprite_factory.py +++ b/TurtleArt/tasprite_factory.py @@ -595,6 +595,31 @@ class SVG: svg += self.footer() return self.header() + svg + def status_block(self, graphic=None): + ''' Generate a status block ''' + self.reset_min_max() + (x, y) = self._calculate_x_y() + self.margins[2] = 0 + self.margins[3] = 0 + svg = self.new_path(x, y) + svg += self._corner(1, -1) + svg += self._rline_to(self._expand_x, 0) + xx = self._x + svg += self._corner(1, 1) + svg += self._rline_to(0, self._expand_y) + svg += self._corner(-1, 1) + svg += self.line_to(xx, self._y) + svg += self._rline_to(-self._expand_x, 0) + svg += self._corner(-1, -1) + svg += self._rline_to(0, -self._expand_y) + self.calc_w_h() + svg += self._close_path() + svg += self.style() + if self._hide is True: + svg += self._hide_dot() + svg += self.footer() + return self.header() + svg + # # Utility methods # diff --git a/TurtleArt/taturtle.py b/TurtleArt/taturtle.py index c13c494..c70f379 100644 --- a/TurtleArt/taturtle.py +++ b/TurtleArt/taturtle.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -#Copyright (c) 2010,11 Walter Bender +#Copyright (c) 2010,12 Walter Bender #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to deal @@ -129,10 +129,10 @@ class Turtle: self._prep_shapes(key, turtles, turtle_colors) - # Choose a random angle from which to attach the turtle label + # Choose a random angle from which to attach the turtle label. if turtles.sprite_list is not None: self.spr = Sprite(turtles.sprite_list, 0, 0, self.shapes[0]) - angle = uniform(0, pi * 4 / 3.0) # 240 degrees + angle = uniform(0, pi * 4 / 3.0) # 240 degrees w = self.shapes[0].get_width() r = w * 0.67 # Restrict angle the the sides 30-150; 210-330 diff --git a/TurtleArt/tautils.py b/TurtleArt/tautils.py index 97b396d..40c39e9 100644 --- a/TurtleArt/tautils.py +++ b/TurtleArt/tautils.py @@ -1,5 +1,5 @@ #Copyright (c) 2007-8, Playful Invention Company. -#Copyright (c) 2008-11, Walter Bender +#Copyright (c) 2008-12, Walter Bender #Permission is hereby granted, free of charge, to any person obtaining a copy #of this software and associated documentation files (the "Software"), to deal @@ -274,7 +274,10 @@ def save_picture(canvas, file_name): cr = cairo.Context(img_surface) cr.set_source_surface(x_surface) cr.paint() - img_surface.write_to_png(file_name) + if type(file_name) == unicode: + img_surface.write_to_png(str(file_name.encode('ascii', 'replace'))) + else: + img_surface.write_to_png(str(file_name)) def get_canvas_data(canvas): @@ -288,13 +291,6 @@ def get_canvas_data(canvas): return img_surface.get_data() -def save_svg(string, file_name): - ''' Write a string to a file. ''' - file_handle = file(file_name, 'w') - file_handle.write(string) - file_handle.close() - - def get_pixbuf_from_journal(dsobject, w, h): ''' Load a pixbuf from a Journal object. ''' try: @@ -798,7 +794,7 @@ def find_blk_below(blk, name): if blk == None or len(blk.connections) == 0: return group = find_group(blk) - for gblk in _group: + for gblk in group: if gblk.name == name: return gblk return None diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py index 20eeb34..b7523e5 100644 --- a/TurtleArt/tawindow.py +++ b/TurtleArt/tawindow.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- #Copyright (c) 2007, Playful Invention Company -#Copyright (c) 2008-11, Walter Bender +#Copyright (c) 2008-12, Walter Bender #Copyright (c) 2009-11 Raúl Gutiérrez Segalés #Copyright (c) 2011 Collabora Ltd. @@ -36,6 +36,7 @@ except ImportError: GST_AVAILABLE = False import os +import subprocess from math import atan2, pi DEGTOR = 2 * pi / 360 @@ -43,7 +44,7 @@ DEGTOR = 2 * pi / 360 import locale from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ - MEDIA_SHAPES, STATUS_SHAPES, OVERLAY_SHAPES, STRING_OR_NUMBER_ARGS, \ + MEDIA_SHAPES, STATUS_SHAPES, OVERLAY_SHAPES, \ TOOLBAR_SHAPES, TAB_LAYER, RETURN, OVERLAY_LAYER, CATEGORY_LAYER, \ BLOCKS_WITH_SKIN, ICON_SIZE, PALETTE_SCALE, PALETTE_WIDTH, SKIN_PATHS, \ MACROS, TOP_LAYER, BLOCK_LAYER, OLD_NAMES, DEFAULT_TURTLE, TURTLE_LAYER, \ @@ -53,7 +54,7 @@ from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ CONSTANTS, EXPAND_SKIN, PROTO_LAYER from tapalette import palette_names, palette_blocks, expandable_blocks, \ block_names, content_blocks, default_values, special_names, block_styles, \ - help_strings, hidden_proto_blocks + help_strings, hidden_proto_blocks, string_or_number_args from talogo import LogoCode from tacanvas import TurtleGraphics from tablock import Blocks, Block @@ -61,7 +62,7 @@ from taturtle import Turtles, Turtle from tautils import magnitude, get_load_name, get_save_name, data_from_file, \ data_to_file, round_int, get_id, get_pixbuf_from_journal, \ movie_media_type, audio_media_type, image_media_type, save_picture, \ - save_svg, calc_image_size, get_path, reset_stack_arm, grow_stack_arm, \ + calc_image_size, get_path, reset_stack_arm, grow_stack_arm, \ find_sandwich_top, find_sandwich_bottom, restore_stack, collapse_stack, \ collapsed, collapsible, hide_button_hit, show_button_hit, chooser, \ arithmetic_check, xy, find_block_to_run, find_top_block, journal_check, \ @@ -76,6 +77,7 @@ if GST_AVAILABLE: MOTION_THRESHOLD = 6 SNAP_THRESHOLD = 200 + class TurtleArtWindow(): """ TurtleArt Window class abstraction """ timeout_tag = [0] @@ -199,10 +201,9 @@ class TurtleArtWindow(): self.drag_group = None self.drag_turtle = 'move', 0, 0 self.drag_pos = 0, 0 + self.dragging_canvas = [False, 0, 0] self.turtle_movement_to_share = None self.paste_offset = 20 # Don't paste on top of where you copied. - self.saving_svg = False - self.svg_string = '' self.block_list = Blocks(font_scale_factor=self.scale, decimal_point=self.decimal_point) @@ -289,29 +290,25 @@ class TurtleArtWindow(): """ Try importing plugin files from the plugin dir. """ for plugin_dir in self._get_plugins_from_plugins_dir( self._get_plugin_home()): - plugin_class = plugin_dir.capitalize() - f = "def f(self): from plugins.%s.%s import %s; return %s(self)" \ - % (plugin_dir, plugin_dir, plugin_class, plugin_class) - plugins = {} - try: - exec f in globals(), plugins - self._plugins.append(plugins.values()[0](self)) - debug_output('successfully importing %s' % (plugin_class), - self.running_sugar) - except ImportError, e: - debug_output('failed to import %s: %s' % (plugin_class, str(e)), - self.running_sugar) - ''' + self.init_plugin(plugin_dir) + + def init_plugin(self, plugin_dir): + """ Initialize plugin in plugin_dir """ + plugin_class = plugin_dir.capitalize() + f = "def f(self): from plugins.%s.%s import %s; return %s(self)" \ + % (plugin_dir, plugin_dir, plugin_class, plugin_class) + plugins = {} + try: exec f in globals(), plugins self._plugins.append(plugins.values()[0](self)) - debug_output('successfully importing %s' % (plugin_class)) - ''' - - # Add the icon dir for each plugin to the icon_theme search path - for plugin_dir in self._get_plugins_from_plugins_dir( - self._get_plugin_home()): + debug_output('Successfully importing %s' % (plugin_class), + self.running_sugar) + # Add the icon dir to the icon_theme search path self._add_plugin_icon_dir(os.path.join(self._get_plugin_home(), plugin_dir)) + except ImportError, e: + debug_output('Failed to import %s: %s' % (plugin_class, str(e)), + self.running_sugar) def _add_plugin_icon_dir(self, dirname): ''' If there is an icon subdir, add it to the search path. ''' @@ -347,7 +344,7 @@ class TurtleArtWindow(): plugin.stop() def clear_plugins(self): - """ Clear is called from the clean block and erase button. """ + """ Clear is called from the clean block and erase button. """ for plugin in self._plugins: if hasattr(plugin, 'clear'): plugin.clear() @@ -380,10 +377,11 @@ class TurtleArtWindow(): self.window.connect("motion-notify-event", self._move_cb) self.window.connect("key-press-event", self._keypress_cb) - def _setup_misc(self): - """ Misc. sprites for status, overlays, etc. """ - # media blocks get positioned into other blocks + def load_media_shapes(self): + """ Media shapes get positioned onto blocks """ for name in MEDIA_SHAPES: + if name in self.media_shapes: + continue if name[0:7] == 'journal' and not self.running_sugar: filename = 'file' + name[7:] else: @@ -396,9 +394,17 @@ class TurtleArtWindow(): os.path.join(self.path, path, filename + '.svg'))) break + def _setup_misc(self): + """ Misc. sprites for status, overlays, etc. """ + self.load_media_shapes() for i, name in enumerate(STATUS_SHAPES): - self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file( - os.path.join(self.path, 'images', name + '.svg'))) + # Temporary hack to use wider shapes + if name in ['print', 'help', 'status'] and self.width > 1024: + self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file( + os.path.join(self.path, 'images', name + '1200.svg'))) + else: + self.status_shapes[name] = svg_str_to_pixbuf(svg_from_file( + os.path.join(self.path, 'images', name + '.svg'))) self.status_spr = Sprite(self.sprite_list, 0, self.height - 200, self.status_shapes['status']) self.status_spr.hide() @@ -414,7 +420,8 @@ class TurtleArtWindow(): self.overlay_shapes[name].type = 'overlay' if not self.running_sugar: - offset = self.width - 55 * len(TOOLBAR_SHAPES) + # offset = 2 * self.width - 55 * len(TOOLBAR_SHAPES) + offset = 55 * (2 + len(palette_blocks)) for i, name in enumerate(TOOLBAR_SHAPES): self.toolbar_shapes[name] = Sprite( self.sprite_list, i * 55 + offset, 0, @@ -459,6 +466,10 @@ class TurtleArtWindow(): # Create the cairo context cr = self.window.window.cairo_create() + # TODO: set global scale + # find_sprite needs rescaled coordinates + # sw needs new bounds set + # cr.scale(self.activity.global_x_scale, self.activity.global_y_scale) if event is None: cr.rectangle(self.rect.x, self.rect.y, @@ -484,7 +495,7 @@ class TurtleArtWindow(): self.lc.prim_clear() self.display_coordinates() - def run_button(self, time): + def run_button(self, time, running_from_button_push=False): """ Run turtle! """ if self.running_sugar: self.activity.recenter() @@ -495,6 +506,10 @@ class TurtleArtWindow(): self.step_time = time debug_output("running stack starting from %s" % (blk.name), self.running_sugar) + if running_from_button_push: + self.selected_blk = None + else: + self.selected_blk = blk self._run_stack(blk) return @@ -504,6 +519,10 @@ class TurtleArtWindow(): self.step_time = time debug_output("running stack starting from %s" % (blk.name), self.running_sugar) + if running_from_button_push: + self.selected_blk = None + else: + self.selected_blk = blk self._run_stack(blk) return @@ -588,6 +607,8 @@ class TurtleArtWindow(): if not self.hide: for blk in self.just_blocks(): blk.spr.hide() + for spr in self.triangle_sprs: + spr.hide() self.hide_palette() self.hide = True else: @@ -629,6 +650,7 @@ class TurtleArtWindow(): self.show_toolbar_palette(n) self.palette_button[self.orientation].set_layer(TAB_LAYER) self.palette_button[2].set_layer(TAB_LAYER) + self._display_palette_shift_button(n) if self.activity is None or not self.activity.has_toolbarbox: self.toolbar_spr.set_layer(CATEGORY_LAYER) self.palette = True @@ -638,6 +660,8 @@ class TurtleArtWindow(): self._hide_toolbar_palette() self.palette_button[self.orientation].hide() self.palette_button[2].hide() + self.palette_button[3].hide() + self.palette_button[4].hide() if self.activity is None or not self.activity.has_toolbarbox: self.toolbar_spr.hide() self.palette = False @@ -715,6 +739,25 @@ class TurtleArtWindow(): if blk.name in BLOCKS_WITH_SKIN: self._resize_skin(blk) + def _shift_toolbar_palette(self, n): + ''' Shift blocks on specified palette ''' + x, y = self.palette_sprs[n][self.orientation].get_xy() + w, h = self.palette_sprs[n][self.orientation].get_dimensions() + bx, by = self.palettes[n][0].spr.get_xy() + if self.orientation == 0: + dx = w - self.width + dy = 0 + if bx - x > 0: + dx *= -1 + else: + dx = 0 + dy = h - self.height + ICON_SIZE + if by - y > 0: + dy *= -1 + for blk in self.palettes[n]: + if blk.get_visibility(): + blk.spr.move_relative((dx, dy)) + def show_toolbar_palette(self, n, init_only=False, regenerate=False, show=True): """ Show the toolbar palettes, creating them on init_only """ @@ -746,7 +789,8 @@ class TurtleArtWindow(): # Make sure all of the selectors are visible. (We don't need to do # this for 0.86+ toolbars since the selectors are toolbar buttons.) - if show and (self.activity is None or not self.activity.has_toolbarbox): + if show and \ + (self.activity is None or not self.activity.has_toolbarbox): self.selected_selector = self.selectors[n] self.selectors[n].set_shape(self.selector_shapes[n][1]) for i in range(len(palette_blocks)): @@ -754,7 +798,9 @@ class TurtleArtWindow(): # Show the palette with the current orientation. if self.palette_sprs[n][self.orientation] is not None: - self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) + self.palette_sprs[n][self.orientation].set_layer( + CATEGORY_LAYER) + self._display_palette_shift_button(n) # Create 'proto' blocks for each palette entry self._create_proto_blocks(n) @@ -784,6 +830,20 @@ class TurtleArtWindow(): self.selected_palette = save_selected self.previous_palette = save_previous + def _display_palette_shift_button(self, n): + ''' Palettes too wide (or tall) for the screen get a shift button ''' + if self.palette_sprs[n][self.orientation].type == \ + 'category-shift-horizontal': + self.palette_button[3].set_layer(CATEGORY_LAYER) + self.palette_button[4].hide() + elif self.palette_sprs[n][self.orientation].type == \ + 'category-shift-vertical': + self.palette_button[3].hide() + self.palette_button[4].set_layer(CATEGORY_LAYER) + else: + self.palette_button[3].hide() + self.palette_button[4].hide() + def _create_the_selectors(self): ''' Create the palette selector buttons: only when running old-style Sugar toolbars or from GNOME ''' @@ -824,7 +884,7 @@ class TurtleArtWindow(): # Create the toolbar background for the selectors self.toolbar_offset = ICON_SIZE self.toolbar_spr = Sprite(self.sprite_list, 0, 0, - svg_str_to_pixbuf(svg.toolbar(self.width, ICON_SIZE))) + svg_str_to_pixbuf(svg.toolbar(2 * self.width, ICON_SIZE))) self.toolbar_spr.type = 'toolbar' self.toolbar_spr.set_layer(CATEGORY_LAYER) @@ -860,11 +920,32 @@ class TurtleArtWindow(): self.palette_button[2].type = 'palette' self.palette_button[2].set_layer(TAB_LAYER) + # Create the palette shift buttons + dims = self.palette_button[0].get_dimensions() + self.palette_button.append(Sprite(self.sprite_list, 0, + self.toolbar_offset + dims[1], svg_str_to_pixbuf(svg_from_file( + "%s/images/palettehshift.svg" % (self.path))))) + self.palette_button.append(Sprite(self.sprite_list, dims[0], + self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( + "%s/images/palettevshift.svg" % (self.path))))) + self.palette_button[3].name = _('shift') + self.palette_button[4].name = _('shift') + self.palette_button[3].type = 'palette' + self.palette_button[4].type = 'palette' + self.palette_button[3].hide() + self.palette_button[4].hide() + def _create_proto_blocks(self, n): ''' Create the protoblocks that will populate a palette. ''' # Reload the palette, but reuse the existing blocks # If a block doesn't exist, add it + if not n < len(self.palettes): + debug_output( + '_create_proto_blocks: palette index %d is out of range' % (n), + self.running_sugar) + return + for blk in self.palettes[n]: blk.spr.hide() old_blocks = self.palettes[n][:] @@ -900,7 +981,7 @@ class TurtleArtWindow(): elif name in PYTHON_SKIN: self._proto_skin('pythonsmall', n, -1) return - + def _hide_toolbar_palette(self): """ Hide the toolbar palettes """ self._hide_previous_palette() @@ -919,6 +1000,11 @@ class TurtleArtWindow(): palette = self.previous_palette # Hide previously selected palette if palette is not None: + if not palette < len(self.palettes): + debug_output( + '_hide_previous_palette: index %d is out of range' % \ + (palette), self.running_sugar) + return for proto in self.palettes[palette]: proto.spr.hide() if self.palette_sprs[palette][self.orientation] is not None: @@ -1031,11 +1117,14 @@ class TurtleArtWindow(): self.palette_button[2].move((PALETTE_WIDTH - 20, self.toolbar_offset)) if show: - self.palette_button[2].save_xy = self.palette_button[2].get_xy() + self.palette_button[2].save_xy = \ + self.palette_button[2].get_xy() if self.running_sugar and not self.hw in [XO1]: self.palette_button[2].move_relative( (self.activity.hadj_value, self.activity.vadj_value)) - self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) + self.palette_sprs[n][self.orientation].set_layer( + CATEGORY_LAYER) + self._display_palette_shift_button(n) def _make_palette_spr(self, n, x, y, w, h, regenerate=False): ''' Make the background for the palette. ''' @@ -1051,7 +1140,14 @@ class TurtleArtWindow(): if self.running_sugar and not self.hw in [XO1]: self.palette_sprs[n][self.orientation].move_relative( (self.activity.hadj_value, self.activity.vadj_value)) - self.palette_sprs[n][self.orientation].type = 'category' + if self.orientation == 0 and w > self.width: + self.palette_sprs[n][self.orientation].type = \ + 'category-shift-horizontal' + elif self.orientation == 1 and h > self.height - ICON_SIZE: + self.palette_sprs[n][self.orientation].type = \ + 'category-shift-vertical' + else: + self.palette_sprs[n][self.orientation].type = 'category' if n == palette_names.index('trash'): svg = SVG() self.palette_sprs[n][self.orientation].set_shape( @@ -1075,7 +1171,8 @@ class TurtleArtWindow(): # Unselect things that may have been selected earlier if self.selected_blk is not None: - if self.selected_blk.name == 'number' and spr in self.triangle_sprs: + if self.selected_blk.name == 'number' and \ + spr in self.triangle_sprs: # increment or decrement a number block nf = float(self.selected_blk.spr.labels[0].replace(CURSOR, '')) ni = int(nf) @@ -1087,7 +1184,7 @@ class TurtleArtWindow(): n += 1 else: n -= 1 - self.selected_blk.spr.set_label(str(n) + CURSOR) + self.selected_blk.spr.set_label(str(n) + CURSOR) return True self._unselect_block() self.selected_turtle = None @@ -1098,8 +1195,12 @@ class TurtleArtWindow(): self.dx = 0 self.dy = 0 + self.dragging_canvas[1] = x + self.dragging_canvas[2] = y if spr is None: + self.dragging_canvas[0] = True return True + self.dragging_canvas[0] = False self.selected_spr = spr # From the sprite at x, y, look for a corresponding block @@ -1174,7 +1275,8 @@ class TurtleArtWindow(): if hasattr(spr, 'type'): if spr.type == 'selector': self._select_category(spr) - elif spr.type == 'category': + elif spr.type in ['category', 'category-shift-horizontal', + 'category-shift-vertical']: if hide_button_hit(spr, x, y): self.hideshow_palette(False) elif spr.type == 'palette': @@ -1198,6 +1300,8 @@ class TurtleArtWindow(): self.activity.palette_buttons[i].set_icon( palette_names[i] + 'on') self.show_palette(i) + elif spr.name == _('shift'): + self._shift_toolbar_palette(self.selected_palette) else: self.orientation = 1 - self.orientation self.palette_button[self.orientation].set_layer(TAB_LAYER) @@ -1229,6 +1333,7 @@ class TurtleArtWindow(): return if spr.name == 'run-fastoff': self.lc.trace = 0 + self.hideblocks() self.run_button(0) elif spr.name == 'run-slowoff': self.lc.trace = 1 @@ -1430,7 +1535,6 @@ class TurtleArtWindow(): newblk.connections[i + 1] = argblk self.drag_group = find_group(newblk) self.block_operation = 'new' - debug_output(newblk.name, True) if len(newblk.spr.labels) > 0 and newblk.spr.labels[0] is not None \ and newblk.name not in ['', 'number', 'string']: if len(self.used_block_list) > 0: @@ -1600,6 +1704,15 @@ class TurtleArtWindow(): def _mouse_move(self, x, y): """ Process mouse movements """ + + if self.running_sugar and self.dragging_canvas[0]: + dx = self.dragging_canvas[1] - x + dy = self.dragging_canvas[2] - y + self.dragging_canvas[1] = x + self.dragging_canvas[2] = y + self.activity.adjust_sw(dx, dy) + return True + self.block_operation = 'move' # First, check to see if we are dragging or rotating a turtle. @@ -1768,6 +1881,13 @@ class TurtleArtWindow(): return True def button_release(self, x, y): + if self.running_sugar and self.dragging_canvas[0]: + self.dragging_canvas[0] = False + self.dragging_canvas[1] = x + self.dragging_canvas[2] = y + self.activity.adjust_palette() + return True + # We may have been moving the turtle if self.selected_turtle is not None: (tx, ty) = self.selected_turtle.get_xy() @@ -2112,6 +2232,10 @@ class TurtleArtWindow(): if blk is None: return self.lc.find_value_blocks() # Are there blocks to update? + # Is there a savesvg block? + if len(self.block_list.get_similar_blocks('block', 'savesvg')) > 0: + if self.canvas.cr_svg is None: + self.canvas.setup_svg_surface() self._start_plugins() # Let the plugins know we are running. top = find_top_block(blk) self.lc.run_blocks(top, self.just_blocks(), True) @@ -2184,7 +2308,8 @@ class TurtleArtWindow(): if best_destination_dockn == 2 and \ (selected_block.name in block_styles['boolean-style'] or \ selected_block.name in block_styles['compare-style'] or \ - selected_block.name in block_styles['compare-porch-style']): + selected_block.name in block_styles['compare-porch-style'] + ): dy = selected_block.ey - best_destination.ey if selected_block.name in block_styles['boolean-style']: # Even without expanding, boolean blocks are @@ -2607,7 +2732,6 @@ class TurtleArtWindow(): else: n = 0 self.selected_blk.spr.set_label(str(n)) - debug_output(str(n), True) try: self.selected_blk.values[0] = \ float(str(n).replace(self.decimal_point, '.')) @@ -3072,7 +3196,10 @@ class TurtleArtWindow(): label = '' self.status_spr.set_shape(self.status_shapes[shp]) self.status_spr.set_label_attributes(12.0, rescale=False) - self.status_spr.set_label(str(label)) + if shp == 'status': + self.status_spr.set_label('"%s"' % (str(label))) + else: + self.status_spr.set_label(str(label)) self.status_spr.set_layer(STATUS_LAYER) if shp == 'info': self.status_spr.move((PALETTE_WIDTH, self.height - 400)) @@ -3136,10 +3263,9 @@ class TurtleArtWindow(): file_path = os.path.join(datapath, filename) if svg: - if self.svg_string == '': + if self.canvas.cr_svg is None: return - save_svg(self.svg_string, file_path) - self.svg_string = '' + self.canvas.svg_reset() else: save_picture(self.canvas, file_path) @@ -3156,14 +3282,22 @@ class TurtleArtWindow(): dsobject.metadata['icon-color'] = profile.get_color().to_string() if svg: dsobject.metadata['mime_type'] = 'image/svg+xml' + dsobject.set_file_path(os.path.join(datapath, 'output.svg')) else: dsobject.metadata['mime_type'] = 'image/png' - dsobject.set_file_path(file_path) + dsobject.set_file_path(file_path) datastore.write(dsobject) dsobject.destroy() self.saved_pictures.append((dsobject.object_id, svg)) - os.remove(file_path) + if svg: + os.remove(os.path.join(datapath, 'output.svg')) + else: + os.remove(file_path) else: + if svg: + output = subprocess.check_output( + ['mv', os.path.join(datapath, 'output.svg'), + os.path.join(datapath, filename)]) self.saved_pictures.append((file_path, svg)) def just_blocks(self): @@ -3275,7 +3409,7 @@ def dock_dx_dy(block1, dock1n, block2, dock2n): block2.connections[dock2n] is not None: return (100, 100) if _d1type != _d2type: - if block1.name in STRING_OR_NUMBER_ARGS: + if block1.name in string_or_number_args: if _d2type == 'number' or _d2type == 'string': pass elif block1.name in CONTENT_ARGS: diff --git a/TurtleConfusionActivity.py b/TurtleConfusionActivity.py index 9c2d9d9..2f28b84 100644 --- a/TurtleConfusionActivity.py +++ b/TurtleConfusionActivity.py @@ -271,8 +271,10 @@ class TurtleConfusionActivity(activity.Activity): if not self.has_toolbarbox: self.palette_buttons[i].set_icon(palette_names[i] + 'on') + ''' else: self._help_button.set_current_palette(palette_names[i]) + ''' self.tw.show_palette(i) self.do_showpalette() @@ -477,8 +479,10 @@ class TurtleConfusionActivity(activity.Activity): self.read_file(os.path.join( activity.get_bundle_path(), 'challenges', 'help-' + str(self._level + 1) + '.ta'), run_it=False) + ''' else: self.hover_help_label.set_label(_("no help available")) + ''' def get_document_path(self, async_cb, async_err_cb): ''' View TA code as part of view source. ''' @@ -565,8 +569,9 @@ class TurtleConfusionActivity(activity.Activity): 'ta-open', _('Load example'), self.do_samples_cb, self._toolbox.toolbar) - self._help_button = HelpButton() - self._toolbox.toolbar.insert(self._help_button, -1) + self._help_button = self._add_button( + 'help-toolbar', _('Help'), self._do_help_cb, + self._toolbox.toolbar) stop_button = StopButton(self) stop_button.props.accelerator = 'Q' @@ -664,10 +669,6 @@ class TurtleConfusionActivity(activity.Activity): self.save_as_image = self._add_button( 'image-saveoff', _('Save as image'), self.do_save_as_image_cb, toolbar) - ''' - self.save_as_html = self._add_button( - 'htmloff', _('Save as HTML'), self.do_save_as_html_cb, toolbar) - ''' self.save_as_logo = self._add_button( 'logo-saveoff', _('Save as Logo'), self.do_save_as_logo_cb, toolbar) @@ -678,11 +679,6 @@ class TurtleConfusionActivity(activity.Activity): self.load_ta_project = self._add_button( 'load-from-journal', _('Import project from the Journal'), self.do_load_ta_project_cb, toolbar) - ''' - self.load_python = self._add_button( - 'pippy-openoff', _('Load Python block'), self.do_load_python_cb, - toolbar) - ''' if not self.has_toolbarbox: self.samples_button = self._add_button( 'ta-open', _('Load example'), self.do_samples_cb, toolbar) @@ -710,8 +706,6 @@ class TurtleConfusionActivity(activity.Activity): 'run-fastoff', _('Run'), self.do_run_cb, toolbar, _('r')) self.step_button = self._add_button( 'run-slowoff', _('Step'), self.do_step_cb, toolbar, _('w')) - self.debug_button = self._add_button( - 'debugoff', _('Debug'), self.do_debug_cb, toolbar, _('d')) self.stop_turtle_button = self._add_button( 'stopitoff', _('Stop turtle'), self.do_stop_cb, toolbar, _('s')) diff --git a/activity/activity.info b/activity/activity.info index 7963c26..6aed98a 100644 --- a/activity/activity.info +++ b/activity/activity.info @@ -1,6 +1,6 @@ [Activity] name = Turtle Confusion -activity_version = 9 +activity_version = 10 license = MIT bundle_id = org.laptop.TurtleConfusionActivity exec = sugar-activity TurtleConfusionActivity.TurtleConfusionActivity diff --git a/images/help1200.svg b/images/help1200.svg new file mode 100644 index 0000000..a284973 --- /dev/null +++ b/images/help1200.svg @@ -0,0 +1,50 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + X + + + diff --git a/images/palettehshift.svg b/images/palettehshift.svg new file mode 100644 index 0000000..38158aa --- /dev/null +++ b/images/palettehshift.svg @@ -0,0 +1,86 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/palettevshift.svg b/images/palettevshift.svg new file mode 100644 index 0000000..504272f --- /dev/null +++ b/images/palettevshift.svg @@ -0,0 +1,86 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/images/print1200.svg b/images/print1200.svg new file mode 100644 index 0000000..e94402e --- /dev/null +++ b/images/print1200.svg @@ -0,0 +1,50 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + X + + + diff --git a/images/status1200.svg b/images/status1200.svg new file mode 100644 index 0000000..6b64812 --- /dev/null +++ b/images/status1200.svg @@ -0,0 +1,80 @@ + + + + + + + + image/svg+xml + + + + + + + + + + + X + + + + + + + + + ! + + diff --git a/po/TurtleConfusion.pot b/po/TurtleConfusion.pot index 92799af..747cff2 100644 --- a/po/TurtleConfusion.pot +++ b/po/TurtleConfusion.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2011-08-03 10:17-0400\n" +"POT-Creation-Date: 2011-08-29 09:03-0400\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,271 +17,670 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -#: activity/activity.info:2 turtleconfusion.py:272 -msgid "Turtle Confusion" +#: activity/activity.info:2 turtleart.py:272 pysamples/grecord.py:205 +#: TurtleArt/tawindow.py:1568 TurtleArt/tawindow.py:2793 +#: TurtleArt/taexporthtml.py:127 TurtleArt/taexporthtml.py:129 +msgid "Turtle Art" msgstr "" -#: turtleconfusion.py:68 +#: turtleart.py:68 msgid "usage is" msgstr "" -#: turtleconfusion.py:212 +#: turtleart.py:212 msgid "No option action:" msgstr "" -#: turtleconfusion.py:224 +#: turtleart.py:224 msgid "File not found" msgstr "" -#: turtleconfusion.py:248 +#: turtleart.py:248 #, python-format msgid "Configuration directory not writable: %s" msgstr "" -#: turtleconfusion.py:304 +#: turtleart.py:304 msgid "New" msgstr "" -#: turtleconfusion.py:305 +#: turtleart.py:305 msgid "Open" msgstr "" -#: turtleconfusion.py:306 +#: turtleart.py:306 msgid "Save" msgstr "" -#: turtleconfusion.py:307 +#: turtleart.py:307 msgid "Save as" msgstr "" -#: turtleconfusion.py:308 TurtleConfusionActivity.py:577 +#: turtleart.py:308 TurtleArtActivity.py:604 msgid "Save as image" msgstr "" -#: turtleconfusion.py:310 +#: turtleart.py:310 TurtleArtActivity.py:607 msgid "Save as HTML" msgstr "" -#: turtleconfusion.py:312 TurtleConfusionActivity.py:574 +#: turtleart.py:312 TurtleArtActivity.py:609 msgid "Save as Logo" msgstr "" -#: turtleconfusion.py:314 +#: turtleart.py:314 msgid "Quit" msgstr "" -#: turtleconfusion.py:315 +#: turtleart.py:315 msgid "File" msgstr "" -#: turtleconfusion.py:318 TurtleConfusionActivity.py:598 +#: turtleart.py:318 TurtleArtActivity.py:539 msgid "Cartesian coordinates" msgstr "" -#: turtleconfusion.py:320 TurtleConfusionActivity.py:600 +#: turtleart.py:320 TurtleArtActivity.py:541 msgid "Polar coordinates" msgstr "" -#: turtleconfusion.py:322 TurtleConfusionActivity.py:615 +#: turtleart.py:322 +msgid "Rescale coordinates" +msgstr "" + +#: turtleart.py:324 TurtleArtActivity.py:554 msgid "Grow blocks" msgstr "" -#: turtleconfusion.py:324 TurtleConfusionActivity.py:618 +#: turtleart.py:326 TurtleArtActivity.py:556 msgid "Shrink blocks" msgstr "" -#: turtleconfusion.py:326 +#: turtleart.py:328 msgid "Reset block size" msgstr "" -#: turtleconfusion.py:328 TurtleConfusionActivity.py:500 -#: TurtleConfusionActivity.py:547 +#: turtleart.py:330 TurtleArtActivity.py:469 TurtleArtActivity.py:518 msgid "View" msgstr "" -#: turtleconfusion.py:331 TurtleConfusionActivity.py:591 +#: turtleart.py:333 TurtleArtActivity.py:533 msgid "Copy" msgstr "" -#: turtleconfusion.py:332 TurtleConfusionActivity.py:593 +#: turtleart.py:334 TurtleArtActivity.py:535 msgid "Paste" msgstr "" -#: turtleconfusion.py:333 TurtleConfusionActivity.py:496 -#: TurtleConfusionActivity.py:550 +#: turtleart.py:335 TurtleArtActivity.py:465 TurtleArtActivity.py:520 msgid "Edit" msgstr "" -#: turtleconfusion.py:336 TurtleConfusionActivity.py:257 +#: turtleart.py:338 TurtleArtActivity.py:244 msgid "Show palette" msgstr "" -#: turtleconfusion.py:338 TurtleConfusionActivity.py:263 -#: TurtleConfusionActivity.py:675 +#: turtleart.py:340 TurtleArtActivity.py:250 TurtleArtActivity.py:629 msgid "Hide palette" msgstr "" -#: turtleconfusion.py:340 +#: turtleart.py:342 msgid "Show/hide blocks" msgstr "" -#: turtleconfusion.py:342 +#: turtleart.py:344 msgid "Tools" msgstr "" -#: turtleconfusion.py:345 TurtleConfusionActivity.py:684 +#: turtleart.py:347 TurtleArtActivity.py:638 msgid "Clean" msgstr "" -#: turtleconfusion.py:346 TurtleConfusionActivity.py:686 +#: turtleart.py:348 TurtleArtActivity.py:640 msgid "Run" msgstr "" -#: turtleconfusion.py:347 TurtleConfusionActivity.py:688 +#: turtleart.py:349 TurtleArtActivity.py:642 msgid "Step" msgstr "" -#: turtleconfusion.py:348 TurtleConfusionActivity.py:690 +#: turtleart.py:350 TurtleArtActivity.py:644 msgid "Debug" msgstr "" -#: turtleconfusion.py:349 +#: turtleart.py:351 msgid "Stop" msgstr "" -#: turtleconfusion.py:350 +#: turtleart.py:352 msgid "Turtle" msgstr "" -#: turtleconfusion.py:357 -msgid "Challenge" -msgstr "" - -#: turtleconfusion.py:359 -msgid "Challenges" -msgstr "" - -#: turtleconfusion.py:389 +#: turtleart.py:382 msgid "You have unsaved work. Would you like to save before quitting?" msgstr "" -#: turtleconfusion.py:390 +#: turtleart.py:383 msgid "Save project?" msgstr "" -#: TurtleConfusionActivity.py:127 +#: TurtleArtActivity.py:125 msgid "presentation" msgstr "" -#: TurtleConfusionActivity.py:210 +#: TurtleArtActivity.py:196 msgid "snapshot" msgstr "" -#: TurtleConfusionActivity.py:270 TurtleConfusionActivity.py:283 +#: TurtleArtActivity.py:257 TurtleArtActivity.py:270 msgid "Show blocks" msgstr "" -#: TurtleConfusionActivity.py:273 TurtleConfusionActivity.py:291 -#: TurtleConfusionActivity.py:678 +#: TurtleArtActivity.py:260 TurtleArtActivity.py:278 TurtleArtActivity.py:632 msgid "Hide blocks" msgstr "" -#: TurtleConfusionActivity.py:419 +#: TurtleArtActivity.py:398 msgid "Rescale coordinates down" msgstr "" -#: TurtleConfusionActivity.py:423 +#: TurtleArtActivity.py:402 TurtleArtActivity.py:551 msgid "Rescale coordinates up" msgstr "" -#: TurtleConfusionActivity.py:440 -msgid "no help available" +#: TurtleArtActivity.py:476 TurtleArtActivity.py:524 +msgid "Help" msgstr "" -#: TurtleConfusionActivity.py:507 TurtleConfusionActivity.py:556 -#: TurtleConfusionActivity.py:621 -msgid "Help" +#: TurtleArtActivity.py:497 TurtleArtActivity.py:623 +msgid "Load example" msgstr "" -#: TurtleConfusionActivity.py:544 +#: TurtleArtActivity.py:516 msgid "Project" msgstr "" -#: TurtleConfusionActivity.py:553 +#: TurtleArtActivity.py:522 msgid "Import/Export" msgstr "" -#: TurtleConfusionActivity.py:566 -msgid "Save snapshot" -msgstr "" - -#: TurtleConfusionActivity.py:580 -msgid "Import project from the Journal" -msgstr "" - -#: TurtleConfusionActivity.py:595 +#: TurtleArtActivity.py:537 msgid "Fullscreen" msgstr "" -#: TurtleConfusionActivity.py:603 +#: TurtleArtActivity.py:544 msgid "Metric coordinates" msgstr "" -#: TurtleConfusionActivity.py:606 TurtleArt/tawindow.py:2763 -#: TurtleArt/tawindow.py:2767 TurtleArt/tabasics.py:202 +#: TurtleArtActivity.py:547 TurtleArt/tawindow.py:2789 +#: TurtleArt/tawindow.py:2793 TurtleArt/tabasics.py:216 msgid "xcor" msgstr "" -#: TurtleConfusionActivity.py:607 TurtleArt/tawindow.py:2763 -#: TurtleArt/tawindow.py:2767 TurtleArt/tabasics.py:213 +#: TurtleArtActivity.py:548 TurtleArt/tawindow.py:2789 +#: TurtleArt/tawindow.py:2793 TurtleArt/tabasics.py:227 msgid "ycor" msgstr "" -#: TurtleConfusionActivity.py:607 TurtleArt/tawindow.py:2763 -#: TurtleArt/tawindow.py:2767 TurtleArt/tabasics.py:224 +#: TurtleArtActivity.py:548 TurtleArt/tawindow.py:2789 +#: TurtleArt/tawindow.py:2793 TurtleArt/tabasics.py:238 msgid "heading" msgstr "" -#: TurtleConfusionActivity.py:624 TurtleConfusionActivity.py:628 +#: TurtleArtActivity.py:574 TurtleArtActivity.py:578 msgid "Move the cursor over the orange palette for help." msgstr "" -#: TurtleConfusionActivity.py:670 -msgid "Select a challenge" +#: TurtleArtActivity.py:612 +msgid "Save snapshot" msgstr "" -#: TurtleConfusionActivity.py:676 +#: TurtleArtActivity.py:616 +msgid "Import project from the Journal" +msgstr "" + +#: TurtleArtActivity.py:619 +msgid "Load Python block" +msgstr "" + +#: TurtleArtActivity.py:630 msgid "p" msgstr "" -#: TurtleConfusionActivity.py:679 +#: TurtleArtActivity.py:633 msgid "b" msgstr "" -#: TurtleConfusionActivity.py:684 +#: TurtleArtActivity.py:638 msgid "e" msgstr "" -#: TurtleConfusionActivity.py:686 +#: TurtleArtActivity.py:640 msgid "r" msgstr "" -#: TurtleConfusionActivity.py:688 +#: TurtleArtActivity.py:642 msgid "w" msgstr "" -#: TurtleConfusionActivity.py:690 +#: TurtleArtActivity.py:644 msgid "d" msgstr "" -#: TurtleConfusionActivity.py:692 +#: TurtleArtActivity.py:646 msgid "Stop turtle" msgstr "" -#: TurtleConfusionActivity.py:693 +#: TurtleArtActivity.py:647 msgid "s" msgstr "" +#: taextras.py:36 +msgid "Turtle Art Mini" +msgstr "" + +#: taextras.py:40 +msgid "Turtle Confusion" +msgstr "" + +#: taextras.py:41 +msgid "Select a challenge" +msgstr "" + +#: taextras.py:47 +msgid "Palette of Mexican pesos" +msgstr "" + +#: taextras.py:48 +msgid "Palette of Colombian pesos" +msgstr "" + +#: taextras.py:49 +msgid "Palette of Rwandan francs" +msgstr "" + +#: taextras.py:50 +msgid "Palette of US currencies" +msgstr "" + +#: taextras.py:51 +msgid "Palette of Australian currencies" +msgstr "" + +#: taextras.py:52 +msgid "Palette of Guaranies" +msgstr "" + +#. TRANS: Butia is the Arduino Robot Project from Uruguay +#. (http://www.fing.edu.uy/inco/proyectos/butia/) +#: taextras.py:58 +msgid "Turtle Art Butia" +msgstr "" + +#: taextras.py:59 +msgid "Adjust LED intensity between 0 and 255." +msgstr "" + +#: taextras.py:60 +msgid "" +"Returns the object gray level encountered him as a number between 0 and 1023." +msgstr "" + +#: taextras.py:62 +msgid "Returns 1 when the button is press and 0 otherwise." +msgstr "" + +#: taextras.py:63 +msgid "Returns the ambient light level as a number between 0 and 1023." +msgstr "" + +#: taextras.py:64 +msgid "Returns the ambient temperature as a number between 0 and 255." +msgstr "" + +#: taextras.py:65 +msgid "" +"Returns the distance from the object in front of the sensor as a number " +"between 0 and 255." +msgstr "" + +#: taextras.py:67 +msgid "Returns 0 or 1 depending on the sensor inclination." +msgstr "" + +#: taextras.py:68 +msgid "Returns 1 when the sensors detects a magnetic field, 0 otherwise." +msgstr "" + +#: taextras.py:69 +msgid "Switches from 0 to 1, the frequency depends on the vibration." +msgstr "" + +#: taextras.py:70 +msgid "LED" +msgstr "" + +#: taextras.py:71 +msgid "pushbutton" +msgstr "" + +#: taextras.py:72 +msgid "grayscale" +msgstr "" + +#: taextras.py:73 +msgid "ambient light" +msgstr "" + +#: taextras.py:74 +msgid "temperature" +msgstr "" + +#: taextras.py:75 +msgid "distance" +msgstr "" + +#: taextras.py:76 +msgid "tilt" +msgstr "" + +#: taextras.py:77 +msgid "magnetic induction" +msgstr "" + +#: taextras.py:78 +msgid "vibration" +msgstr "" + +#: taextras.py:79 +msgid "Butia Robot" +msgstr "" + +#: taextras.py:80 +msgid "delay Butia" +msgstr "" + +#: taextras.py:81 +msgid "wait for argument seconds" +msgstr "" + +#: taextras.py:82 +msgid "Butia battery charge" +msgstr "" + +#: taextras.py:83 +msgid "Returns the battery charge as a number between 0 and 255." +msgstr "" + +#: taextras.py:84 +msgid "Butia speed" +msgstr "" + +#: taextras.py:85 +msgid "" +"Set the speed of the Butia motors as a value between 0 and 1023, passed by " +"an argument." +msgstr "" + +#: taextras.py:87 +msgid "forward Butia" +msgstr "" + +#: taextras.py:88 +msgid "Move the Butia robot forward." +msgstr "" + +#: taextras.py:89 +msgid "forward distance" +msgstr "" + +#: taextras.py:90 +msgid "Move the Butia robot forward a predefined distance." +msgstr "" + +#: taextras.py:91 +msgid "backward Butia" +msgstr "" + +#: taextras.py:92 taextras.py:96 taextras.py:98 taextras.py:102 +msgid "Move the Butia robot backward." +msgstr "" + +#: taextras.py:93 +msgid "backward distance" +msgstr "" + +#: taextras.py:94 +msgid "Move the Butia robot backward a predefined distance." +msgstr "" + +#: taextras.py:95 +msgid "left Butia" +msgstr "" + +#: taextras.py:97 +msgid "right Butia" +msgstr "" + +#: taextras.py:99 +msgid "Turn x degrees" +msgstr "" + +#: taextras.py:100 +msgid "Turn the Butia robot x degrees." +msgstr "" + +#: taextras.py:101 +msgid "stop Butia" +msgstr "" + +#: taextras.py:103 +msgid "print Butia" +msgstr "" + +#: taextras.py:104 +msgid "Print text in Butia robot 32-character ASCII display." +msgstr "" + +#: taextras.py:105 +msgid "Butia" +msgstr "" + +#: taextras.py:109 +msgid "The camera was not found." +msgstr "" + +#: taextras.py:110 +msgid "Error on the initialization of the camera." +msgstr "" + +#: taextras.py:111 +msgid "FollowMe" +msgstr "" + +#: taextras.py:112 +msgid "follow a RGB color" +msgstr "" + +#: taextras.py:113 +msgid "follow a turtle color" +msgstr "" + +#: taextras.py:114 +msgid "calibrate a color to follow" +msgstr "" + +#: taextras.py:115 +msgid "x position" +msgstr "" + +#: taextras.py:116 +msgid "return x position" +msgstr "" + +#: taextras.py:117 +msgid "y position" +msgstr "" + +#: taextras.py:118 +msgid "return y position" +msgstr "" + +#: taextras.py:122 +msgid "Sumo Butia" +msgstr "" + +#: taextras.py:123 +msgid "submit speed​​" +msgstr "" + +#: taextras.py:124 +msgid "Send speeds the robot." +msgstr "" + +#: taextras.py:125 +msgid "set speed" +msgstr "" + +#: taextras.py:126 +msgid "Set the default speed for the movement commands." +msgstr "" + +#: taextras.py:127 +msgid "move" +msgstr "" + +#: taextras.py:128 TurtleArt/tabasics.py:131 +msgid "back" +msgstr "" + +#: taextras.py:129 pysamples/grecord.py:215 +msgid "stop" +msgstr "" + +#: taextras.py:130 +msgid "turn left" +msgstr "" + +#: taextras.py:131 +msgid "turn right" +msgstr "" + +#: taextras.py:132 +msgid "angle to center" +msgstr "" + +#. TRANS: dojo is the playing field +#: taextras.py:134 +msgid "Get the angle to the center of the dojo." +msgstr "" + +#: taextras.py:135 +msgid "angle to the opponent" +msgstr "" + +#: taextras.py:136 +msgid "Get the angle to the center of the opponent." +msgstr "" + +#: taextras.py:137 +msgid "x coor." +msgstr "" + +#: taextras.py:138 +msgid "Get the x coordinate of the robot." +msgstr "" + +#: taextras.py:139 +msgid "y coor." +msgstr "" + +#: taextras.py:140 +msgid "Get the y coordinate of the robot." +msgstr "" + +#: taextras.py:141 +msgid "opponent x coor." +msgstr "" + +#: taextras.py:142 +msgid "Get the x coordinate of the opponent." +msgstr "" + +#: taextras.py:143 +msgid "opponent y coor." +msgstr "" + +#: taextras.py:144 +msgid "Get the y coordinate of the opponent." +msgstr "" + +#: taextras.py:145 +msgid "rotation" +msgstr "" + +#: taextras.py:146 +msgid "Get SumBot rotation." +msgstr "" + +#: taextras.py:147 +msgid "opponent rotation" +msgstr "" + +#: taextras.py:148 +msgid "Get the rotation of the opponent." +msgstr "" + +#: taextras.py:149 +msgid "distance to center" +msgstr "" + +#. TRANS: dojo is the playing field +#: taextras.py:151 +msgid "Get the distance to the center of the dojo." +msgstr "" + +#: taextras.py:152 +msgid "distance to opponent" +msgstr "" + +#: taextras.py:153 +msgid "Get the distance to the opponent." +msgstr "" + +#: taextras.py:154 +msgid "update information" +msgstr "" + +#: taextras.py:155 +msgid "Update information from the server." +msgstr "" + +#: pysamples/grecord.py:205 plugins/audio_sensors/audio_sensors.py:82 +#: plugins/audio_sensors/audio_sensors.py:97 +msgid "sound" +msgstr "" + +#: pysamples/grecord.py:213 TurtleArt/tabasics.py:801 +msgid "start" +msgstr "" + +#: pysamples/grecord.py:217 +msgid "play" +msgstr "" + +#: pysamples/grecord.py:219 +msgid "save" +msgstr "" + +#: pysamples/uturn.py:24 +msgid "uturn" +msgstr "" + +#: pysamples/uturn.py:26 +msgid "make a uturn" +msgstr "" + #: gnome_plugins/collaboration_plugin.py:67 msgid "My Turtle Art session" msgstr "" @@ -384,6 +783,604 @@ msgstr "" msgid "Failed to upload!" msgstr "" +#: plugins/camera_sensor/camera_sensor.py:58 plugins/rfid/rfid.py:86 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:269 +#: plugins/light_sensor/light_sensor.py:49 +#: plugins/audio_sensors/audio_sensors.py:75 +#: plugins/accelerometer/accelerometer.py:49 +msgid "Palette of sensor blocks" +msgstr "" + +#: plugins/camera_sensor/camera_sensor.py:69 +#: plugins/camera_sensor/camera_sensor.py:81 +#: plugins/camera_sensor/camera_sensor.py:99 +#: plugins/camera_sensor/camera_sensor.py:112 +#: plugins/light_sensor/light_sensor.py:55 +#: plugins/light_sensor/light_sensor.py:62 +msgid "brightness" +msgstr "" + +#: plugins/camera_sensor/camera_sensor.py:70 +#: plugins/camera_sensor/camera_sensor.py:101 +msgid "light level detected by camera" +msgstr "" + +#: plugins/camera_sensor/camera_sensor.py:82 +#: plugins/camera_sensor/camera_sensor.py:113 +msgid "Average RGB color from camera is pushed to the stack" +msgstr "" + +#: plugins/camera_sensor/camera_sensor.py:93 +#: plugins/camera_sensor/camera_sensor.py:125 +msgid "camera output" +msgstr "" + +#: plugins/rfid/rfid.py:91 plugins/rfid/rfid.py:99 +msgid "RFID" +msgstr "" + +#: plugins/rfid/rfid.py:92 plugins/rfid/rfid.py:100 +msgid "read value from RFID device" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:98 +#: TurtleArt/tabasics.py:707 +msgid "Palette of flow operators" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:103 +msgid "while" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:104 +msgid "do-while-True operator that uses boolean operators from Numbers palette" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:110 +msgid "until" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:111 +msgid "do-until-True operator that uses boolean operators from Numbers palette" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:118 +msgid "Palette of media objects" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:124 +msgid "journal" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:125 +msgid "Sugar Journal media object" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:135 +msgid "audio" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:137 +msgid "Sugar Journal audio object" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:147 +msgid "video" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:149 +msgid "Sugar Journal video object" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:159 +msgid "description" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:161 +msgid "Sugar Journal description field" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:170 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:171 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:172 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:179 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:192 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:207 +#: TurtleArt/tabasics.py:834 TurtleArt/tabasics.py:835 +#: TurtleArt/tabasics.py:836 +msgid "text" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:173 +#: TurtleArt/tabasics.py:837 +msgid "string value" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:178 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:206 +msgid "show" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:182 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:195 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:210 +msgid "draws text or show media from the Journal" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:191 +msgid "show aligned" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:218 +msgid "set scale" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:222 +msgid "sets the scale of media" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:229 +msgid "save picture" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:231 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:242 +msgid "picture name" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:232 +msgid "saves a picture to the Sugar Journal" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:240 +msgid "save SVG" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:243 +msgid "saves turtle graphics as an SVG file in the Sugar Journal" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:250 +msgid "scale" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:254 +msgid "holds current scale value" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:259 +msgid "media wait" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:261 +msgid "wait for current video or audio to complete" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:274 +msgid "query keyboard" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:276 +msgid "query for keyboard input (results stored in keyboard block)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:283 +msgid "keyboard" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:287 +msgid "holds results of query-keyboard block" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:294 +msgid "read pixel" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:297 +msgid "RGB color under the turtle is pushed to the stack" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:305 +msgid "turtle sees" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:307 +msgid "returns the color that the turtle \"sees\"" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:315 +msgid "time" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:318 +msgid "elapsed time (in seconds) since program started" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:327 +msgid "Palette of extra options" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:332 +msgid "push" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:335 +msgid "pushes value onto FILO (first-in last-out heap)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:345 +msgid "show heap" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:348 +msgid "shows values in FILO (first-in last-out heap)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:358 +msgid "empty heap" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:361 +msgid "emptys FILO (first-in-last-out heap)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:371 +msgid "pop" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:375 +msgid "pops value off FILO (first-in last-out heap)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:385 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:387 +msgid "comment" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:388 +msgid "places a comment in your code" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:394 +msgid "print" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:397 +msgid "prints value in status block at bottom of the screen" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:405 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:417 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:430 +msgid "Python" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:408 +msgid "" +"a programmable block: used to add advanced single-variable math equations, e." +"g., sin(x)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:420 +msgid "" +"a programmable block: used to add advanced multi-variable math equations, e." +"g., sqrt(x*x+y*y)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:433 +msgid "" +"a programmable block: used to add advanced multi-variable math equations, e." +"g., sin(x+y+z)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:444 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:459 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:474 +msgid "Python block" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:446 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:461 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:476 +msgid "runs code found in the tamyblock.py module found in the Journal" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:489 +msgid "Cartesian" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:491 +msgid "displays Cartesian coordinates" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:497 +msgid "polar" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:499 +msgid "displays polar coordinates" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:505 +msgid "turtle" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:508 +msgid "chooses which turtle to command" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:517 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:526 +msgid "turtle shell" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:519 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:527 +msgid "put a custom 'shell' on the turtle" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:532 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:697 +msgid "top" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:534 +msgid "top of a collapsed stack" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:540 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:673 +msgid "bottom" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:541 +msgid "bottom of a collapsible stack" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:549 +msgid "bottom block in a collapsed stack: click to open" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:557 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:560 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:569 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:577 +msgid "top of stack" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:558 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:567 +msgid "label" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:566 +msgid "top of a collapsible stack" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:575 +#: TurtleArt/tautils.py:590 +msgid "click to open" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:583 +msgid "Palette of presentation templates" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:587 +msgid "hide blocks" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:589 +msgid "declutters canvas by hiding blocks" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:594 +msgid "show blocks" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:596 +msgid "restores hidden blocks" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:601 +msgid "full screen" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:603 +msgid "hides the Sugar toolbars" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:612 +msgid "list" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:615 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:845 +msgid "presentation bulleted list" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:623 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:846 +msgid "presentation template: list of bullets" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:630 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:790 +msgid "presentation template: select Journal object (no description)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:637 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:776 +msgid "presentation template: select Journal object (with description)" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:644 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:832 +msgid "presentation template: select four Journal objects" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:651 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:658 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:804 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:818 +msgid "presentation template: select two Journal objects" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:665 +#: TurtleArt/tabasics.py:154 +msgid "left" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:668 +msgid "xcor of left of screen" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:676 +msgid "ycor of bottom of screen" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:681 +msgid "width" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:684 +msgid "the canvas width" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:689 +#: TurtleArt/tabasics.py:165 +msgid "right" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:692 +msgid "xcor of right of screen" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:700 +msgid "ycor of top of screen" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:705 +msgid "height" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:708 +msgid "the canvas height" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:715 +msgid "title x" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:724 +msgid "title y" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:733 +msgid "left x" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:742 +msgid "top y" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:751 +msgid "right x" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:760 +msgid "bottom y" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:774 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:788 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:802 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:816 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:830 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:844 +#: TurtleArt/taconstants.py:251 TurtleArt/taconstants.py:273 +#: TurtleArt/taconstants.py:294 TurtleArt/taconstants.py:336 +#: TurtleArt/taconstants.py:378 TurtleArt/taconstants.py:420 +msgid "Title" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:775 +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:789 +msgid "presentation 1x1" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:803 +msgid "presentation 2x1" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:817 +msgid "presentation 1x2" +msgstr "" + +#: plugins/turtle_blocks_extras/turtle_blocks_extras.py:831 +msgid "presentation 2x2" +msgstr "" + +#: plugins/light_sensor/light_sensor.py:57 +#: plugins/light_sensor/light_sensor.py:64 +msgid "light level detected by light sensor" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:83 +#: plugins/audio_sensors/audio_sensors.py:98 +msgid "raw microphone input signal" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:89 +#: plugins/audio_sensors/audio_sensors.py:104 +msgid "loudness" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:90 +#: plugins/audio_sensors/audio_sensors.py:105 +msgid "microphone input volume" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:118 +#: plugins/audio_sensors/audio_sensors.py:126 +msgid "pitch" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:119 +#: plugins/audio_sensors/audio_sensors.py:127 +msgid "microphone input pitch" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:145 +#: plugins/audio_sensors/audio_sensors.py:159 +msgid "resistance" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:146 +#: plugins/audio_sensors/audio_sensors.py:160 +msgid "microphone input resistance" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:151 +#: plugins/audio_sensors/audio_sensors.py:166 +msgid "voltage" +msgstr "" + +#: plugins/audio_sensors/audio_sensors.py:152 +#: plugins/audio_sensors/audio_sensors.py:167 +msgid "microphone input voltage" +msgstr "" + +#: plugins/accelerometer/accelerometer.py:55 +#: plugins/accelerometer/accelerometer.py:62 +msgid "acceleration" +msgstr "" + +#: plugins/accelerometer/accelerometer.py:57 +#: plugins/accelerometer/accelerometer.py:64 +msgid "push acceleration in x, y, z to heap" +msgstr "" + #: TurtleArt/tapalette.py:83 msgid "displays next palette" msgstr "" @@ -392,20 +1389,15 @@ msgstr "" msgid "changes the orientation of the palette of blocks" msgstr "" -#: TurtleArt/tawindow.py:737 TurtleArt/tawindow.py:738 +#: TurtleArt/tawindow.py:748 TurtleArt/tawindow.py:749 msgid "orientation" msgstr "" -#: TurtleArt/tawindow.py:748 TurtleArt/tawindow.py:1010 +#: TurtleArt/tawindow.py:759 TurtleArt/tawindow.py:1022 msgid "next" msgstr "" -#: TurtleArt/tawindow.py:1549 TurtleArt/tawindow.py:2767 -#: TurtleArt/taexporthtml.py:127 TurtleArt/taexporthtml.py:129 -msgid "Turtle Art" -msgstr "" - -#: TurtleArt/tawindow.py:2859 +#: TurtleArt/tawindow.py:2885 msgid "image" msgstr "" @@ -417,16 +1409,6 @@ msgstr "" msgid "Save..." msgstr "" -#: TurtleArt/tautils.py:587 -msgid "click to open" -msgstr "" - -#: TurtleArt/taconstants.py:255 TurtleArt/taconstants.py:277 -#: TurtleArt/taconstants.py:298 TurtleArt/taconstants.py:340 -#: TurtleArt/taconstants.py:382 TurtleArt/taconstants.py:424 -msgid "Title" -msgstr "" - #: TurtleArt/talogo.py:417 msgid "did not output to" msgstr "" @@ -435,11 +1417,11 @@ msgstr "" msgid "I don't know how to" msgstr "" -#: TurtleArt/talogo.py:515 +#: TurtleArt/talogo.py:512 msgid "doesn't like" msgstr "" -#: TurtleArt/talogo.py:515 +#: TurtleArt/talogo.py:512 msgid "as input" msgstr "" @@ -455,10 +1437,6 @@ msgstr "" msgid "moves turtle forward" msgstr "" -#: TurtleArt/tabasics.py:131 -msgid "back" -msgstr "" - #: TurtleArt/tabasics.py:135 msgid "moves turtle backward" msgstr "" @@ -471,568 +1449,539 @@ msgstr "" msgid "clears the screen and reset the turtle" msgstr "" -#: TurtleArt/tabasics.py:154 -msgid "left" -msgstr "" - #: TurtleArt/tabasics.py:158 msgid "turns turtle counterclockwise (angle in degrees)" msgstr "" -#: TurtleArt/tabasics.py:165 -msgid "right" -msgstr "" - #: TurtleArt/tabasics.py:169 msgid "turns turtle clockwise (angle in degrees)" msgstr "" -#: TurtleArt/tabasics.py:176 TurtleArt/tabasics.py:258 +#: TurtleArt/tabasics.py:177 +msgid "arc" +msgstr "" + +#: TurtleArt/tabasics.py:177 +msgid "angle" +msgstr "" + +#: TurtleArt/tabasics.py:177 +msgid "radius" +msgstr "" + +#: TurtleArt/tabasics.py:181 +msgid "moves turtle along an arc" +msgstr "" + +#: TurtleArt/tabasics.py:190 TurtleArt/tabasics.py:256 msgid "set xy" msgstr "" -#: TurtleArt/tabasics.py:176 TurtleArt/tabasics.py:258 +#: TurtleArt/tabasics.py:190 TurtleArt/tabasics.py:256 msgid "x" msgstr "" -#: TurtleArt/tabasics.py:176 TurtleArt/tabasics.py:258 +#: TurtleArt/tabasics.py:190 TurtleArt/tabasics.py:256 msgid "y" msgstr "" -#: TurtleArt/tabasics.py:180 TurtleArt/tabasics.py:262 +#: TurtleArt/tabasics.py:194 TurtleArt/tabasics.py:260 msgid "" "moves turtle to position xcor, ycor; (0, 0) is in the center of the screen." msgstr "" -#: TurtleArt/tabasics.py:190 +#: TurtleArt/tabasics.py:204 msgid "set heading" msgstr "" -#: TurtleArt/tabasics.py:194 +#: TurtleArt/tabasics.py:208 msgid "sets the heading of the turtle (0 is towards the top of the screen.)" msgstr "" -#: TurtleArt/tabasics.py:203 +#: TurtleArt/tabasics.py:217 msgid "" "holds current x-coordinate value of the turtle (can be used in place of a " "number block)" msgstr "" -#: TurtleArt/tabasics.py:214 +#: TurtleArt/tabasics.py:228 msgid "" "holds current y-coordinate value of the turtle (can be used in place of a " "number block)" msgstr "" -#: TurtleArt/tabasics.py:225 +#: TurtleArt/tabasics.py:239 msgid "" "holds current heading value of the turtle (can be used in place of a number " "block)" msgstr "" -#: TurtleArt/tabasics.py:244 -msgid "arc" -msgstr "" - -#: TurtleArt/tabasics.py:244 -msgid "angle" -msgstr "" - -#: TurtleArt/tabasics.py:244 -msgid "radius" -msgstr "" - -#: TurtleArt/tabasics.py:248 -msgid "moves turtle along an arc" -msgstr "" - -#: TurtleArt/tabasics.py:275 +#: TurtleArt/tabasics.py:273 msgid "Palette of pen commands" msgstr "" -#: TurtleArt/tabasics.py:279 +#: TurtleArt/tabasics.py:277 msgid "pen up" msgstr "" -#: TurtleArt/tabasics.py:282 +#: TurtleArt/tabasics.py:280 msgid "Turtle will not draw when moved." msgstr "" -#: TurtleArt/tabasics.py:288 +#: TurtleArt/tabasics.py:286 msgid "pen down" msgstr "" -#: TurtleArt/tabasics.py:291 +#: TurtleArt/tabasics.py:289 msgid "Turtle will draw when moved." msgstr "" -#: TurtleArt/tabasics.py:299 +#: TurtleArt/tabasics.py:295 msgid "set pen size" msgstr "" -#: TurtleArt/tabasics.py:303 +#: TurtleArt/tabasics.py:299 msgid "sets size of the line drawn by the turtle" msgstr "" -#: TurtleArt/tabasics.py:314 +#: TurtleArt/tabasics.py:309 msgid "fill screen" msgstr "" -#: TurtleArt/tabasics.py:314 TurtleArt/tabasics.py:404 +#: TurtleArt/tabasics.py:309 TurtleArt/tabasics.py:394 msgid "color" msgstr "" -#: TurtleArt/tabasics.py:314 TurtleArt/tabasics.py:415 +#: TurtleArt/tabasics.py:309 TurtleArt/tabasics.py:404 msgid "shade" msgstr "" -#: TurtleArt/tabasics.py:318 +#: TurtleArt/tabasics.py:313 msgid "fills the background with (color, shade)" msgstr "" -#: TurtleArt/tabasics.py:328 +#: TurtleArt/tabasics.py:322 msgid "pen size" msgstr "" -#: TurtleArt/tabasics.py:329 +#: TurtleArt/tabasics.py:323 msgid "holds current pen size (can be used in place of a number block)" msgstr "" -#: TurtleArt/tabasics.py:341 +#: TurtleArt/tabasics.py:334 msgid "start fill" msgstr "" -#: TurtleArt/tabasics.py:343 +#: TurtleArt/tabasics.py:336 msgid "starts filled polygon (used with end fill block)" msgstr "" -#: TurtleArt/tabasics.py:351 +#: TurtleArt/tabasics.py:343 msgid "end fill" msgstr "" -#: TurtleArt/tabasics.py:353 +#: TurtleArt/tabasics.py:345 msgid "completes filled polygon (used with start fill block)" msgstr "" -#: TurtleArt/tabasics.py:363 +#: TurtleArt/tabasics.py:355 msgid "Palette of pen colors" msgstr "" -#: TurtleArt/tabasics.py:367 +#: TurtleArt/tabasics.py:359 msgid "set color" msgstr "" -#: TurtleArt/tabasics.py:371 +#: TurtleArt/tabasics.py:363 msgid "sets color of the line drawn by the turtle" msgstr "" -#: TurtleArt/tabasics.py:380 +#: TurtleArt/tabasics.py:371 msgid "set shade" msgstr "" -#: TurtleArt/tabasics.py:384 +#: TurtleArt/tabasics.py:375 msgid "sets shade of the line drawn by the turtle" msgstr "" -#: TurtleArt/tabasics.py:393 +#: TurtleArt/tabasics.py:383 msgid "set gray" msgstr "" -#: TurtleArt/tabasics.py:396 +#: TurtleArt/tabasics.py:386 msgid "sets gray level of the line drawn by the turtle" msgstr "" -#: TurtleArt/tabasics.py:405 +#: TurtleArt/tabasics.py:395 msgid "holds current pen color (can be used in place of a number block)" msgstr "" -#: TurtleArt/tabasics.py:416 +#: TurtleArt/tabasics.py:405 msgid "holds current pen shade" msgstr "" -#: TurtleArt/tabasics.py:425 +#: TurtleArt/tabasics.py:413 msgid "gray" msgstr "" -#: TurtleArt/tabasics.py:426 +#: TurtleArt/tabasics.py:414 msgid "holds current gray level (can be used in place of a number block)" msgstr "" -#: TurtleArt/tabasics.py:446 +#: TurtleArt/tabasics.py:434 msgid "set text color" msgstr "" -#: TurtleArt/tabasics.py:449 +#: TurtleArt/tabasics.py:437 msgid "sets color of text drawn by the turtle" msgstr "" -#: TurtleArt/tabasics.py:457 +#: TurtleArt/tabasics.py:445 msgid "set text size" msgstr "" -#: TurtleArt/tabasics.py:460 +#: TurtleArt/tabasics.py:448 msgid "sets size of text drawn by the turtle" msgstr "" -#: TurtleArt/tabasics.py:543 +#: TurtleArt/tabasics.py:531 msgid "Palette of numeric operators" msgstr "" -#: TurtleArt/tabasics.py:549 +#: TurtleArt/tabasics.py:537 msgid "plus" msgstr "" -#: TurtleArt/tabasics.py:552 +#: TurtleArt/tabasics.py:540 msgid "adds two alphanumeric inputs" msgstr "" -#: TurtleArt/tabasics.py:560 +#: TurtleArt/tabasics.py:548 msgid "minus" msgstr "" -#: TurtleArt/tabasics.py:563 +#: TurtleArt/tabasics.py:551 msgid "subtracts bottom numeric input from top numeric input" msgstr "" -#: TurtleArt/tabasics.py:574 +#: TurtleArt/tabasics.py:562 msgid "multiply" msgstr "" -#: TurtleArt/tabasics.py:577 +#: TurtleArt/tabasics.py:565 msgid "multiplies two numeric inputs" msgstr "" -#: TurtleArt/tabasics.py:586 +#: TurtleArt/tabasics.py:574 msgid "divide" msgstr "" -#: TurtleArt/tabasics.py:589 +#: TurtleArt/tabasics.py:577 msgid "" "divides top numeric input (numerator) by bottom numeric input (denominator)" msgstr "" -#: TurtleArt/tabasics.py:599 +#: TurtleArt/tabasics.py:587 msgid "identity" msgstr "" -#: TurtleArt/tabasics.py:601 +#: TurtleArt/tabasics.py:589 msgid "identity operator used for extending blocks" msgstr "" -#: TurtleArt/tabasics.py:609 TurtleArt/tabasics.py:610 +#: TurtleArt/tabasics.py:597 TurtleArt/tabasics.py:598 msgid "mod" msgstr "" -#: TurtleArt/tabasics.py:613 +#: TurtleArt/tabasics.py:601 msgid "modular (remainder) operator" msgstr "" -#: TurtleArt/tabasics.py:621 +#: TurtleArt/tabasics.py:608 msgid "√" msgstr "" -#: TurtleArt/tabasics.py:622 +#: TurtleArt/tabasics.py:609 msgid "square root" msgstr "" -#: TurtleArt/tabasics.py:625 +#: TurtleArt/tabasics.py:612 msgid "calculates square root" msgstr "" -#: TurtleArt/tabasics.py:633 +#: TurtleArt/tabasics.py:619 msgid "random" msgstr "" -#: TurtleArt/tabasics.py:633 +#: TurtleArt/tabasics.py:619 msgid "min" msgstr "" -#: TurtleArt/tabasics.py:633 +#: TurtleArt/tabasics.py:619 msgid "max" msgstr "" -#: TurtleArt/tabasics.py:637 +#: TurtleArt/tabasics.py:623 msgid "returns random number between minimum (top) and maximum (bottom) values" msgstr "" -#: TurtleArt/tabasics.py:649 +#: TurtleArt/tabasics.py:635 msgid "number" msgstr "" -#: TurtleArt/tabasics.py:650 +#: TurtleArt/tabasics.py:636 msgid "used as numeric input in mathematic operators" msgstr "" -#: TurtleArt/tabasics.py:658 +#: TurtleArt/tabasics.py:643 msgid "greater than" msgstr "" -#: TurtleArt/tabasics.py:661 +#: TurtleArt/tabasics.py:646 msgid "logical greater-than operator" msgstr "" -#: TurtleArt/tabasics.py:670 +#: TurtleArt/tabasics.py:654 msgid "less than" msgstr "" -#: TurtleArt/tabasics.py:673 +#: TurtleArt/tabasics.py:657 msgid "logical less-than operator" msgstr "" -#: TurtleArt/tabasics.py:682 +#: TurtleArt/tabasics.py:665 msgid "equal" msgstr "" -#: TurtleArt/tabasics.py:685 +#: TurtleArt/tabasics.py:668 msgid "logical equal-to operator" msgstr "" -#: TurtleArt/tabasics.py:692 +#: TurtleArt/tabasics.py:674 msgid "not" msgstr "" -#: TurtleArt/tabasics.py:695 +#: TurtleArt/tabasics.py:677 msgid "logical NOT operator" msgstr "" -#: TurtleArt/tabasics.py:702 TurtleArt/tabasics.py:705 +#: TurtleArt/tabasics.py:683 TurtleArt/tabasics.py:686 msgid "and" msgstr "" -#: TurtleArt/tabasics.py:706 +#: TurtleArt/tabasics.py:687 msgid "logical AND operator" msgstr "" -#: TurtleArt/tabasics.py:714 TurtleArt/tabasics.py:717 +#: TurtleArt/tabasics.py:694 TurtleArt/tabasics.py:697 msgid "or" msgstr "" -#: TurtleArt/tabasics.py:718 +#: TurtleArt/tabasics.py:698 msgid "logical OR operator" msgstr "" -#: TurtleArt/tabasics.py:727 -msgid "Palette of flow operators" -msgstr "" - -#: TurtleArt/tabasics.py:733 +#: TurtleArt/tabasics.py:712 msgid "wait" msgstr "" -#: TurtleArt/tabasics.py:737 +#: TurtleArt/tabasics.py:716 msgid "pauses program execution a specified number of seconds" msgstr "" -#: TurtleArt/tabasics.py:745 +#: TurtleArt/tabasics.py:723 msgid "forever" msgstr "" -#: TurtleArt/tabasics.py:749 +#: TurtleArt/tabasics.py:727 msgid "loops forever" msgstr "" -#: TurtleArt/tabasics.py:755 TurtleArt/tabasics.py:759 +#: TurtleArt/tabasics.py:733 TurtleArt/tabasics.py:737 msgid "repeat" msgstr "" -#: TurtleArt/tabasics.py:760 +#: TurtleArt/tabasics.py:738 msgid "loops specified number of times" msgstr "" -#: TurtleArt/tabasics.py:767 TurtleArt/tabasics.py:780 +#: TurtleArt/tabasics.py:744 TurtleArt/tabasics.py:756 msgid "if" msgstr "" -#: TurtleArt/tabasics.py:767 +#: TurtleArt/tabasics.py:744 msgid "then" msgstr "" -#: TurtleArt/tabasics.py:770 +#: TurtleArt/tabasics.py:747 msgid "if then" msgstr "" -#: TurtleArt/tabasics.py:772 +#: TurtleArt/tabasics.py:749 msgid "if-then operator that uses boolean operators from Numbers palette" msgstr "" -#: TurtleArt/tabasics.py:780 +#: TurtleArt/tabasics.py:756 msgid "then else" msgstr "" -#: TurtleArt/tabasics.py:784 +#: TurtleArt/tabasics.py:760 msgid "if then else" msgstr "" -#: TurtleArt/tabasics.py:785 +#: TurtleArt/tabasics.py:761 msgid "if-then-else operator that uses boolean operators from Numbers palette" msgstr "" -#: TurtleArt/tabasics.py:794 +#: TurtleArt/tabasics.py:769 msgid "horizontal space" msgstr "" -#: TurtleArt/tabasics.py:795 +#: TurtleArt/tabasics.py:770 msgid "jogs stack right" msgstr "" -#: TurtleArt/tabasics.py:802 +#: TurtleArt/tabasics.py:777 msgid "vertical space" msgstr "" -#: TurtleArt/tabasics.py:803 +#: TurtleArt/tabasics.py:778 msgid "jogs stack down" msgstr "" -#: TurtleArt/tabasics.py:810 +#: TurtleArt/tabasics.py:784 msgid "stop action" msgstr "" -#: TurtleArt/tabasics.py:813 +#: TurtleArt/tabasics.py:787 msgid "stops current action" msgstr "" -#: TurtleArt/tabasics.py:822 +#: TurtleArt/tabasics.py:796 msgid "Palette of variable blocks" msgstr "" -#: TurtleArt/tabasics.py:827 -msgid "start" -msgstr "" - -#: TurtleArt/tabasics.py:830 +#: TurtleArt/tabasics.py:804 msgid "connects action to toolbar run buttons" msgstr "" -#: TurtleArt/tabasics.py:838 +#: TurtleArt/tabasics.py:812 msgid "store in box 1" msgstr "" -#: TurtleArt/tabasics.py:842 +#: TurtleArt/tabasics.py:816 msgid "stores numeric value in Variable 1" msgstr "" -#: TurtleArt/tabasics.py:849 +#: TurtleArt/tabasics.py:823 msgid "store in box 2" msgstr "" -#: TurtleArt/tabasics.py:853 +#: TurtleArt/tabasics.py:827 msgid "stores numeric value in Variable 2" msgstr "" -#: TurtleArt/tabasics.py:861 TurtleArt/tabasics.py:862 -#: TurtleArt/tabasics.py:863 -msgid "text" -msgstr "" - -#: TurtleArt/tabasics.py:864 -msgid "string value" -msgstr "" - -#: TurtleArt/tabasics.py:868 +#: TurtleArt/tabasics.py:841 msgid "box 1" msgstr "" -#: TurtleArt/tabasics.py:871 +#: TurtleArt/tabasics.py:844 msgid "Variable 1 (numeric value)" msgstr "" -#: TurtleArt/tabasics.py:877 +#: TurtleArt/tabasics.py:850 msgid "box 2" msgstr "" -#: TurtleArt/tabasics.py:880 +#: TurtleArt/tabasics.py:853 msgid "Variable 2 (numeric value)" msgstr "" -#: TurtleArt/tabasics.py:888 TurtleArt/tabasics.py:899 +#: TurtleArt/tabasics.py:860 TurtleArt/tabasics.py:870 msgid "box" msgstr "" -#: TurtleArt/tabasics.py:890 TurtleArt/tabasics.py:902 +#: TurtleArt/tabasics.py:862 TurtleArt/tabasics.py:873 msgid "my box" msgstr "" -#: TurtleArt/tabasics.py:892 +#: TurtleArt/tabasics.py:864 msgid "named variable (numeric value)" msgstr "" -#: TurtleArt/tabasics.py:899 +#: TurtleArt/tabasics.py:870 msgid "store in" msgstr "" -#: TurtleArt/tabasics.py:899 +#: TurtleArt/tabasics.py:870 msgid "value" msgstr "" -#: TurtleArt/tabasics.py:903 +#: TurtleArt/tabasics.py:874 msgid "stores numeric value in named variable" msgstr "" -#: TurtleArt/tabasics.py:912 TurtleArt/tabasics.py:939 -#: TurtleArt/tabasics.py:942 +#: TurtleArt/tabasics.py:882 TurtleArt/tabasics.py:884 +#: TurtleArt/tabasics.py:908 TurtleArt/tabasics.py:911 msgid "action" msgstr "" -#: TurtleArt/tabasics.py:914 -msgid "stack" -msgstr "" - -#: TurtleArt/tabasics.py:916 +#: TurtleArt/tabasics.py:886 msgid "top of nameable action stack" msgstr "" -#: TurtleArt/tabasics.py:921 TurtleArt/tabasics.py:949 +#: TurtleArt/tabasics.py:891 TurtleArt/tabasics.py:918 msgid "action 1" msgstr "" -#: TurtleArt/tabasics.py:924 +#: TurtleArt/tabasics.py:894 msgid "top of Action 1 stack" msgstr "" -#: TurtleArt/tabasics.py:929 TurtleArt/tabasics.py:958 +#: TurtleArt/tabasics.py:899 TurtleArt/tabasics.py:927 msgid "action 2" msgstr "" -#: TurtleArt/tabasics.py:932 +#: TurtleArt/tabasics.py:902 msgid "top of Action 2 stack" msgstr "" -#: TurtleArt/tabasics.py:943 +#: TurtleArt/tabasics.py:912 msgid "invokes named action stack" msgstr "" -#: TurtleArt/tabasics.py:952 +#: TurtleArt/tabasics.py:921 msgid "invokes Action 1 stack" msgstr "" -#: TurtleArt/tabasics.py:961 +#: TurtleArt/tabasics.py:930 msgid "invokes Action 2 stack" msgstr "" -#: TurtleArt/tabasics.py:969 +#: TurtleArt/tabasics.py:938 msgid "trash" msgstr "" -#: TurtleArt/tabasics.py:973 +#: TurtleArt/tabasics.py:942 msgid "empty trash" msgstr "" -#: TurtleArt/tabasics.py:974 +#: TurtleArt/tabasics.py:943 msgid "permanently deletes items in trash" msgstr "" -#: TurtleArt/tabasics.py:978 +#: TurtleArt/tabasics.py:947 msgid "restore all" msgstr "" -#: TurtleArt/tabasics.py:979 +#: TurtleArt/tabasics.py:948 msgid "restore all blocks from trash" msgstr "" -#: TurtleArt/tabasics.py:983 +#: TurtleArt/tabasics.py:952 msgid "clear all" msgstr "" -#: TurtleArt/tabasics.py:984 +#: TurtleArt/tabasics.py:953 msgid "move all blocks to trash" msgstr "" diff --git a/turtleconfusion.py b/turtleconfusion.py index 0cff962..e639e38 100755 --- a/turtleconfusion.py +++ b/turtleconfusion.py @@ -1,6 +1,6 @@ #!/usr/bin/env python #Copyright (c) 2007-8, Playful Invention Company -#Copyright (c) 2008-11, Walter Bender +#Copyright (c) 2008-12, Walter Bender #Copyright (c) 2011 Collabora Ltd. #Permission is hereby granted, free of charge, to any person obtaining a copy @@ -32,6 +32,7 @@ import os import os.path import cStringIO import errno +import ConfigParser try: # Try to use XDG Base Directory standard for config files. @@ -51,8 +52,7 @@ import gettext # from a git repository or the unzipped .xo file. # gettext.bindtextdomain('org.laptop.TurtleArtActivity', 'locale') -gettext.textdomain('org.laptop.TurtleArtActivity') -_ = gettext.gettext +import gettext from TurtleArt.taconstants import OVERLAY_LAYER, DEFAULT_TURTLE_COLORS from TurtleArt.tautils import data_to_string, data_from_string, get_save_name @@ -64,13 +64,7 @@ from util.menubuilder import MenuBuilder class TurtleMain(): - ''' Launch Turtle Art from outside of Sugar. ''' - - _HELP_MSG = 'turtleart.py: ' + _('usage is') + ''' - \tturtleart.py - \tturtleart.py project.ta - \tturtleart.py --output_png project.ta - \tturtleart.py -o project''' + ''' Launch Turtle Confusion from outside of Sugar. ''' _INSTALL_PATH = '/usr/share/sugar/activities/TurtleArt.activity' _ALTERNATIVE_INSTALL_PATH = \ '/usr/local/share/sugar/activities/TurtleArt.activity' @@ -78,12 +72,30 @@ class TurtleMain(): _GNOME_PLUGIN_SUBPATH = 'gnome_plugins' def __init__(self): + self._abspath = os.path.abspath('.') + self._execdirname = self._get_execution_dir() + if self._execdirname is not None: + os.chdir(self._execdirname) + file_activity_info = ConfigParser.ConfigParser() + activity_info_path = os.path.abspath('./activity/activity.info') + file_activity_info.read(activity_info_path) + bundle_id = file_activity_info.get('Activity', 'bundle_id') + gettext.textdomain(bundle_id) + global _ + _ = gettext.gettext + self._HELP_MSG = 'turtleart.py: ' + _('usage is') + ''' + \tturtleconfusion.py + \tturtleconfusion.py project.ta + \tturtleconfusion.py --output_png project.ta + \tturtleconfusion.py -o project + \tturtleconfusion.py --run project.ta + \tturtleconfusion.py -r project''' self._init_vars() self._parse_command_line() self._ensure_sugar_paths() self._plugins = [] - if self.output_png: + if self._output_png: # Fix me: We need to create a cairo surface to work with pixbuf = gtk.gdk.Pixbuf(gtk.gdk.COLORSPACE_RGB, False, 8, gtk.gdk.screen_width(), @@ -105,9 +117,9 @@ class TurtleMain(): def _get_gnome_plugin_home(self): ''' Use plugin directory associated with execution path. ''' - if os.path.exists(os.path.join(self._dirname, + if os.path.exists(os.path.join(self._execdirname, self._GNOME_PLUGIN_SUBPATH)): - return os.path.join(self._dirname, self._GNOME_PLUGIN_SUBPATH) + return os.path.join(self._execdirname, self._GNOME_PLUGIN_SUBPATH) else: return None @@ -162,22 +174,23 @@ class TurtleMain(): ''' Get a main window set up. ''' self.win.connect('configure_event', self.tw.update_overlay_position) self.tw.parent = self.win - if self.ta_file is None: + if self._ta_file is None: self.tw.load_start() else: - print self.ta_file - self.tw.load_start(self.ta_file) + print self._ta_file + self.tw.load_start(self._ta_file) self.tw.lc.trace = 0 - self.tw.run_button(0) + if self._run_on_launch: + self._do_run_cb() gtk.main() def _draw_and_quit(self): ''' Non-interactive mode: run the project, save it to a file and quit. ''' - self.tw.load_start(self.ta_file) + self.tw.load_start(self._ta_file) self.tw.lc.trace = 0 self.tw.run_button(0) - self.tw.save_as_image(self.ta_file) + self.tw.save_as_image(self._ta_file) def _build_window(self, interactive=True): ''' Initialize the TurtleWindow instance. ''' @@ -193,18 +206,15 @@ class TurtleMain(): self.turtle_canvas = surface.create_similar( cairo.CONTENT_COLOR, gtk.gdk.screen_width() * 2, gtk.gdk.screen_height() * 2) - self.tw = TurtleArtWindow(self.canvas, self._dirname, + self.tw = TurtleArtWindow(self.canvas, self._execdirname, turtle_canvas=self.turtle_canvas) self.tw.save_folder = os.path.expanduser('~') def _init_vars(self): ''' If we are invoked to start a project from Gnome, we should make sure our current directory is TA's source dir. ''' - self._dirname = self._get_execution_dir() - if self._dirname is not None: - os.chdir(self._dirname) - self.ta_file = None - self.output_png = False + self._ta_file = None + self._output_png = False self.i = 0 # FIXME: use a better name for this variable self.scale = 2.0 self.tw = None @@ -212,32 +222,35 @@ class TurtleMain(): def _parse_command_line(self): ''' Try to make sense of the command-line arguments. ''' try: - opts, args = getopt.getopt(argv[1:], 'ho', - ['help', 'output_png']) + opts, args = getopt.getopt(argv[1:], 'hor', + ['help', '_output_png', 'run']) except getopt.GetoptError, err: print str(err) print self._HELP_MSG sys.exit(2) + self._run_on_launch = False for o, a in opts: if o in ('-h', '--help'): print self._HELP_MSG sys.exit() if o in ('-o', '--output_png'): - self.output_png = True + self._output_png = True + elif o in ('-r', '--run'): + self._run_on_launch = True else: assert False, _('No option action:') + ' ' + o if args: - self.ta_file = args[0] + self._ta_file = args[0] - if len(args) > 1 or self.output_png and self.ta_file is None: + if len(args) > 1 or self._output_png and self._ta_file is None: print self._HELP_MSG sys.exit() - if self.ta_file is not None: - if not self.ta_file.endswith(('.ta')): - self.ta_file += '.ta' - if not os.path.exists(self.ta_file): - assert False, ('%s: %s' % (self.ta_file, _('File not found'))) + if self._ta_file is not None: + if not self._ta_file.endswith(('.ta')): + self._ta_file += '.ta' + if not os.path.exists(self._ta_file): + assert False, ('%s: %s' % (self._ta_file, _('File not found'))) def _ensure_sugar_paths(self): ''' Make sure Sugar paths are present. ''' @@ -286,8 +299,8 @@ class TurtleMain(): win.move(self.x, self.y) win.maximize() win.set_title(_('Turtle Art')) - if os.path.exists(os.path.join(self._dirname, self._ICON_SUBPATH)): - win.set_icon_from_file(os.path.join(self._dirname, + if os.path.exists(os.path.join(self._execdirname, self._ICON_SUBPATH)): + win.set_icon_from_file(os.path.join(self._execdirname, self._ICON_SUBPATH)) win.connect('delete_event', self._quit_ta) @@ -367,7 +380,6 @@ class TurtleMain(): MenuBuilder.make_menu_item(menu, _('Clean'), self._do_eraser_cb) MenuBuilder.make_menu_item(menu, _('Run'), self._do_run_cb) MenuBuilder.make_menu_item(menu, _('Step'), self._do_step_cb) - MenuBuilder.make_menu_item(menu, _('Debug'), self._do_trace_cb) MenuBuilder.make_menu_item(menu, _('Stop'), self._do_stop_cb) turtle_menu = MenuBuilder.make_sub_menu(menu, _('Turtle')) @@ -545,24 +557,26 @@ class TurtleMain(): def _do_run_cb(self, widget): ''' Callback for run button (rabbit). ''' self.tw.lc.trace = 0 - self.tw.run_button(0) + self.tw.hideblocks() + self.tw.run_button(0, running_from_button_push=True) return def _do_step_cb(self, widget): ''' Callback for step button (turtle). ''' self.tw.lc.trace = 0 - self.tw.run_button(3) + self.tw.run_button(3, running_from_button_push=True) return def _do_trace_cb(self, widget): ''' Callback for debug button (bug). ''' self.tw.lc.trace = 1 - self.tw.run_button(6) + self.tw.run_button(9, running_from_button_push=True) return def _do_stop_cb(self, widget): ''' Callback for stop button. ''' self.tw.lc.trace = 0 + self.tw.showblocks() self.tw.stop_button() return diff --git a/util/helpbutton.py b/util/helpbutton.py new file mode 100644 index 0000000..47a36cd --- /dev/null +++ b/util/helpbutton.py @@ -0,0 +1,118 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# Copyright (C) 2012, Gonzalo Odiard +# Copyright (C) 2012, 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 +# 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 + +from TurtleArt.tapalette import palette_names, help_windows + +import logging +_logger = logging.getLogger('turtleart-activity') + + +class HelpButton(gtk.ToolItem): + + def __init__(self, activity): + self._activity = activity + self._current_palette = 'turtle' + + 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 set_current_palette(self, name): + self._current_palette = name + + def __help_button_clicked_cb(self, button): + if self._activity.palette_toolbar_button.is_expanded(): + if not (self._current_palette in help_windows): + _logger.debug('name %s not found' % (self._current_palette)) + return + self._palette.set_content(help_windows[self._current_palette]) + help_windows[self._current_palette].show_all() + elif self._activity.edit_toolbar_button.is_expanded(): + self._palette.set_content(help_windows['edit-toolbar']) + help_windows['edit-toolbar'].show_all() + elif self._activity.view_toolbar_button.is_expanded(): + self._palette.set_content(help_windows['view-toolbar']) + help_windows['view-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('%s' % 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) -- cgit v0.9.1