From 25e7097b3fbddcc140a081a5cf570d815c43c1d8 Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 18 Aug 2010 18:16:39 +0000 Subject: removing files that were moved --- (limited to 'tawindow.py') diff --git a/tawindow.py b/tawindow.py deleted file mode 100644 index 3d62a3f..0000000 --- a/tawindow.py +++ /dev/null @@ -1,2336 +0,0 @@ -# -*- coding: utf-8 -*- -#Copyright (c) 2007, Playful Invention Company -#Copyright (c) 2008-10, Walter Bender -#Copyright (c) 2009-10 Raúl Gutiérrez Segalés - -#Permission is hereby granted, free of charge, to any person obtaining a copy -#of this software and associated documentation files (the "Software"), to deal -#in the Software without restriction, including without limitation the rights -#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -#copies of the Software, and to permit persons to whom the Software is -#furnished to do so, subject to the following conditions: - -#The above copyright notice and this permission notice shall be included in -#all copies or substantial portions of the Software. - -#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -#THE SOFTWARE. - -import pygtk -pygtk.require('2.0') -import gtk -import gobject -import os -import os.path -from math import atan2, pi -DEGTOR = 2*pi/360 -from gettext import gettext as _ - -try: - from sugar.graphics.objectchooser import ObjectChooser - from sugar.datastore import datastore - from sugar import profile -except ImportError: - pass - -from taconstants import HORIZONTAL_PALETTE, VERTICAL_PALETTE, BLOCK_SCALE, \ - PALETTE_NAMES, TITLEXY, MEDIA_SHAPES, STATUS_SHAPES, \ - OVERLAY_SHAPES, TOOLBAR_SHAPES, TAB_LAYER, \ - OVERLAY_LAYER, CATEGORY_LAYER, BLOCKS_WITH_SKIN, \ - ICON_SIZE, PALETTES, PALETTE_SCALE, BOX_STYLE_MEDIA, \ - PALETTE_WIDTH, MACROS, TOP_LAYER, BLOCK_LAYER, \ - CONTENT_BLOCKS, DEFAULTS, SPECIAL_NAMES, HELP_STRINGS, \ - CURSOR, EXPANDABLE, COLLAPSIBLE, RETURN, \ - DEAD_DICTS, DEAD_KEYS, TEMPLATES, PYTHON_SKIN, \ - PALETTE_HEIGHT, STATUS_LAYER, OLD_DOCK, OLD_NAMES, \ - BOOLEAN_STYLE, BLOCK_NAMES -from talogo import LogoCode, stop_logo -from tacanvas import TurtleGraphics -from tablock import Blocks, Block -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, find_sandwich_top, \ - find_sandwich_bottom, restore_stack, collapse_stack, \ - collapsed, collapsible, hide_button_hit, show_button_hit, \ - arithmetic_check, xy, find_block_to_run, find_top_block, \ - find_start_stack, find_group, find_blk_below, olpc_xo_1, \ - dock_dx_dy, data_to_string -from tasprite_factory import SVG, svg_str_to_pixbuf, svg_from_file -from sprites import Sprites, Sprite - -import logging -_logger = logging.getLogger('turtleart-activity') - -class TurtleArtWindow(): - """ TurtleArt Window class abstraction """ - timeout_tag = [0] - - def __init__(self, win, path, parent=None, mycolors=None): - self._loaded_project = "" - self.win = None - self.parent = parent - if type(win) == gtk.DrawingArea: - self.interactive_mode = True - self.window = win - self.window.set_flags(gtk.CAN_FOCUS) - if self.parent is not None: - self.parent.show_all() - self.running_sugar = True - else: - self.window.show_all() - self.running_sugar = False - self.area = self.window.window - self.gc = self.area.new_gc() - self._setup_events() - elif type(win) == gtk.gdk.Pixmap: - self.interactive_mode = False - self.window = win - self.running_sugar = False - self.gc = self.window.new_gc() - else: - _logger.debug("bad win type %s" % (type(win))) - - if self.running_sugar: - self.activity = parent - self.nick = profile.get_nick_name() - else: - self.activity = None - self.nick = None - - self.path = path - self.load_save_folder = os.path.join(path, 'samples') - self.save_folder = None - self.save_file_name = None - self.width = gtk.gdk.screen_width() - self.height = gtk.gdk.screen_height() - - self.keypress = "" - self.keyvalue = 0 - self.dead_key = "" - self.mouse_flag = 0 - self.mouse_x = 0 - self.mouse_y = 0 - - self.orientation = HORIZONTAL_PALETTE - if olpc_xo_1(): - self.lead = 1.0 - self.scale = 0.67 - if self.running_sugar and not self.activity.new_sugar_system: - self.orientation = VERTICAL_PALETTE - else: - self.lead = 1.0 - self.scale = 1.0 - self.block_scale = BLOCK_SCALE - self.trash_scale = 0.5 - self.myblock = None - self.nop = 'nop' - self.loaded = 0 - self.step_time = 0 - self.hide = False - self.palette = True - self.coord_scale = 1 - self.buddies = [] - self.saved_string = '' - self.dx = 0 - self.dy = 0 - self.media_shapes = {} - self.cartesian = False - self.polar = False - self.overlay_shapes = {} - self.toolbar_shapes = {} - self.toolbar_offset = 0 - self.status_spr = None - self.status_shapes = {} - self.toolbar_spr = None - self.palette_sprs = [] - self.palettes = [] - self.palette_button = [] - self.trash_index = PALETTE_NAMES.index('trash') - self.trash_stack = [] - self.selected_palette = None - self.previous_palette = None - self.selectors = [] - self.selected_selector = None - self.previous_selector = None - self.selector_shapes = [] - self.selected_blk = None - self.selected_spr = None - self.drag_group = None - self.drag_turtle = 'move', 0, 0 - self.drag_pos = 0, 0 - self.paste_offset = 20 - self.block_list = Blocks(self.scale) - if self.interactive_mode: - self.sprite_list = Sprites(self.window, self.area, self.gc) - else: - self.sprite_list = None # Sprites(self.window, None, self.gc) - self.turtles = Turtles(self.sprite_list) - if mycolors == None: - Turtle(self.turtles, 1) - else: - Turtle(self.turtles, 1, mycolors.split(',')) - self.active_turtle = self.turtles.get_turtle(1) - self.saving_svg = False - self.svg_string = '' - self.selected_turtle = None - self.canvas = TurtleGraphics(self, self.width, self.height) - self.titlex = -(self.canvas.width*TITLEXY[0])/(self.coord_scale*2) - self.leftx = -(self.canvas.width*TITLEXY[0])/(self.coord_scale*2) - self.rightx = 0 - self.titley = (self.canvas.height*TITLEXY[1])/(self.coord_scale*2) - self.topy = (self.canvas.height*(TITLEXY[1]-0.125))/(self.coord_scale*2) - self.bottomy = 0 - self.lc = LogoCode(self) - self.saved_pictures = [] - - if self.interactive_mode: - self._setup_misc() - self._show_toolbar_palette(0, False) - self.block_operation = '' - - def _setup_events(self): - """ Register the events we listen to. """ - self.window.add_events(gtk.gdk.BUTTON_PRESS_MASK) - self.window.add_events(gtk.gdk.BUTTON_RELEASE_MASK) - self.window.add_events(gtk.gdk.POINTER_MOTION_MASK) - self.window.add_events(gtk.gdk.KEY_PRESS_MASK) - self.window.connect("expose-event", self._expose_cb) - self.window.connect("button-press-event", self._buttonpress_cb) - self.window.connect("button-release-event", self._buttonrelease_cb) - 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 - for _name in MEDIA_SHAPES: - if _name[0:7] == 'journal' and not self.running_sugar: - file_name = 'file'+_name[7:] - else: - file_name = _name - self.media_shapes[_name] = svg_str_to_pixbuf(svg_from_file( - "%s/images/%s.svg" % (self.path, file_name))) - - for i, _name in enumerate(STATUS_SHAPES): - self.status_shapes[_name] = svg_str_to_pixbuf(svg_from_file( - "%s/images/%s.svg" % (self.path, _name))) - self.status_spr = Sprite(self.sprite_list, 0, self.height-200, - self.status_shapes['status']) - self.status_spr.hide() - self.status_spr.type = 'status' - - for _name in OVERLAY_SHAPES: - self.overlay_shapes[_name] = Sprite(self.sprite_list, - int(self.width/2-600), int(self.height/2-450), - svg_str_to_pixbuf(svg_from_file( - "%s/images/%s.svg" % (self.path, _name)))) - self.overlay_shapes[_name].hide() - self.overlay_shapes[_name].type = 'overlay' - - if not self.running_sugar: - offset = self.width-55*len(TOOLBAR_SHAPES) - for i, _name in enumerate(TOOLBAR_SHAPES): - self.toolbar_shapes[_name] = Sprite(self.sprite_list, - i*55+offset, 0, - svg_str_to_pixbuf( - svg_from_file("%s/icons/%s.svg" % (self.path, _name)))) - self.toolbar_shapes[_name].set_layer(TAB_LAYER) - self.toolbar_shapes[_name].name = _name - self.toolbar_shapes[_name].type = 'toolbar' - self.toolbar_shapes['stopiton'].hide() - - def sharing(self): - """ Is a chattube available for share? """ - if self.running_sugar and hasattr(self.activity, 'chattube') and\ - self.activity.chattube is not None: - return True - return False - - def is_project_empty(self): - """ Check to see if project has any blocks in use """ - return len(self.just_blocks()) == 1 - - def _expose_cb(self, win, event): - """ Repaint """ - self.sprite_list.refresh(event) - # self.canvas.cr_expose(event) - return True - - def eraser_button(self): - """ Eraser_button (hide status block when clearing the screen.) """ - if self.status_spr is not None: - self.status_spr.hide() - self.lc.prim_clear() - self.display_coordinates() - - def run_button(self, time): - """ Run turtle! """ - if self.running_sugar: - self.activity.recenter() - # Look for a 'start' block - for blk in self.just_blocks(): - if find_start_stack(blk): - self.step_time = time - print "running stack starting from %s" % (blk.name) - self._run_stack(blk) - return - # If there is no 'start' block, run stacks that aren't 'def action' - for blk in self.just_blocks(): - if find_block_to_run(blk): - self.step_time = time - print "running stack starting from %s" % (blk.name) - self._run_stack(blk) - return - - def stop_button(self): - """ Stop button """ - stop_logo(self) - - def set_userdefined(self): - """ Change icon for user-defined blocks after Python code is loaded. """ - for blk in self.just_blocks(): - if blk.name in PYTHON_SKIN: - x, y = self._calc_image_offset('pythonon', blk.spr) - blk.set_image(self.media_shapes['pythonon'], x, y) - self._resize_skin(blk) - self.nop = 'pythonloaded' - - def set_fullscreen(self): - """ Enter fullscreen mode """ - if self.running_sugar: - self.activity.fullscreen() - self.activity.recenter() - - def set_cartesian(self, flag): - """ Turn on/off Cartesian coordinates """ - if flag: - if self.coord_scale == 1: - self.overlay_shapes['Cartesian_labeled'].set_layer( - OVERLAY_LAYER) - else: - self.overlay_shapes['Cartesian'].set_layer(OVERLAY_LAYER) - self.cartesian = True - else: - if self.coord_scale == 1: - self.overlay_shapes['Cartesian_labeled'].hide() - else: - self.overlay_shapes['Cartesian'].hide() - self.cartesian = False - - def set_polar(self, flag): - """ Turn on/off polar coordinates """ - if flag: - self.overlay_shapes['polar'].set_layer(OVERLAY_LAYER) - self.polar = True - else: - self.overlay_shapes['polar'].hide() - self.polar = False - - def update_overlay_position(self, widget, event): - """ Reposition the overlays when window size changes """ - self.width = event.width - self.height = event.height - for _name in OVERLAY_SHAPES: - shape = self.overlay_shapes[_name] - showing = False - if shape in shape._sprites.list: - shape.hide() - showing = True - self.overlay_shapes[_name] = Sprite(self.sprite_list, - int(self.width / 2 - 600), - int(self.height / 2 - 450), - svg_str_to_pixbuf( - svg_from_file("%s/images/%s.svg" % (self.path, _name)))) - if showing: - self.overlay_shapes[_name].set_layer(OVERLAY_LAYER) - else: - self.overlay_shapes[_name].hide() - self.overlay_shapes[_name].type = 'overlay' - self.cartesian = False - self.polar = False - self.canvas.width = self.width - self.canvas.height = self.height - self.canvas.move_turtle() - - def hideshow_button(self): - """ Hide/show button """ - if not self.hide: - for blk in self.just_blocks(): - blk.spr.hide() - self.hide_palette() - self.hide = True - else: - for blk in self.just_blocks(): - if blk.status != 'collapsed': - blk.spr.set_layer(BLOCK_LAYER) - self.show_palette() - if self.activity is not None and self.activity.new_sugar_system: - self.activity.palette_buttons[0].set_icon( - PALETTE_NAMES[0] + 'on') - self.hide = False - self.canvas.canvas.inval() - - def hideshow_palette(self, state): - """ Hide or show palette """ - if not state: - self.palette = False - if self.running_sugar: - self.activity.do_hidepalette() - self.hide_palette() - else: - self.palette = True - if self.running_sugar: - self.activity.do_showpalette() - self.show_palette() - - def show_palette(self, n=0): - """ Show palette """ - self._show_toolbar_palette(n) - self.palette_button[self.orientation].set_layer(TAB_LAYER) - self.palette_button[2].set_layer(TAB_LAYER) - if self.activity is None or not self.activity.new_sugar_system: - self.toolbar_spr.set_layer(CATEGORY_LAYER) - self.palette = True - - def hide_palette(self): - """ Hide the palette. """ - self._hide_toolbar_palette() - self.palette_button[self.orientation].hide() - self.palette_button[2].hide() - if self.activity is None or not self.activity.new_sugar_system: - self.toolbar_spr.hide() - self.palette = False - - def hideblocks(self): - """ Callback from 'hide blocks' block """ - if not self.interactive_mode: - return - self.hide = False - self.hideshow_button() - if self.running_sugar: - self.activity.do_hide() - - def showblocks(self): - """ Callback from 'show blocks' block """ - if not self.interactive_mode: - return - self.hide = True - self.hideshow_button() - if self.running_sugar: - self.activity.do_show() - - def resize_blocks(self, blocks=None): - """ Resize blocks or if blocks is None, all of the blocks """ - if blocks is None: - blocks = self.just_blocks() - - # We need to restore collapsed stacks before resizing. - for blk in blocks: - if blk.status == 'collapsed': - bot = find_sandwich_bottom(blk) - if collapsed(bot): - dy = bot.values[0] - restore_stack(find_sandwich_top(blk)) - bot.values[0] = dy - - # Do the resizing. - for blk in blocks: - blk.rescale(self.block_scale) - for blk in blocks: - self._adjust_dock_positions(blk) - - # Re-collapsed stacks after resizing. - for blk in blocks: - if collapsed(blk): - collapse_stack(find_sandwich_top(blk)) - for blk in blocks: - if blk.name == 'sandwichtop': - grow_stack_arm(blk) - - # Resize the skins on some blocks: media content and Python - for blk in blocks: - if blk.name in BLOCKS_WITH_SKIN: - self._resize_skin(blk) - - def _show_toolbar_palette(self, n, init_only=False): - """ Show the toolbar palettes, creating them on init_only """ - if (self.activity is None or not self.activity.new_sugar_system) and\ - self.selectors == []: - # Create the selectors - svg = SVG() - x, y = 50, 0 - for i, name in enumerate(PALETTE_NAMES): - a = svg_str_to_pixbuf(svg_from_file("%s/icons/%soff.svg" % ( - self.path, name))) - b = svg_str_to_pixbuf(svg_from_file("%s/icons/%son.svg" % ( - self.path, name))) - self.selector_shapes.append([a, b]) - self.selectors.append(Sprite(self.sprite_list, x, y, a)) - self.selectors[i].type = 'selector' - self.selectors[i].name = name - self.selectors[i].set_layer(TAB_LAYER) - w = self.selectors[i].get_dimensions()[0] - x += int(w) - - # Create the toolbar background - self.toolbar_offset = ICON_SIZE - self.toolbar_spr = Sprite(self.sprite_list, 0, 0, - svg_str_to_pixbuf(svg.toolbar(self.width, ICON_SIZE))) - self.toolbar_spr.type = 'toolbar' - self.toolbar_spr.set_layer(CATEGORY_LAYER) - - - if self.palette_sprs == []: - # Create the empty palettes - if len(self.palettes) == 0: - for i in range(len(PALETTES)): - self.palettes.append([]) - - # Create empty palette backgrounds - for i in PALETTE_NAMES: - self.palette_sprs.append([None, None]) - - # Create the palette orientation button - self.palette_button.append(Sprite(self.sprite_list, 0, - self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( - "%s/images/palettehorizontal.svg" %(self.path))))) - self.palette_button.append(Sprite(self.sprite_list, 0, - self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( - "%s/images/palettevertical.svg" % (self.path))))) - self.palette_button[0].name = _('orientation') - self.palette_button[1].name = _('orientation') - self.palette_button[0].type = 'palette' - self.palette_button[1].type = 'palette' - self.palette_button[self.orientation].set_layer(TAB_LAYER) - self.palette_button[1-self.orientation].hide() - - # Create the palette next button - self.palette_button.append(Sprite(self.sprite_list, 16, - self.toolbar_offset, svg_str_to_pixbuf(svg_from_file( - "%s/images/palettenext.svg" %(self.path))))) - self.palette_button[2].name = _('next') - self.palette_button[2].type = 'palette' - self.palette_button[2].set_layer(TAB_LAYER) - - if init_only: - return - - # Hide the previously displayed palette - self._hide_previous_palette() - - self.selected_palette = n - self.previous_palette = self.selected_palette - - if self.activity is None or not self.activity.new_sugar_system: - self.selected_selector = self.selectors[n] - # Make sure all of the selectors are visible. - self.selectors[n].set_shape(self.selector_shapes[n][1]) - for i in range(len(PALETTES)): - self.selectors[i].set_layer(TAB_LAYER) - - # 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) - - if self.palettes[n] == []: - # Create 'proto' blocks for each palette entry - for i, name in enumerate(PALETTES[n]): - self.palettes[n].append(Block(self.block_list, - self.sprite_list, name, - 0, 0, 'proto', [], PALETTE_SCALE)) - self.palettes[n][i].spr.set_layer(TAB_LAYER) - self.palettes[n][i].unhighlight() - - # Some proto blocks get a skin. - if name in BOX_STYLE_MEDIA: - self._proto_skin(name+'small', n, i) - elif name[:8] == 'template': - self._proto_skin(name[8:], n, i) - elif name[:7] == 'picture': - self._proto_skin(name[7:], n, i) - elif name in PYTHON_SKIN: - self._proto_skin('pythonsmall', n, i) - - self._layout_palette(n) - for blk in self.palettes[n]: - blk.spr.set_layer(TAB_LAYER) - if n == self.trash_index: - for blk in self.trash_stack: - for gblk in find_group(blk): - if gblk.status != 'collapsed': - gblk.spr.set_layer(TAB_LAYER) - - def _hide_toolbar_palette(self): - """ Hide the toolbar palettes """ - self._hide_previous_palette() - if self.activity is None or not self.activity.new_sugar_system: - # Hide the selectors - for i in range(len(PALETTES)): - self.selectors[i].hide() - elif self.selected_palette is not None: - self.activity.palette_buttons[self.selected_palette].set_icon( - PALETTE_NAMES[self.selected_palette] + 'off') - self.selected_palette = None - self.previous_palette = None - - def _hide_previous_palette(self): - """ Hide just the previously viewed toolbar palette """ - # Hide previous palette - if self.previous_palette is not None: - for i in range(len(PALETTES[self.previous_palette])): - self.palettes[self.previous_palette][i].spr.hide() - self.palette_sprs[self.previous_palette][ - self.orientation].hide() - if self.activity is None or not self.activity.new_sugar_system: - self.selectors[self.previous_palette].set_shape( - self.selector_shapes[self.previous_palette][0]) - elif self.previous_palette is not None and \ - self.previous_palette != self.selected_palette: - self.activity.palette_buttons[self.previous_palette].set_icon( - PALETTE_NAMES[self.previous_palette] + 'off') - if self.previous_palette == self.trash_index: - for blk in self.trash_stack: - for gblk in find_group(blk): - gblk.spr.hide() - - def _horizontal_layout(self, x, y, blocks): - """ Position prototypes in a horizontal palette. """ - _max_w = 0 - for blk in blocks: - _w, _h = self._width_and_height(blk) - if y + _h > PALETTE_HEIGHT + self.toolbar_offset: - x += int(_max_w+3) - y = self.toolbar_offset + 3 - _max_w = 0 - (_bx, _by) = blk.spr.get_xy() - _dx = x-_bx - _dy = y-_by - for g in find_group(blk): - g.spr.move_relative((int(_dx), int(_dy))) - y += int(_h+3) - if _w > _max_w: - _max_w = _w - return x, y, _max_w - - def _vertical_layout(self, x, y, blocks): - """ Position prototypes in a vertical palette. """ - _row = [] - _row_w = 0 - _max_h = 0 - for _b in blocks: - _w, _h = self._width_and_height(_b) - if x + _w > PALETTE_WIDTH: - # Recenter row. - _dx = int((PALETTE_WIDTH-_row_w)/2) - for _r in _row: - for _g in find_group(_r): - _g.spr.move_relative((_dx, 0)) - _row = [] - _row_w = 0 - x = 4 - y += int(_max_h+3) - _max_h = 0 - _row.append(_b) - _row_w += (4 + _w) - (_bx, _by) = _b.spr.get_xy() - _dx = int(x - _bx) - _dy = int(y - _by) - for _g in find_group(_b): - _g.spr.move_relative((_dx, _dy)) - x += int(_w + 4) - if _h > _max_h: - _max_h = _h - # Recenter last row. - _dx = int((PALETTE_WIDTH - _row_w)/2) - for _r in _row: - for _g in find_group(_r): - _g.spr.move_relative((_dx, 0)) - return x, y, _max_h - - def _layout_palette(self, n): - """ Layout prototypes in a palette. """ - if n is not None: - if self.orientation == HORIZONTAL_PALETTE: - _x, _y = 20, self.toolbar_offset + 5 - _x, _y, _max = self._horizontal_layout(_x, _y, self.palettes[n]) - if n == self.trash_index: - _x, _y, _max = self._horizontal_layout(_x+_max, _y, - self.trash_stack) - _w = _x + _max + 25 - if self.palette_sprs[n][self.orientation] is None: - svg = SVG() - self.palette_sprs[n][self.orientation] = Sprite( - self.sprite_list, 0, self.toolbar_offset, - svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT))) - self.palette_sprs[n][self.orientation].type = 'category' - if n == PALETTE_NAMES.index('trash'): - svg = SVG() - self.palette_sprs[n][self.orientation].set_shape( - svg_str_to_pixbuf(svg.palette(_w, PALETTE_HEIGHT))) - self.palette_button[2].move((_w-20, self.toolbar_offset)) - else: - _x, _y = 5, self.toolbar_offset + 15 - _x, _y, _max = self._vertical_layout(_x, _y, self.palettes[n]) - if n == PALETTE_NAMES.index('trash'): - _x, _y, _max = self._vertical_layout(_x, _y + _max, - self.trash_stack) - _h = _y + _max + 25 - self.toolbar_offset - if self.palette_sprs[n][self.orientation] is None: - svg = SVG() - self.palette_sprs[n][self.orientation] = \ - Sprite(self.sprite_list, 0, self.toolbar_offset, - svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h))) - self.palette_sprs[n][self.orientation].type = 'category' - if n == PALETTE_NAMES.index('trash'): - svg = SVG() - self.palette_sprs[n][self.orientation].set_shape( - svg_str_to_pixbuf(svg.palette(PALETTE_WIDTH, _h))) - self.palette_button[2].move((PALETTE_WIDTH-20, - self.toolbar_offset)) - self.palette_sprs[n][self.orientation].set_layer(CATEGORY_LAYER) - - def _buttonpress_cb(self, win, event): - """ Button press """ - self.window.grab_focus() - x, y = xy(event) - self.mouse_flag = 1 - self.mouse_x = x - self.mouse_y = y - self.button_press(event.get_state()>k.gdk.CONTROL_MASK, x, y) - return True - - def button_press(self, mask, x, y, verbose=False): - if verbose: - print "processing remote button press: %d, %d" % (x, y) - self.block_operation = 'click' - - # Unselect things that may have been selected earlier - if self.selected_blk is not None: - self._unselect_block() - self.selected_turtle = None - # Always hide the status layer on a click - if self.status_spr is not None: - self.status_spr.hide() - - # Find out what was clicked - spr = self.sprite_list.find_sprite((x, y)) - self.dx = 0 - self.dy = 0 - if spr is None: - return True - self.selected_spr = spr - - # From the sprite at x, y, look for a corresponding block - blk = self.block_list.spr_to_block(spr) - if blk is not None: - if blk.type == 'block': - self.selected_blk = blk - self._block_pressed(x, y, blk) - elif blk.type == 'trash': - self._restore_from_trash(find_top_block(blk)) - elif blk.type == 'proto': - if blk.name == 'restoreall': - self._restore_all_from_trash() - elif blk.name == 'restore': - self._restore_latest_from_trash() - elif blk.name == 'empty': - self._empty_trash() - elif MACROS.has_key(blk.name): - self._new_macro(blk.name, x + 20, y + 20) - else: - blk.highlight() - self._new_block(blk.name, x, y) - blk.unhighlight() - return True - - # Next, look for a turtle - t = self.turtles.spr_to_turtle(spr) - if t is not None: - self.selected_turtle = t - self.canvas.set_turtle(self.turtles.get_turtle_key(t)) - self._turtle_pressed(x, y) - return True - - # Finally, check for anything else - if hasattr(spr, 'type'): - if spr.type == "canvas": - pass - # spr.set_layer(CANVAS_LAYER) - elif spr.type == 'selector': - self._select_category(spr) - elif spr.type == 'category': - if hide_button_hit(spr, x, y): - self.hideshow_palette(False) - elif spr.type == 'palette': - if spr.name == _('next'): - i = self.selected_palette + 1 - if i == len(PALETTE_NAMES): - i = 0 - if self.activity is None or \ - not self.activity.new_sugar_system: - self._select_category(self.selectors[i]) - else: - if self.selected_palette is not None: - self.activity.palette_buttons[ - self.selected_palette].set_icon( - PALETTE_NAMES[self.selected_palette] + 'off') - self.activity.palette_buttons[i].set_icon( - PALETTE_NAMES[i] + 'on') - self.show_palette(i) - else: - self.orientation = 1 - self.orientation - self.palette_button[self.orientation].set_layer(TAB_LAYER) - self.palette_button[1 - self.orientation].hide() - self.palette_sprs[self.selected_palette][ - 1 - self.orientation].hide() - self._layout_palette(self.selected_palette) - self.show_palette(self.selected_palette) - elif spr.type == 'toolbar': - self._select_toolbar_button(spr) - return True - - def _select_category(self, spr): - """ Select a category from the toolbar (old Sugar systems only). """ - i = self.selectors.index(spr) - spr.set_shape(self.selector_shapes[i][1]) - if self.selected_selector is not None: - j = self.selectors.index(self.selected_selector) - if i == j: - return - self.selected_selector.set_shape(self.selector_shapes[j][0]) - self.previous_selector = self.selected_selector - self.selected_selector = spr - self.show_palette(i) - - def _select_toolbar_button(self, spr): - """ Select a toolbar button (Used when not running Sugar). """ - if not hasattr(spr, 'name'): - return - if spr.name == 'run-fastoff': - self.lc.trace = 0 - self.run_button(0) - elif spr.name == 'run-slowoff': - self.lc.trace = 0 - self.run_button(3) - elif spr.name == 'debugoff': - self.lc.trace = 1 - self.run_button(6) - elif spr.name == 'stopiton': - self.stop_button() - self.toolbar_shapes['stopiton'].hide() - elif spr.name == 'eraseron': - self.eraser_button() - elif spr.name == 'hideshowoff': - self.hideshow_button() - - def _put_in_trash(self, blk, x=0, y=0): - """ Put a group of blocks into the trash. """ - self.trash_stack.append(blk) - group = find_group(blk) - for gblk in group: - if gblk.status == 'collapsed': - # Collapsed stacks are restored for rescaling - # and then recollapsed after they are moved to the trash. - bot = find_sandwich_bottom(gblk) - if collapsed(bot): - dy = bot.values[0] - restore_stack(find_sandwich_top(gblk)) - bot.values[0] = dy - gblk.type = 'trash' - gblk.rescale(self.trash_scale) - blk.spr.move((x, y)) - for gblk in group: - self._adjust_dock_positions(gblk) - - # Re-collapsing any stacks we had restored for scaling - for gblk in group: - if collapsed(gblk): - collapse_stack(find_sandwich_top(gblk)) - - # And resize any skins. - for gblk in group: - if gblk.name in BLOCKS_WITH_SKIN: - self._resize_skin(gblk) - - # self.show_palette(self.trash_index) - if self.selected_palette != self.trash_index: - for gblk in group: - gblk.spr.hide() - - def _restore_all_from_trash(self): - """ Restore all the blocks in the trash can. """ - for blk in self.block_list.list: - if blk.type == 'trash': - self._restore_from_trash(blk) - - def _restore_latest_from_trash(self): - """ Restore most recent blocks from the trash can. """ - if len(self.trash_stack) == 0: - return - self._restore_from_trash(self.trash_stack[len(self.trash_stack) - 1]) - - def _restore_from_trash(self, blk): - group = find_group(blk) - for gblk in group: - gblk.rescale(self.block_scale) - gblk.spr.set_layer(BLOCK_LAYER) - x, y = gblk.spr.get_xy() - if self.orientation == 0: - gblk.spr.move((x, y + PALETTE_HEIGHT + self.toolbar_offset)) - else: - gblk.spr.move((x + PALETTE_WIDTH, y)) - gblk.type = 'block' - for gblk in group: - self._adjust_dock_positions(gblk) - # If the stack had been collapsed before going into the trash, - # collapse it again now. - for gblk in group: - if collapsed(gblk): - collapse_stack(find_sandwich_top(gblk)) - # And resize any skins. - for gblk in group: - if gblk.name in BLOCKS_WITH_SKIN: - self._resize_skin(gblk) - - self.trash_stack.remove(blk) - - def _empty_trash(self): - """ Permanently remove all blocks presently in the trash can. """ - for blk in self.block_list.list: - if blk.type == 'trash': - blk.type = 'deleted' - blk.spr.hide() - self.trash_stack = [] - - def _in_the_trash(self, x, y): - """ Is x, y over the trash can? """ - """ - if self.selected_palette == self.trash_index and \ - self.palette_sprs[self.trash_index][self.orientation].hit((x, y)): - return True - """ - if self.selected_palette is not None and\ - self.palette_sprs[self.selected_palette][self.orientation].hit( - (x, y)): - return True - return False - - def _block_pressed(self, x, y, blk): - """ Block pressed """ - if blk is not None: - blk.highlight() - self._disconnect(blk) - self.drag_group = find_group(blk) - (sx, sy) = blk.spr.get_xy() - self.drag_pos = x-sx, y-sy - for blk in self.drag_group: - if blk.status != 'collapsed': - blk.spr.set_layer(TOP_LAYER) - self.saved_string = blk.spr.labels[0] - - def _unselect_block(self): - """ Unselect block """ - # After unselecting a 'number' block, we need to check its value - if self.selected_blk.name == 'number': - self._number_check() - elif self.selected_blk.name == 'string': - self._string_check() - self.selected_blk.unhighlight() - self.selected_blk = None - - def _new_block(self, name, x, y): - """ Make a new block. """ - if name in CONTENT_BLOCKS: - newblk = Block(self.block_list, self.sprite_list, name, x - 20, - y - 20, 'block', DEFAULTS[name], self.block_scale) - else: - newblk = Block(self.block_list, self.sprite_list, name, x - 20, - y - 20, 'block', [], self.block_scale) - - # Add a 'skin' to some blocks - if name in PYTHON_SKIN: - if self.nop == 'pythonloaded': - self._block_skin('pythonon', newblk) - else: - self._block_skin('pythonoff', newblk) - elif name in BOX_STYLE_MEDIA: - self._block_skin(name+'off', newblk) - - newspr = newblk.spr - newspr.set_layer(TOP_LAYER) - self.drag_pos = 20, 20 - newblk.connections = [None]*len(newblk.docks) - if DEFAULTS.has_key(newblk.name): - for i, argvalue in enumerate(DEFAULTS[newblk.name]): - # skip the first dock position since it is always a connector - dock = newblk.docks[i + 1] - argname = dock[0] - if argname == 'unavailable': - continue - if argname == 'media': - argname = 'journal' - elif argname == 'number' and \ - (type(argvalue) is str or type(argvalue) is unicode): - argname = 'string' - elif argname == 'bool': - argname = argvalue - elif argname == 'flow': - argname = argvalue - (sx, sy) = newspr.get_xy() - if argname is not None: - if argname in CONTENT_BLOCKS: - argblk = Block(self.block_list, self.sprite_list, - argname, 0, 0, 'block', [argvalue], - self.block_scale) - else: - argblk = Block(self.block_list, self.sprite_list, - argname, 0, 0, 'block', [], - self.block_scale) - argdock = argblk.docks[0] - nx = sx + dock[2] - argdock[2] - ny = sy + dock[3] - argdock[3] - if argname == 'journal': - self._block_skin('journaloff', argblk) - argblk.spr.move((nx, ny)) - argblk.spr.set_layer(TOP_LAYER) - argblk.connections = [newblk, None] - newblk.connections[i + 1] = argblk - self.drag_group = find_group(newblk) - self.block_operation = 'new' - - def _new_macro(self, name, x, y): - """ Create a "macro" (predefined stack of blocks). """ - macro = MACROS[name] - macro[0][2] = x - macro[0][3] = y - top = self.process_data(macro) - self.block_operation = 'new' - self._check_collapsibles(top) - self.drag_group = find_group(top) - - def process_data(self, block_data, offset=0): - """ Process block_data (from a macro, a file, or the clipboard). """ - if offset != 0: - _logger.debug("offset is %d" % (offset)) - # Create the blocks (or turtle). - blocks = [] - for blk in block_data: - if not self._found_a_turtle(blk): - blocks.append(self.load_block(blk, offset)) - - # Make the connections. - for i in range(len(blocks)): - cons = [] - # Normally, it is simply a matter of copying the connections. - if blocks[i].connections == None: - for c in block_data[i][4]: - if c is None: - cons.append(None) - else: - cons.append(blocks[c]) - elif blocks[i].connections == 'check': - # Corner case to convert old-style boolean and arithmetic blocks - cons.append(None) # Add an extra connection. - for c in block_data[i][4]: - if c is None: - cons.append(None) - else: - cons.append(blocks[c]) - # If the boolean op was connected, readjust the plumbing. - if blocks[i].name in BOOLEAN_STYLE: - if block_data[i][4][0] is not None: - c = block_data[i][4][0] - cons[0] = blocks[block_data[c][4][0]] - c0 = block_data[c][4][0] - for j, cj in enumerate(block_data[c0][4]): - if cj == c: - blocks[c0].connections[j] = blocks[i] - if c < i: - blocks[c].connections[0] = blocks[i] - blocks[c].connections[3] = None - else: - # Connection was to a block we haven't seen yet. - print "WARNING: dock check couldn't see the future" - else: - if block_data[i][4][0] is not None: - c = block_data[i][4][0] - cons[0] = blocks[block_data[c][4][0]] - c0 = block_data[c][4][0] - for j, cj in enumerate(block_data[c0][4]): - if cj == c: - blocks[c0].connections[j] = blocks[i] - if c < i: - blocks[c].connections[0] = blocks[i] - blocks[c].connections[1] = None - else: - # Connection was to a block we haven't seen yet. - print "WARNING: dock check couldn't see the future" - else: - print "WARNING: unknown connection state %s" % \ - (str(blocks[i].connections)) - blocks[i].connections = cons[:] - - # Block sizes and shapes may have changed. - for blk in blocks: - self._adjust_dock_positions(blk) - - # Look for any stacks that need to be collapsed or sandwiched - for blk in blocks: - if collapsed(blk): - collapse_stack(find_sandwich_top(blk)) - elif blk.name == 'sandwichbottom' and collapsible(blk): - blk.svg.set_hide(True) - blk.svg.set_show(False) - blk.refresh() - grow_stack_arm(find_sandwich_top(blk)) - - # Resize blocks to current scale - self.resize_blocks(blocks) - - if len(blocks) > 0: - return blocks[0] - else: - return None - - def _adjust_dock_positions(self, blk): - """ Adjust the dock x, y positions """ - if not self.interactive_mode: - return - (sx, sy) = blk.spr.get_xy() - for i, c in enumerate(blk.connections): - if i > 0 and c is not None: - bdock = blk.docks[i] - for j in range(len(c.docks)): - if c.connections[j] == blk: - cdock = c.docks[j] - nx = sx + bdock[2] - cdock[2] - ny = sy + bdock[3] - cdock[3] - c.spr.move((nx, ny)) - self._adjust_dock_positions(c) - - def _turtle_pressed(self, x, y): - """ Turtle pressed """ - (tx, ty) = self.selected_turtle.get_xy() - dx = x - tx - 30 - dy = y - ty - 30 - if (dx * dx) + (dy * dy) > 200: - self.drag_turtle = ('turn', - self.canvas.heading - atan2(dy, dx)/DEGTOR, 0) - else: - self.drag_turtle = ('move', x - tx, y - ty) - - def _move_cb(self, win, event): - """ Mouse move """ - x, y = xy(event) - self._mouse_move(x, y) - return True - - def _mouse_move(self, x, y, verbose=False, mdx=0, mdy=0): - if verbose: - print "processing remote mouse move: %d, %d" % (x, y) - - self.block_operation = 'move' - # First, check to see if we are dragging or rotating a turtle. - if self.selected_turtle is not None: - dtype, dragx, dragy = self.drag_turtle - (sx, sy) = self.selected_turtle.get_xy() - if dtype == 'move': - if mdx != 0 or mdy != 0: - dx, dy = mdx, mdy - else: - dx = x - dragx - sx - dy = y - dragy - sy - self.selected_turtle.move((sx + dx, sy + dy)) - else: - if mdx != 0 or mdy != 0: - dx = mdx - dy = mdy - else: - dx = x - sx - 30 - dy = y - sy - 30 - self.canvas.seth(int(dragx + atan2(dy, dx)/DEGTOR + 5)/10 * 10) - # If we are hoving, show popup help. - elif self.drag_group is None: - self._show_popup(x, y) - return - # If we have a stack of blocks selected, move them. - elif self.drag_group[0] is not None: - blk = self.drag_group[0] - # Don't move a bottom blk is the stack is collapsed - if collapsed(blk): - return - - self.selected_spr = blk.spr - dragx, dragy = self.drag_pos - if mdx != 0 or mdy != 0: - dx = mdx - dy = mdy - else: - (sx, sy) = blk.spr.get_xy() - dx = x - dragx - sx - dy = y - dragy - sy - - # Take no action if there was a move of 0,0. - if dx == 0 and dy == 0: - return - self.drag_group = find_group(blk) - - # Prevent blocks from ending up with a negative x... - for gblk in self.drag_group: - (bx, by) = gblk.spr.get_xy() - if bx + dx < 0: - dx += -(bx + dx) - """ - # ...or under the palette. - if self.selected_palette is not None and\ - self.selected_palette != self.trash_index: - w, h = self.palette_sprs[self.selected_palette][ - self.orientation].get_dimensions() - if self.orientation == HORIZONTAL_PALETTE: - if bx < w and\ - by+dy < self.toolbar_offset+PALETTE_HEIGHT: - dy += -(by+dy)+self.toolbar_offset+PALETTE_HEIGHT - else: - if by < h+self.toolbar_offset and bx+dx < PALETTE_WIDTH: - dx += -(bx+dx)+PALETTE_WIDTH - """ - - # Move the stack. - for gblk in self.drag_group: - (bx, by) = gblk.spr.get_xy() - gblk.spr.move((bx + dx, by + dy)) - if mdx != 0 or mdy != 0: - dx = 0 - dy = 0 - else: - self.dx += dx - self.dy += dy - - def _show_popup(self, x, y): - """ Let's help our users by displaying a little help. """ - spr = self.sprite_list.find_sprite((x, y)) - blk = self.block_list.spr_to_block(spr) - if spr and blk is not None: - if self.timeout_tag[0] == 0: - self.timeout_tag[0] = self._do_show_popup(blk.name) - self.selected_spr = spr - else: - if self.timeout_tag[0] > 0: - try: - gobject.source_remove(self.timeout_tag[0]) - self.timeout_tag[0] = 0 - except: - self.timeout_tag[0] = 0 - elif spr and hasattr(spr,'type') and (spr.type == 'selector' or\ - spr.type == 'palette' or\ - spr.type == 'toolbar'): - if self.timeout_tag[0] == 0 and hasattr(spr, 'name'): - self.timeout_tag[0] = self._do_show_popup(spr.name) - self.selected_spr = spr - else: - if self.timeout_tag[0] > 0: - try: - gobject.source_remove(self.timeout_tag[0]) - self.timeout_tag[0] = 0 - except: - self.timeout_tag[0] = 0 - else: - if self.timeout_tag[0] > 0: - try: - gobject.source_remove(self.timeout_tag[0]) - self.timeout_tag[0] = 0 - except: - self.timeout_tag[0] = 0 - - def _do_show_popup(self, block_name): - """ Fetch the help text and display it. """ - if SPECIAL_NAMES.has_key(block_name): - block_name_s = SPECIAL_NAMES[block_name] - elif BLOCK_NAMES.has_key(block_name): - block_name_s = BLOCK_NAMES[block_name][0] - elif block_name in TOOLBAR_SHAPES: - block_name_s = '' - else: - block_name_s = _(block_name) - if HELP_STRINGS.has_key(block_name): - if block_name_s == '': - label = HELP_STRINGS[block_name] - else: - label = block_name_s + ": " + HELP_STRINGS[block_name] - else: - label = block_name_s - if self.running_sugar: - self.activity.hover_help_label.set_text(label) - self.activity.hover_help_label.show() - else: - if self.interactive_mode: - self.win.set_title(_("Turtle Art") + " — " + label) - return 0 - - def _buttonrelease_cb(self, win, event): - """ Button release """ - x, y = xy(event) - self.button_release(x, y) - return True - - def button_release(self, x, y, verbose=False): - # We may have been moving the turtle - if self.selected_turtle is not None: - (tx, ty) = self.selected_turtle.get_xy() - (cx, cy) = self.canvas.canvas.get_xy() - # self.canvas.xcor = tx - self.canvas.canvas._width/2 + 30 - cx - # self.canvas.ycor = self.canvas.canvas._height/2 - ty - 30 + cy - self.canvas.xcor = tx - self.canvas.width/2 + 30 - cx - self.canvas.ycor = self.canvas.height/2 - ty - 30 + cy - self.canvas.move_turtle() - if self.running_sugar: - self.display_coordinates() - self.selected_turtle = None - return - - # If we don't have a group of blocks, then there is nothing to do. - if self.drag_group == None: - return - - blk = self.drag_group[0] - # Remove blocks by dragging them onto the trash palette. - if self.block_operation == 'move' and self._in_the_trash(x, y): - self._put_in_trash(blk, x, y) - self.drag_group = None - return - - # Pull a stack of new blocks off of the category palette. - if self.block_operation == 'new': - for gblk in self.drag_group: - (bx, by) = gblk.spr.get_xy() - if self.orientation == 0: - gblk.spr.move((bx+20, - by+PALETTE_HEIGHT+self.toolbar_offset)) - else: - gblk.spr.move((bx+PALETTE_WIDTH, by+20)) - - # Look to see if we can dock the current stack. - self._snap_to_dock() - self._check_collapsibles(blk) - for gblk in self.drag_group: - if gblk.status != 'collapsed': - gblk.spr.set_layer(BLOCK_LAYER) - self.drag_group = None - - # Find the block we clicked on and process it. - if self.block_operation == 'click': - self._click_block(x, y) - - def _click_block(self, x, y): - """ Click block """ - blk = self.block_list.spr_to_block(self.selected_spr) - if blk is None: - return - self.selected_blk = blk - if blk.name == 'number' or blk.name == 'string': - self.saved_string = blk.spr.labels[0] - blk.spr.labels[0] += CURSOR - elif blk.name in BOX_STYLE_MEDIA: - self._import_from_journal(self.selected_blk) - if blk.name == 'journal' and self.running_sugar: - self._load_description_block(blk) - elif blk.name == 'identity2' or blk.name == 'hspace': - group = find_group(blk) - if hide_button_hit(blk.spr, x, y): - dx = blk.reset_x() - elif show_button_hit(blk.spr, x, y): - dx = 20 - blk.expand_in_x(dx) - else: - dx = 0 - for gblk in group: - if gblk != blk: - gblk.spr.move_relative((dx * blk.scale, 0)) - elif blk.name == 'vspace': - group = find_group(blk) - if hide_button_hit(blk.spr, x, y): - dy = blk.reset_y() - elif show_button_hit(blk.spr, x, y): - dy = 20 - blk.expand_in_y(dy) - else: - dy = 0 - for gblk in group: - if gblk != blk: - gblk.spr.move_relative((0, dy * blk.scale)) - grow_stack_arm(find_sandwich_top(blk)) - elif blk.name in EXPANDABLE or blk.name == 'nop': - if show_button_hit(blk.spr, x, y): - n = len(blk.connections) - group = find_group(blk.connections[n-1]) - if blk.name == 'myfunc1arg': - blk.spr.labels[1] = 'f(x, y)' - blk.spr.labels[2] = ' ' - dy = blk.add_arg() - blk.primitive = 'myfunction2' - blk.name = 'myfunc2arg' - elif blk.name == 'myfunc2arg': - blk.spr.labels[1] = 'f(x, y, z)' - dy = blk.add_arg(False) - blk.primitive = 'myfunction3' - blk.name = 'myfunc3arg' - elif blk.name == 'userdefined': - dy = blk.add_arg() - blk.primitive = 'userdefined2' - blk.name = 'userdefined2args' - elif blk.name == 'userdefined2args': - dy = blk.add_arg(False) - blk.primitive = 'userdefined3' - blk.name = 'userdefined3args' - else: - dy = blk.add_arg() - for gblk in group: - gblk.spr.move_relative((0, dy)) - blk.connections.append(blk.connections[n-1]) - argname = blk.docks[n-1][0] - argvalue = DEFAULTS[blk.name][len(DEFAULTS[blk.name])-1] - argblk = Block(self.block_list, self.sprite_list, argname, - 0, 0, 'block', [argvalue], self.block_scale) - argdock = argblk.docks[0] - (bx, by) = blk.spr.get_xy() - nx = bx + blk.docks[n - 1][2] - argdock[2] - ny = by + blk.docks[n - 1][3] - argdock[3] - argblk.spr.move((nx, ny)) - argblk.spr.set_layer(TOP_LAYER) - argblk.connections = [blk, None] - blk.connections[n - 1] = argblk - grow_stack_arm(find_sandwich_top(blk)) - elif blk.name in PYTHON_SKIN and self.myblock == None: - self._import_py() - else: - self._run_stack(blk) - elif blk.name in COLLAPSIBLE: - top = find_sandwich_top(blk) - if collapsed(blk): - restore_stack(top) - elif top is not None: - collapse_stack(top) - else: - self._run_stack(blk) - - def _check_collapsibles(self, blk): - """ Check the state of collapsible blocks upon change in dock state. """ - group = find_group(blk) - for gblk in group: - if gblk.name in COLLAPSIBLE: - if collapsed(gblk): - gblk.svg.set_show(True) - gblk.svg.set_hide(False) - reset_stack_arm(find_sandwich_top(gblk)) - elif collapsible(gblk): - gblk.svg.set_hide(True) - gblk.svg.set_show(False) - grow_stack_arm(find_sandwich_top(gblk)) - else: - gblk.svg.set_hide(False) - gblk.svg.set_show(False) - # Ouch: When you tear off the sandwich bottom, you - # no longer have access to the group with the sandwich top - # so check them all. - for b in self.just_blocks(): - if b.name == 'sandwichtop': - if find_sandwich_bottom(b) is None: - reset_stack_arm(b) - gblk.refresh() - - def _run_stack(self, blk): - """ Run a stack of blocks. """ - if blk is None: - return - self.lc.ag = None - top = find_top_block(blk) - self.lc.run_blocks(top, self.just_blocks(), True) - if self.interactive_mode: - gobject.idle_add(self.lc.doevalstep) - else: - while self.lc.doevalstep(): - pass - - def _snap_to_dock(self): - """ Snap a block to the dock of another block. """ - my_block = self.drag_group[0] - d = 200 - for my_dockn in range(len(my_block.docks)): - for your_block in self.just_blocks(): - # don't link to a block to which you're already connected - if your_block in self.drag_group: - continue - # check each dock of your_block for a possible connection - for your_dockn in range(len(your_block.docks)): - this_xy = dock_dx_dy(your_block, your_dockn, - my_block, my_dockn) - if magnitude(this_xy) > d: - continue - d = magnitude(this_xy) - best_xy = this_xy - best_you = your_block - best_your_dockn = your_dockn - best_my_dockn = my_dockn - if d < 200: - if not arithmetic_check(my_block, best_you, best_my_dockn, - best_your_dockn): - return - for blk in self.drag_group: - (sx, sy) = blk.spr.get_xy() - blk.spr.move((sx + best_xy[0], sy + best_xy[1])) - - # If there was already a block docked there, move it to the trash. - blk_in_dock = best_you.connections[best_your_dockn] - if blk_in_dock is not None: - blk_in_dock.connections[0] = None - self._put_in_trash(blk_in_dock) - - best_you.connections[best_your_dockn] = my_block - if my_block.connections is not None: - my_block.connections[best_my_dockn] = best_you - - def _import_from_journal(self, blk): - """ Import a file from the Sugar Journal """ - if self.running_sugar: - chooser = ObjectChooser('Choose image', self.parent, - gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT) - try: - result = chooser.run() - if result == gtk.RESPONSE_ACCEPT: - dsobject = chooser.get_selected_object() - self._update_media_icon(blk, dsobject, dsobject.object_id) - dsobject.destroy() - finally: - chooser.destroy() - del chooser - else: - fname, self.load_save_folder = \ - get_load_name('.*', self.load_save_folder) - if fname is None: - return - self._update_media_icon(blk, fname) - - def _load_description_block(self, blk): - """ Look for a corresponding description block """ - if blk == None or blk.name != 'journal' or len(blk.values) == 0 or\ - blk.connections[0] is None: - return - _blk = blk.connections[0] - dblk = find_blk_below(_blk, 'description') - # Autoupdate the block if it is empty - if dblk != None and (len(dblk.values) == 0 or dblk.values[0] == None): - self._update_media_icon(dblk, None, blk.values[0]) - - def _update_media_icon(self, blk, name, value=''): - """ Update the icon on a 'loaded' media block. """ - if blk.name == 'journal': - self._load_image_thumb(name, blk) - elif blk.name == 'audio': - self._block_skin('audioon', blk) - else: - self._block_skin('descriptionon', blk) - if value == '': - value = name - if len(blk.values) > 0: - blk.values[0] = value - else: - blk.values.append(value) - blk.spr.set_label(' ') - - def _load_image_thumb(self, picture, blk): - """ Replace icon with a preview image. """ - pixbuf = None - self._block_skin('descriptionon', blk) - - if self.running_sugar: - w, h = calc_image_size(blk.spr) - pixbuf = get_pixbuf_from_journal(picture, w, h) - else: - if movie_media_type(picture): - self._block_skin('journalon', blk) - elif audio_media_type(picture): - self._block_skin('audioon', blk) - blk.name = 'audio' - elif image_media_type(picture): - w, h = calc_image_size(blk.spr) - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(picture, w, h) - else: - blk.name = 'description' - if pixbuf is not None: - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - self._resize_skin(blk) - - def _disconnect(self, blk): - """ Disconnect block from stack above it. """ - if blk.connections[0] == None: - return - if collapsed(blk): - return - blk2 = blk.connections[0] - blk2.connections[blk2.connections.index(blk)] = None - blk.connections[0] = None - - def _keypress_cb(self, area, event): - """ Keyboard """ - keyname = gtk.gdk.keyval_name(event.keyval) - keyunicode = gtk.gdk.keyval_to_unicode(event.keyval) - - if event.get_state()>k.gdk.MOD1_MASK: - alt_mask = True - alt_flag = 'T' - else: - alt_mask = False - alt_flag = 'F' - self._key_press(alt_mask, keyname, keyunicode) - return keyname - - def _key_press(self, alt_mask, keyname, keyunicode, verbose=False): - if keyname is None: - return False - if verbose: - print "processing remote key press: %s" % (keyname) - - self.keypress = keyname - - # First, process Alt keys. - if alt_mask and self.selected_blk is not None: - if keyname == "p": - self.hideshow_button() - elif keyname == 'q': - exit() - return True - # Process keyboard input for 'number' blocks - if self.selected_blk is not None and \ - self.selected_blk.name == 'number': - self._process_numeric_input(keyname) - return True - # Process keyboard input for 'string' blocks - elif self.selected_blk is not None and \ - self.selected_blk.name == 'string': - self.process_alphanumeric_input(keyname, keyunicode) - if self.selected_blk is not None: - self.selected_blk.resize() - return True - # Otherwise, use keyboard input to move blocks or turtles - else: - self._process_keyboard_commands(keyname) - if self.selected_blk is None: - return False - - def _process_numeric_input(self, keyname): - ''' Make sure numeric input is valid. ''' - oldnum = self.selected_blk.spr.labels[0].replace(CURSOR, '') - if len(oldnum) == 0: - oldnum = '0' - if keyname == 'minus': - if oldnum == '0': - newnum = '-' - elif oldnum[0] != '-': - newnum = '-' + oldnum - else: - newnum = oldnum - elif keyname == 'period' and '.' not in oldnum: - newnum = oldnum + '.' - elif keyname == 'BackSpace': - if len(oldnum) > 0: - newnum = oldnum[:len(oldnum)-1] - else: - newnum = '' - elif keyname in ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9']: - if oldnum == '0': - newnum = keyname - else: - newnum = oldnum + keyname - elif keyname == 'Return': - self._unselect_block() - return - else: - newnum = oldnum - if newnum == '.': - newnum = '0.' - if len(newnum) > 0 and newnum != '-': - try: - float(newnum) - except ValueError, e: - newnum = oldnum - self.selected_blk.spr.set_label(newnum + CURSOR) - - def process_alphanumeric_input(self, keyname, keyunicode): - """ Make sure alphanumeric input is properly parsed. """ - if len(self.selected_blk.spr.labels[0]) > 0: - c = self.selected_blk.spr.labels[0].count(CURSOR) - if c == 0: - oldleft = self.selected_blk.spr.labels[0] - oldright = '' - elif len(self.selected_blk.spr.labels[0]) == 1: - oldleft = '' - oldright = '' - else: - try: # Why are getting a ValueError on occasion? - oldleft, oldright = \ - self.selected_blk.spr.labels[0].split(CURSOR) - except ValueError: - print "[%s]" % self.selected_blk.spr.labels[0] - oldleft = self.selected_blk.spr.labels[0] - oldright = '' - else: - oldleft = '' - oldright = '' - newleft = oldleft - if keyname in ['Shift_L', 'Shift_R', 'Control_L', 'Caps_Lock', \ - 'Alt_L', 'Alt_R', 'KP_Enter', 'ISO_Level3_Shift']: - keyname = '' - keyunicode = 0 - # Hack until I sort out input and unicode and dead keys, - if keyname[0:5] == 'dead_': - self.dead_key = keyname - keyname = '' - keyunicode = 0 - if keyname == 'space': - keyunicode = 32 - elif keyname == 'Tab': - keyunicode = 9 - if keyname == 'BackSpace': - if len(oldleft) > 1: - newleft = oldleft[:len(oldleft)-1] - else: - newleft = '' - elif keyname == 'Home': - oldright = oldleft+oldright - newleft = '' - elif keyname == 'Left': - if len(oldleft) > 0: - oldright = oldleft[len(oldleft)-1:]+oldright - newleft = oldleft[:len(oldleft)-1] - elif keyname == 'Right': - if len(oldright) > 0: - newleft = oldleft + oldright[0] - oldright = oldright[1:] - elif keyname == 'End': - newleft = oldleft+oldright - oldright = '' - elif keyname == 'Return': - newleft = oldleft+RETURN - elif keyname == 'Down': - self._unselect_block() - return - elif keyname == 'Up' or keyname == 'Escape': # Restore previous state - self.selected_blk.spr.set_label(self.saved_string) - self._unselect_block() - return - else: - if self.dead_key is not '': - keyunicode = \ - DEAD_DICTS[DEAD_KEYS.index(self.dead_key[5:])][keyname] - self.dead_key = '' - if keyunicode > 0: - if unichr(keyunicode) != '\x00': - newleft = oldleft+unichr(keyunicode) - else: - newleft = oldleft - elif keyunicode == -1: # clipboard text - if keyname == '\n': - newleft = oldleft+RETURN - else: - newleft = oldleft+keyname - self.selected_blk.spr.set_label("%s%s%s" % (newleft, CURSOR, oldright)) - - def _process_keyboard_commands(self, keyname): - """ Use the keyboard to move blocks and turtle """ - mov_dict = {'KP_Up':[0, 10], 'j':[0, 10], 'Up':[0, 10], - 'KP_Down':[0, -10], 'k':[0, -10], 'Down':[0, -10], - 'KP_Left':[-10, 0], 'h':[-10, 0], 'Left':[-10, 0], - 'KP_Right':[10, 0], 'l':[10, 0], 'Right':[10, 0], - 'KP_Page_Down':[0, 0], 'KP_Page_Up':[0, 0], 'KP_End':[0, 0], - 'KP_Home':[-1, -1], 'Return':[-1, -1], 'Esc':[0, 0]} - if not mov_dict.has_key(keyname): - return - if keyname == 'KP_End': - self.run_button(0) - elif self.selected_spr is not None: - blk = self.block_list.spr_to_block(self.selected_spr) - tur = self.turtles.spr_to_turtle(self.selected_spr) - if not self.lc.running and blk is not None: - if keyname == 'Return' or keyname == 'KP_Page_Up': - (x, y) = blk.spr.get_xy() - self._click_block(x, y) - elif keyname == 'KP_Page_Down': - if self.drag_group == None: - self.drag_group = find_group(blk) - for gblk in self.drag_group: - gblk.spr.hide() - self.drag_group = None - else: - self._jog_block(blk, mov_dict[keyname][0], - mov_dict[keyname][1]) - elif tur is not None: - self._jog_turtle(mov_dict[keyname][0], mov_dict[keyname][1]) - return True - - def _jog_turtle(self, dx, dy): - """ Jog turtle """ - if dx == -1 and dy == -1: - self.canvas.xcor = 0 - self.canvas.ycor = 0 - else: - self.canvas.xcor += dx - self.canvas.ycor += dy - self.canvas.move_turtle() - self.display_coordinates() - self.selected_turtle = None - - def _jog_block(self, blk, dx, dy): - """ Jog block """ - if collapsed(blk): - return - self.drag_group = find_group(blk) - # check to see if any block ends up with a negative x - for blk in self.drag_group: - (sx, sy) = blk.spr.get_xy() - if sx+dx < 0: - dx += -(sx + dx) - # move the stack - for blk in self.drag_group: - (sx, sy) = blk.spr.get_xy() - blk.spr.move((sx + dx, sy - dy)) - self._snap_to_dock() - self.drag_group = None - - def _number_check(self): - """ Make sure a 'number' block contains a number. """ - n = self.selected_blk.spr.labels[0].replace(CURSOR, '') - if n in ['-', '.', '-.']: - n = 0 - if n is not None: - try: - f = float(n) - if f > 1000000: - n = 1 - self.showlabel("#overflowerror") - elif f < -1000000: - n = -1 - self.showlabel("#overflowerror") - except ValueError: - n = 0 - self.showlabel("#notanumber") - else: - n = 0 - self.selected_blk.spr.set_label(n) - self.selected_blk.values[0] = n - - def _string_check(self): - s = self.selected_blk.spr.labels[0].replace(CURSOR, '') - self.selected_blk.spr.set_label(s) - self.selected_blk.values[0] = s.replace(RETURN, "\12") - - def load_python_code(self): - """ Load Python code from a file """ - fname, self.load_save_folder = get_load_name('.py', - self.load_save_folder) - if fname == None: - return - f = open(fname, 'r') - self.myblock = f.read() - f.close() - - def _import_py(self): - """ Import Python code into a block """ - if self.running_sugar: - self.activity.import_py() - else: - self.load_python_code() - self.set_userdefined() - - def new_project(self): - """ Start a new project """ - stop_logo(self) - self._loaded_project = "" - # Put current project in the trash. - while len(self.just_blocks()) > 0: - blk = self.just_blocks()[0] - top = find_top_block(blk) - self._put_in_trash(top) - self.canvas.clearscreen() - self.save_file_name = None - - def is_new_project(self): - """ Is this a new project or was a old project loaded from a file? """ - return self._loaded_project == "" - - def project_has_changed(self): - """ WARNING: order of JSON serialized data may have changed. """ - try: - f = open(self._loaded_project, 'r') - saved_project_data = f.read() - f.close() - except: - print "problem loading saved project data from %s" %\ - (self._loaded_project) - saved_project_data = "" - current_project_data = data_to_string(self.assemble_data_to_save()) - - return saved_project_data != current_project_data - - def load_files(self, ta_file, create_new_project=True): - """ Load a project from a file """ - if create_new_project: - self.new_project() - self._check_collapsibles(self.process_data(data_from_file(ta_file))) - self._loaded_prokect = ta_file - - def load_file(self, create_new_project=True): - _file_name, self.load_save_folder = get_load_name('.ta', - self.load_save_folder) - if _file_name == None: - return - if _file_name[-3:] == '.ta': - _file_name = _file_name[0:-3] - self.load_files(_file_name+'.ta', create_new_project) - if create_new_project: - self.save_file_name = os.path.basename(_file_name) - if self.running_sugar: - self.activity.metadata['title'] = os.path.split(_file_name)[1] - - def _found_a_turtle(self, blk): - """ Either [-1, 'turtle', ...] or [-1, ['turtle', key], ...] """ - if blk[1] == 'turtle': - self.load_turtle(blk) - return True - elif type(blk[1]) == list and blk[1][0] == 'turtle': - self.load_turtle(blk, blk[1][1]) - return True - elif type(blk[1]) == tuple: - _btype, _key = blk[1] - if _btype == 'turtle': - self.load_turtle(blk, _key) - return True - return False - - def load_turtle(self, blk, key=1): - """ Restore a turtle from its saved state """ - tid, name, xcor, ycor, heading, color, shade, pensize = blk - self.canvas.set_turtle(key) - self.canvas.setxy(xcor, ycor) - self.canvas.seth(heading) - self.canvas.setcolor(color) - self.canvas.setshade(shade) - self.canvas.setpensize(pensize) - - def load_block(self, b, offset=0): - """ Restore individual blocks from saved state """ - # A block is saved as: (i, (btype, value), x, y, (c0,... cn)) - # The x, y position is saved/loaded for backward compatibility - btype, value = b[1], None - if type(btype) == tuple: - btype, value = btype - elif type(btype) == list: - btype, value = btype[0], btype[1] - if btype in CONTENT_BLOCKS or btype in COLLAPSIBLE: - if btype == 'number': - try: - values = [round_int(value)] - except ValueError: - values = [0] - elif btype in COLLAPSIBLE: - if value is not None: - values = [int(value)] - else: - values = [] - else: - values = [value] - else: - values = [] - - if btype in OLD_DOCK: - check_dock = True - else: - check_dock = False - if OLD_NAMES.has_key(btype): - btype = OLD_NAMES[btype] - blk = Block(self.block_list, self.sprite_list, btype, - b[2] + self.canvas.cx + offset, - b[3] + self.canvas.cy + offset, - 'block', values, self.block_scale) - # Some blocks get transformed. - if btype == 'string' and blk.spr is not None: - blk.spr.set_label(blk.values[0].replace('\n', RETURN)) - elif btype == 'start': # block size is saved in start block - if value is not None: - self.block_scale = value - elif btype in EXPANDABLE or btype == 'nop': - if btype == 'vspace': - if value is not None: - blk.expand_in_y(value) - elif btype == 'hspace' or btype == 'identity2': - if value is not None: - blk.expand_in_x(value) - elif btype == 'templatelist' or btype == 'list': - for i in range(len(b[4])-4): - blk.add_arg() - elif btype == 'myfunc2arg' or btype == 'myfunc3arg' or\ - btype == 'userdefined2args' or btype == 'userdefined3args': - blk.add_arg() - if btype == 'myfunc3arg' or btype == 'userdefined3args': - blk.add_arg(False) - if btype in PYTHON_SKIN: - if self.nop == 'pythonloaded': - self._block_skin('pythonon', blk) - else: - self._block_skin('pythonoff', blk) - elif btype in BOX_STYLE_MEDIA and blk.spr is not None: - if len(blk.values) == 0 or blk.values[0] == 'None' or\ - blk.values[0] == None: - self._block_skin(btype+'off', blk) - elif btype == 'audio' or btype == 'description': - self._block_skin(btype+'on', blk) - elif self.running_sugar: - try: - dsobject = datastore.get(blk.values[0]) - if not movie_media_type(dsobject.file_path[-4:]): - w, h, = calc_image_size(blk.spr) - pixbuf = get_pixbuf_from_journal(dsobject, w, h) - if pixbuf is not None: - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - else: - self._block_skin('journalon', blk) - dsobject.destroy() - except: - try: - w, h, = calc_image_size(blk.spr) - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( - blk.values[0], w, h) - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - except: - print "Warning: Couldn't open dsobject (%s)" % \ - (blk.values[0]) - self._block_skin('journaloff', blk) - else: - if not movie_media_type(blk.values[0][-4:]): - try: - w, h, = calc_image_size(blk.spr) - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size( - blk.values[0], w, h) - x, y = self._calc_image_offset('', blk.spr) - blk.set_image(pixbuf, x, y) - except: - self._block_skin('journaloff', blk) - else: - self._block_skin('journalon', blk) - blk.spr.set_label(' ') - blk.resize() - - if self.interactive_mode: - blk.spr.set_layer(BLOCK_LAYER) - if check_dock: - blk.connections = 'check' - return blk - - def load_start(self, ta_file=None): - """ Start a new project with a 'start' brick """ - if ta_file is None: - self.process_data([[0, "start", PALETTE_WIDTH + 20, - self.toolbar_offset+PALETTE_HEIGHT + 20, - [None, None]]]) - else: - self.process_data(data_from_file(ta_file)) - - def save_file(self, _file_name=None): - """ Start a project to a file """ - if self.save_folder is not None: - self.load_save_folder = self.save_folder - if _file_name is None: - _file_name, self.load_save_folder = get_save_name('.ta', - self.load_save_folder, self.save_file_name) - if _file_name is None: - return - if _file_name[-3:] == '.ta': - _file_name = _file_name[0:-3] - data_to_file(self.assemble_data_to_save(), _file_name + '.ta') - self.save_file_name = os.path.basename(_file_name) - if not self.running_sugar: - self.save_folder = self.load_save_folder - - def assemble_data_to_save(self, save_turtle=True, save_project=True): - """ Pack the project (or stack) into a data stream to be serialized """ - _data = [] - _blks = [] - - if save_project: - _blks = self.just_blocks() - else: - if self.selected_blk is None: - return [] - _blks = find_group(find_top_block(self.selected_blk)) - - for _i, _blk in enumerate(_blks): - _blk.id = _i - for _blk in _blks: - if _blk.name in CONTENT_BLOCKS or _blk.name in COLLAPSIBLE: - if len(_blk.values) > 0: - _name = (_blk.name, _blk.values[0]) - else: - _name = (_blk.name) - elif _blk.name in EXPANDABLE: - _ex, _ey = _blk.get_expand_x_y() - if _ex > 0: - _name = (_blk.name, _ex) - elif _ey > 0: - _name = (_blk.name, _ey) - else: - _name = (_blk.name, 0) - elif _blk.name == 'start': # save block_size in start block - _name = (_blk.name, self.block_scale) - else: - _name = (_blk.name) - if hasattr(_blk, 'connections'): - connections = [get_id(_cblk) for _cblk in _blk.connections] - else: - connections = None - (_sx, _sy) = _blk.spr.get_xy() - # Add a slight offset for copy/paste - if not save_project: - _sx += 20 - _sy += 20 - _data.append((_blk.id, _name, _sx-self.canvas.cx, - _sy-self.canvas.cy, connections)) - if save_turtle: - for _turtle in iter(self.turtles.dict): - self.canvas.set_turtle(_turtle) - _data.append((-1, ['turtle', _turtle], - self.canvas.xcor, self.canvas.ycor, - self.canvas.heading, - self.canvas.color, self.canvas.shade, - self.canvas.pensize)) - return _data - - def display_coordinates(self): - """ Display the coordinates of the current turtle on the toolbar """ - x = round_int(self.canvas.xcor/self.coord_scale) - y = round_int(self.canvas.ycor/self.coord_scale) - h = round_int(self.canvas.heading) - if self.running_sugar: - self.activity.coordinates_label.set_text("%s: %d %s: %d %s: %d" % ( - _("xcor"), x, _("ycor"), y, _("heading"), h)) - self.activity.coordinates_label.show() - elif self.interactive_mode: - self.win.set_title("%s — %s: %d %s: %d %s: %d" % (_("Turtle Art"), - _("xcor"), x, _("ycor"), y, _("heading"), h)) - - def showlabel(self, shp, label = ''): - """ Display a message on a status block """ - if not self.interactive_mode: - print label - return - if shp == 'syntaxerror' and str(label) != '': - if self.status_shapes.has_key(str(label)[1:]): - shp = str(label)[1:] - label = '' - else: - shp = 'status' - elif shp[0] == '#': - shp = shp[1:] - label = '' - if shp == 'notanumber': - shp = 'overflowerror' - self.status_spr.set_shape(self.status_shapes[shp]) - 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)) - else: - self.status_spr.move((PALETTE_WIDTH, self.height-200)) - - def calc_position(self, template): - """ Relative placement of portfolio objects (depreciated) """ - w, h, x, y, dx, dy = TEMPLATES[template] - x *= self.canvas.width - y *= self.canvas.height - w *= (self.canvas.width-x) - h *= (self.canvas.height-y) - dx *= w - dy *= h - return(w, h, x, y, dx, dy) - - def save_for_upload(self, _file_name): - """ Grab the current canvas and save it for upload """ - if _file_name[-3:] == '.ta': - _file_name = _file_name[0:-3] - data_to_file(self.assemble_data_to_save(), _file_name + '.ta') - save_picture(self.canvas, _file_name + '.png') - ta_file = _file_name + '.ta' - image_file = _file_name + '.png' - return ta_file, image_file - - def save_as_image(self, name="", svg=False, pixbuf=None): - """ Grab the current canvas and save it. """ - - if not self.interactive_mode: - # print name - save_picture(self.canvas, name[:-3] + ".png") - return - """ - self.color_map = self.window.get_colormap() - new_pix = pixbuf.get_from_drawable(self.window, self.color_map, - 0, 0, 0, 0, - self.width, self.height) - new_pix.save(name[:-3] + ".png", "png") - """ - - if self.running_sugar: - if svg: - if len(name) == 0: - filename = "ta.svg" - else: - filename = name+".svg" - else: - if len(name) == 0: - filename = "ta.png" - else: - filename = name+".png" - datapath = get_path(self.activity, 'instance') - elif len(name) == 0: - name = "ta" - if self.save_folder is not None: - self.load_save_folder = self.save_folder - if svg: - filename, self.load_save_folder = get_save_name('.svg', - self.load_save_folder, - name) - else: - filename, self.load_save_folder = get_save_name('.png', - self.load_save_folder, - name) - datapath = self.load_save_folder - else: - datapath = os.getcwd() - if svg: - filename = name+".svg" - else: - filename = name+".png" - if filename is None: - return - - file_path = os.path.join(datapath, filename) - if svg: - if self.svg_string == '': - return - save_svg(self.svg_string, file_path) - self.svg_string = '' - else: - save_picture(self.canvas, file_path) - - # keep a log of the saved pictures for export to HTML - self.saved_pictures.append(file_path) - - if self.running_sugar: - dsobject = datastore.create() - if len(name) == 0: - dsobject.metadata['title'] = "%s %s" % ( - self.activity.metadata['title'], _("image")) - else: - dsobject.metadata['title'] = name - dsobject.metadata['icon-color'] = profile.get_color().to_string() - if svg: - dsobject.metadata['mime_type'] = 'image/svg+xml' - else: - dsobject.metadata['mime_type'] = 'image/png' - dsobject.set_file_path(file_path) - datastore.write(dsobject) - dsobject.destroy() - - def just_blocks(self): - """ Filter out 'proto', 'trash', and 'deleted' blocks """ - just_blocks_list = [] - for _blk in self.block_list.list: - if _blk.type == 'block': - just_blocks_list.append(_blk) - return just_blocks_list - - def _width_and_height(self, blk): - """ What are the width and height of a stack? """ - minx = 10000 - miny = 10000 - maxx = -10000 - maxy = -10000 - for gblk in find_group(blk): - (x, y) = gblk.spr.get_xy() - w, h = gblk.spr.get_dimensions() - if x < minx: - minx = x - if y < miny: - miny = y - if x + w > maxx: - maxx = x + w - if y + h > maxy: - maxy = y + h - return(maxx - minx, maxy - miny) - - # Utilities related to putting a image 'skin' on a block - - def _calc_image_offset(self, name, spr, iw=0, ih=0): - """ Calculate the postion for placing an image onto a sprite. """ - _l, _t = spr.label_left_top() - if name == '': - return _l, _t - _w = spr.label_safe_width() - _h = spr.label_safe_height() - if iw == 0: - iw = self.media_shapes[name].get_width() - ih = self.media_shapes[name].get_height() - return int(_l + (_w - iw)/2), int(_t + (_h - ih)/2) - - def _calc_w_h(self, name, spr): - """ Calculate new image size """ - target_w = spr.label_safe_width() - target_h = spr.label_safe_height() - if name == '': - return target_w, target_h - image_w = self.media_shapes[name].get_width() - image_h = self.media_shapes[name].get_height() - scale_factor = float(target_w)/image_w - new_w = target_w - new_h = image_h*scale_factor - if new_h > target_h: - scale_factor = float(target_h)/new_h - new_h = target_h - new_w = target_w*scale_factor - return int(new_w), int(new_h) - - def _proto_skin(self, name, n, i): - """ Utility for calculating proto skin images """ - x, y = self._calc_image_offset(name, self.palettes[n][i].spr) - self.palettes[n][i].spr.set_image(self.media_shapes[name], 1, x, y) - - def _block_skin(self, name, blk): - """ Some blocks get a skin """ - x, y = self._calc_image_offset(name, blk.spr) - blk.set_image(self.media_shapes[name], x, y) - self._resize_skin(blk) - - def _resize_skin(self, blk): - """ Resize the 'skin' when block scale changes. """ - if blk.name in PYTHON_SKIN: - w, h = self._calc_w_h('pythonoff', blk.spr) - x, y = self._calc_image_offset('pythonoff', blk.spr, w, h) - elif blk.name == 'journal': - if len(blk.values) == 1 and blk.values[0] is not None: - w, h = self._calc_w_h('', blk.spr) - x, y = self._calc_image_offset('journaloff', blk.spr, w, h) - else: - w, h = self._calc_w_h('journaloff', blk.spr) - x, y = self._calc_image_offset('journaloff', blk.spr, w, h) - else: - w, h = self._calc_w_h('descriptionoff', blk.spr) - x, y = self._calc_image_offset('descriptionoff', blk.spr, w, h) - blk.scale_image(x, y, w, h) -- cgit v0.9.1