Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/TurtleArt/tawindow.py
diff options
context:
space:
mode:
Diffstat (limited to 'TurtleArt/tawindow.py')
-rw-r--r--TurtleArt/tawindow.py276
1 files changed, 190 insertions, 86 deletions
diff --git a/TurtleArt/tawindow.py b/TurtleArt/tawindow.py
index e20a1cf..5072ab2 100644
--- a/TurtleArt/tawindow.py
+++ b/TurtleArt/tawindow.py
@@ -102,10 +102,12 @@ class TurtleArtWindow():
def __init__(self, canvas_window, path, parent=None, activity=None,
mycolors=None, mynick=None, turtle_canvas=None,
running_sugar=True, running_turtleart=True):
- '''parent -- the GTK Window that TA runs in
- activity -- the object that instantiated this TurtleArtWindow (in
- GNOME, a TurtleMain instance)
- running_turtleart -- are we running TA or exported python code?
+ '''
+ parent: the GTK Window that TA runs in
+ activity: the object that instantiated this TurtleArtWindow (in
+ GNOME, a TurtleMain instance, in Sugar, the Activity
+ instance)
+ running_turtleart: are we running TA or exported python code?
'''
self.parent = parent
self.turtle_canvas = turtle_canvas
@@ -380,6 +382,7 @@ class TurtleArtWindow():
except Exception as e:
debug_output('Failed to load %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. '''
@@ -402,38 +405,73 @@ class TurtleArtWindow():
def _setup_plugins(self):
''' Initial setup -- called just once. '''
for plugin in self.turtleart_plugins:
- plugin.setup()
+ try:
+ plugin.setup()
+ except Exception as e:
+ debug_output('Plugin %s failed during setup: %s' %
+ (plugin, str(e)), self.running_sugar)
+ # If setup fails, remove the plugin from the list
+ self.turtleart_plugins.remove(plugin)
def _start_plugins(self):
''' Start is called everytime we execute blocks. '''
for plugin in self.turtleart_plugins:
- plugin.start()
+ if hasattr(plugin, 'start'):
+ try:
+ plugin.start()
+ except Exception as e:
+ debug_output('Plugin %s failed during start: %s' %
+ (plugin, str(e)), self.running_sugar)
def stop_plugins(self):
''' Stop is called whenever we stop execution. '''
for plugin in self.turtleart_plugins:
- plugin.stop()
+ if hasattr(plugin, 'stop'):
+ try:
+ plugin.stop()
+ except Exception as e:
+ debug_output('Plugin %s failed during stop: %s' %
+ (plugin, str(e)), self.running_sugar)
def clear_plugins(self):
''' Clear is called from the clean block and erase button. '''
for plugin in self.turtleart_plugins:
if hasattr(plugin, 'clear'):
- plugin.clear()
+ try:
+ plugin.clear()
+ except Exception as e:
+ debug_output('Plugin %s failed during clear: %s' %
+ (plugin, str(e)), self.running_sugar)
def background_plugins(self):
''' Background is called when we are pushed to the background. '''
for plugin in self.turtleart_plugins:
- plugin.goto_background()
+ if hasattr(plugin, 'goto_background'):
+ try:
+ plugin.goto_background()
+ except Exception as e:
+ debug_output('Plugin %s failed during background: %s' %
+ (plugin, str(e)), self.running_sugar)
def foreground_plugins(self):
''' Foreground is called when we are return from the background. '''
for plugin in self.turtleart_plugins:
- plugin.return_to_foreground()
+ if hasattr(plugin, 'return_to_foreground'):
+ try:
+ plugin.return_to_foreground()
+ except Exception as e:
+ debug_output('Plugin %s failed during foreground: %s' %
+ (plugin, str(e)), self.running_sugar)
def quit_plugins(self):
''' Quit is called upon program exit. '''
for plugin in self.turtleart_plugins:
- plugin.quit()
+ if hasattr(plugin, 'quit'):
+ try:
+ plugin.quit()
+ except Exception as e:
+ debug_output('Plugin %s failed during quit: %s' %
+ (plugin, str(e)), self.running_sugar)
def _setup_events(self):
''' Register the events we listen to. '''
@@ -460,14 +498,15 @@ class TurtleArtWindow():
if not self.activity._unfullscreen_button.props.visible:
self.activity._unfullscreen_button.show()
# Reset the timer
- if self.activity._unfullscreen_button_timeout_id is not None:
- gobject.source_remove(
- self.activity._unfullscreen_button_timeout_id)
- self.activity._unfullscreen_button_timeout_id = None
+ if hasattr(self.activity, '_unfullscreen_button_timeout_id'):
+ if self.activity._unfullscreen_button_timeout_id is not None:
+ gobject.source_remove(
+ self.activity._unfullscreen_button_timeout_id)
+ self.activity._unfullscreen_button_timeout_id = None
- self.activity._unfullscreen_button_timeout_id = \
- gobject.timeout_add_seconds(_UNFULLSCREEN_VISIBILITY_TIMEOUT,
- self.__unfullscreen_button_timeout_cb)
+ self.activity._unfullscreen_button_timeout_id = \
+ gobject.timeout_add_seconds(_UNFULLSCREEN_VISIBILITY_TIMEOUT,
+ self.__unfullscreen_button_timeout_cb)
def __unfullscreen_button_timeout_cb(self):
self.activity._unfullscreen_button.hide()
@@ -529,6 +568,8 @@ class TurtleArtWindow():
self._autohide_shape = True
for name in OVERLAY_SHAPES:
+ if name == 'Cartesian':
+ continue
self.overlay_shapes[name] = Sprite(
self.sprite_list,
int(self.width / 2 - 600),
@@ -538,6 +579,8 @@ class TurtleArtWindow():
self.overlay_shapes[name].hide()
self.overlay_shapes[name].type = 'overlay'
+ self._create_scaled_cartesian_coordinates()
+
if self.running_turtleart and not self.running_sugar:
# offset = 2 * self.width - 55 * len(TOOLBAR_SHAPES)
offset = 55 * (1 + len(palette_blocks))
@@ -553,6 +596,27 @@ class TurtleArtWindow():
self.toolbar_shapes[name].type = 'toolbar'
self.toolbar_shapes['stopiton'].hide()
+ def _create_scaled_cartesian_coordinates(self):
+ # Cartesian overlay has to be scaled to match the coordinate_scale
+ # 200 pixels in the graphic == height / 4. (10 units)
+ pixbuf = svg_str_to_pixbuf(
+ svg_from_file('%s/images/%s.svg' % (self.path, 'Cartesian')))
+
+ if self.running_sugar:
+ scale = self.height / 800.
+ else:
+ scale = self.height / 800.
+ # scale = (self.height + ICON_SIZE) / 800.
+ self.overlay_shapes['Cartesian'] = Sprite(
+ self.sprite_list,
+ int(self.width / 2 - 600),
+ int(self.height / 2 - 450),
+ pixbuf.scale_simple(int(1200 * scale),
+ int(900 * scale),
+ gtk.gdk.INTERP_BILINEAR))
+ self.overlay_shapes['Cartesian'].set_layer(TAB_LAYER)
+ self.overlay_shapes['Cartesian'].hide()
+
def set_sharing(self, shared):
self._sharing = shared
@@ -587,7 +651,8 @@ class TurtleArtWindow():
if event is None:
return
- self.activity.check_buttons_for_fit()
+ if self.running_sugar:
+ self.activity.check_buttons_for_fit()
# If there are any constant blocks on the canvas, relabel them
for blk in self.just_blocks():
@@ -714,7 +779,8 @@ class TurtleArtWindow():
if self.running_sugar:
y_offset = 0
else:
- y_offset = ICON_SIZE
+ y_offset = 0
+ # y_offset = ICON_SIZE
self.canvas.draw_surface(
self.overlay_shapes[overlay].cached_surfaces[0],
(self.canvas.width - width) / 2.0,
@@ -722,10 +788,13 @@ class TurtleArtWindow():
width,
height)
- def update_overlay_position(self, widget, event):
+ def update_overlay_position(self, widget=None, event=None):
''' Reposition the overlays when window size changes '''
- self.width = event.width
- self.height = event.height
+ # self.width = event.width
+ # self.height = event.height
+ self.width = gtk.gdk.screen_width()
+ self.height = gtk.gdk.screen_height()
+
for name in OVERLAY_SHAPES:
if not name in self.overlay_shapes:
continue
@@ -734,17 +803,24 @@ class TurtleArtWindow():
if shape in shape._sprites.list:
shape.hide()
showing = True
+ self.overlay_shapes[name].move((int(self.width / 2 - 600),
+ int(self.height / 2 - 450)))
+ '''
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.metric = False
@@ -802,6 +878,7 @@ class TurtleArtWindow():
if not self.running_sugar or not self.activity.has_toolbarbox:
self.toolbar_spr.set_layer(CATEGORY_LAYER)
self.palette = True
+ self._set_coordinates_label(palette_names[n])
def hide_palette(self):
''' Hide the palette. '''
@@ -963,7 +1040,8 @@ class TurtleArtWindow():
self.running_sugar)
else:
blk.spr.hide()
- if 'trash' in palette_names and n == palette_names.index('trash'):
+ if 'trash' in palette_names and \
+ n == palette_names.index('trash'):
for blk in self.trash_stack:
# Deprecated
for gblk in find_group(blk):
@@ -1403,6 +1481,8 @@ class TurtleArtWindow():
if self.running_sugar:
self._show_unfullscreen_button()
+ self.activity.hide_store()
+
# Find out what was clicked
spr = self.sprite_list.find_sprite((x, y))
@@ -1410,9 +1490,16 @@ class TurtleArtWindow():
if spr is not None:
blk = self.block_list.spr_to_block(spr)
if blk is not None:
+ # Make sure stop button is visible
+ if self.running_sugar:
+ self.activity.stop_turtle_button.set_icon("stopiton")
+ self.activity.stop_turtle_button.set_tooltip(
+ _('Stop turtle'))
+ elif self.interactive_mode:
+ self.toolbar_shapes['stopiton'].set_layer(TAB_LAYER)
self.showlabel('status',
label=_('Please hit the Stop Button \
-before making changes to your Turtle Blocks program'))
+before making changes to your program'))
self._autohide_shape = True
return True
@@ -1499,9 +1586,9 @@ before making changes to your Turtle Blocks program'))
self._restore_from_trash(find_top_block(blk))
elif blk.type == 'proto':
if self.deleting_blocks:
- if 'myblocks' in palette_names and \
+ if 'my blocks' in palette_names and \
self.selected_palette == \
- palette_names.index('myblocks'):
+ palette_names.index('my blocks'):
self._delete_stack_alert(blk)
self.parent.get_window().set_cursor(
gtk.gdk.Cursor(gtk.gdk.LEFT_PTR))
@@ -1511,7 +1598,10 @@ before making changes to your Turtle Blocks program'))
elif blk.name == 'restore':
self.restore_latest_from_trash()
elif blk.name == 'empty':
- self._empty_trash()
+ if self.running_sugar:
+ self.activity.empty_trash_alert()
+ else:
+ self.empty_trash()
elif blk.name == 'trashall':
for b in self.just_blocks():
if b.type != 'trash':
@@ -1523,8 +1613,9 @@ before making changes to your Turtle Blocks program'))
self._put_in_trash(b1)
else:
self._put_in_trash(find_top_block(b))
- self.show_toolbar_palette(palette_names.index('trash'),
- regenerate=True)
+ if 'trash' in palette_names:
+ self.show_toolbar_palette(
+ palette_names.index('trash'), regenerate=True)
elif blk.name in MACROS:
self.new_macro(blk.name, x + 20, y + 20)
else:
@@ -1545,13 +1636,13 @@ before making changes to your Turtle Blocks program'))
found_the_action_block = False
bname = _('action')
if isinstance(bname, unicode):
- bname = bname.encode('ascii', 'replace')
+ bname = bname.encode('utf-8')
for sblk in similars:
cblk = sblk.connections[1]
if cblk is not None:
blabel = cblk.spr.labels[0]
if isinstance(blabel, unicode):
- blabel = blabel.encode('ascii', 'replace')
+ blabel = blabel.encode('utf-8')
if bname == blabel:
found_the_action_block = True
# If there is an action block in use, change the name
@@ -1706,7 +1797,7 @@ before making changes to your Turtle Blocks program'))
error_output('Could not remove macro %s: %s' %
(macro_path, e))
return
- i = palette_names.index('myblocks')
+ i = palette_names.index('my blocks')
palette_blocks[i].remove(blk.name)
for pblk in self.palettes[i]:
if pblk.name == blk.name:
@@ -1779,7 +1870,7 @@ before making changes to your Turtle Blocks program'))
if isinstance(name, (float, int)):
return
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
for blk in self.just_blocks():
if self._action_name(blk, hat=False):
if blk.spr.labels[0] == self._saved_action_name:
@@ -1797,7 +1888,7 @@ before making changes to your Turtle Blocks program'))
if isinstance(name, (float, int)):
return
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
for blk in self.just_blocks():
if self._box_name(blk, storein=False):
if blk.spr.labels[0] == self._saved_box_name:
@@ -1815,7 +1906,7 @@ before making changes to your Turtle Blocks program'))
if isinstance(name, (float, int)):
return
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
for blk in self.just_blocks():
if self._box_name(blk, storein=True):
if blk.spr.labels[0] == self._saved_box_name:
@@ -1838,11 +1929,11 @@ before making changes to your Turtle Blocks program'))
# (3) The list of proto blocks on the palette
# (4) The list of block names
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
if isinstance(old, unicode):
- old = old.encode('ascii', 'replace')
+ old = old.encode('utf-8')
if isinstance(new, unicode):
- new = new.encode('ascii', 'replace')
+ new = new.encode('utf-8')
if old == new:
'''
@@ -2064,15 +2155,16 @@ before making changes to your Turtle Blocks program'))
self.trash_stack.remove(blk)
- def _empty_trash(self):
+ 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 = []
- self.show_toolbar_palette(palette_names.index('trash'),
- regenerate=True)
+ if 'trash' in palette_names:
+ self.show_toolbar_palette(palette_names.index('trash'),
+ regenerate=True)
def _in_the_trash(self, x, y):
''' Is x, y over a palette? '''
@@ -2511,10 +2603,12 @@ before making changes to your Turtle Blocks program'))
pos = self.turtles.screen_to_turtle_coordinates((dx, dy))
if self.selected_turtle.get_pen_state():
self.selected_turtle.set_pen_state(False)
- self.selected_turtle.set_xy(pos, share=False)
+ self.selected_turtle.set_xy(*pos, share=False,
+ dragging=True)
self.selected_turtle.set_pen_state(True)
else:
- self.selected_turtle.set_xy(pos, share=False)
+ self.selected_turtle.set_xy(*pos, share=False,
+ dragging=True)
if self.update_counter % 5:
self.lc.update_label_value(
'xcor', self.selected_turtle.get_xy()[0] /
@@ -2777,13 +2871,10 @@ before making changes to your Turtle Blocks program'))
0,
'label',
[],
- 2.0 / self.scale,
+ 1.5 / self.scale,
colors)
- turtle.label_block.spr.set_label_attributes(12.0 / self.scale)
- if len(name) > 6:
- turtle.label_block.spr.set_label(name[0:4] + '…')
- else:
- turtle.label_block.spr.set_label(name)
+ turtle.label_block.spr.set_label_attributes(10.0 / self.scale)
+ turtle.label_block.spr.set_label(name)
turtle.set_remote()
turtle.show()
@@ -3809,7 +3900,6 @@ before making changes to your Turtle Blocks program'))
(self._loaded_project), self.running_sugar)
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):
@@ -3854,7 +3944,8 @@ before making changes to your Turtle Blocks program'))
''' Restore a turtle from its saved state '''
tid, name, xcor, ycor, heading, color, shade, pensize = blk
self.turtles.set_turtle(key)
- self.turtles.get_active_turtle().set_xy(xcor, ycor, pendown=False)
+ self.turtles.get_active_turtle().set_xy(xcor, ycor, share=True,
+ pendown=False)
self.turtles.get_active_turtle().set_heading(heading)
self.turtles.get_active_turtle().set_color(color)
self.turtles.get_active_turtle().set_shade(shade)
@@ -3914,34 +4005,42 @@ before making changes to your Turtle Blocks program'))
self._process_block_data[b[0]] = [
b[0], b[1], b[2], b[3], [b[4][0], i, b[4][1]]]
elif btype == 'hat':
+ name = None
if b[4][1] < len(self._process_block_data):
i = b[4][1]
- name = self._process_block_data[i][1][1]
+ if i is not None:
+ name = self._process_block_data[i][1][1]
else:
i = b[4][1] - len(self._process_block_data)
name = self._extra_block_data[i][1][1]
- while self._find_proto_name('stack_%s' % (name), name):
- name = increment_name(name)
- if b[4][1] < len(self._process_block_data):
- dblk = self._process_block_data[i]
- self._process_block_data[i] = [dblk[0], (dblk[1][0], name),
- dblk[2], dblk[3], dblk[4]]
- else:
- dblk = self._extra_block_data[i]
- self._extra_block_data[i] = [dblk[0], (dblk[1][0], name),
- dblk[2], dblk[3], dblk[4]]
- self._new_stack_block(name)
+ if name is not None:
+ while self._find_proto_name('stack_%s' % (name), name):
+ name = increment_name(name)
+ if b[4][1] < len(self._process_block_data):
+ dblk = self._process_block_data[i]
+ self._process_block_data[i] = [
+ dblk[0], (dblk[1][0], name), dblk[2], dblk[3],
+ dblk[4]]
+ else:
+ dblk = self._extra_block_data[i]
+ self._extra_block_data[i] = [
+ dblk[0], (dblk[1][0], name), dblk[2], dblk[3],
+ dblk[4]]
+ self._new_stack_block(name)
elif btype == 'storein':
+ name = None
if b[4][1] < len(self._process_block_data):
i = b[4][1]
- name = self._process_block_data[i][1][1]
+ if i is not None:
+ name = self._process_block_data[i][1][1]
else:
i = b[4][1] - len(self._process_block_data)
name = self._extra_block_data[i][1][1]
- if not self._find_proto_name('storein_%s' % (name), name):
- self._new_storein_block(name)
- if not self._find_proto_name('box_%s' % (name), name):
- self._new_box_block(name)
+ if name is not None:
+ if not self._find_proto_name('storein_%s' % (name), name):
+ self._new_storein_block(name)
+ if not self._find_proto_name('box_%s' % (name), name):
+ self._new_box_block(name)
if btype in content_blocks:
if btype == 'number':
@@ -4011,7 +4110,7 @@ before making changes to your Turtle Blocks program'))
if btype == 'string' and blk.spr is not None:
value = blk.values[0]
if isinstance(value, unicode):
- value = value.encode('ascii', 'replace')
+ value = value.encode('utf-8')
blk.spr.set_label(value.replace('\n', RETURN))
elif btype == 'start': # block size is saved in start block
if value is not None:
@@ -4133,6 +4232,7 @@ before making changes to your Turtle Blocks program'))
[None, None]]])
else:
self.process_data(data_from_file(ta_file))
+ self._loaded_project = ta_file
def save_file(self, file_name=None):
''' Start a project to a file '''
@@ -4219,11 +4319,7 @@ before making changes to your Turtle Blocks program'))
def display_coordinates(self, clear=False):
''' Display the coordinates of the current turtle on the toolbar '''
if clear:
- if self.running_sugar:
- self.activity.coordinates_label.set_text('')
- self.activity.coordinates_label.show()
- elif self.interactive_mode:
- self.parent.set_title('')
+ self._set_coordinates_label('')
else:
x = round_int(float(self.turtles.get_active_turtle().get_xy()[0]) /
self.coord_scale)
@@ -4235,19 +4331,25 @@ before making changes to your Turtle Blocks program'))
formatting = '(%d, %d) %d'
else:
formatting = '(%0.2f, %0.2f) %0.2f'
- self.activity.coordinates_label.set_text(
- formatting % (x, y, h))
- self.activity.coordinates_label.show()
+ self._set_coordinates_label(formatting % (x, y, h))
elif self.interactive_mode:
if int(x) == x and int(y) == y and int(h) == h:
formatting = '%s — %s: %d %s: %d %s: %d'
else:
formatting = '%s — %s: %0.2f %s: %0.2f %s: %0.2f'
- self.parent.set_title(
+ self._set_coordinates_label(
formatting % (self.activity.name, _('xcor'), x,
_('ycor'), y, _('heading'), h))
self.update_counter = 0
+ def _set_coordinates_label(self, text):
+ if self.running_sugar:
+ self.activity.coordinates_label.set_text(text)
+ self.activity.coordinates_label.show()
+ elif self.interactive_mode:
+ self.parent.set_title(text)
+
+
def showlabel(self, shp, label=''):
''' Display a message on a status block '''
if not self.interactive_mode:
@@ -4272,6 +4374,8 @@ before making changes to your Turtle Blocks program'))
self.status_spr.set_shape(self.status_shapes[shp])
self.status_spr.set_label_attributes(12.0, rescale=False)
if shp == 'status':
+ if label in ['True', 'False']:
+ label = _(label)
self.status_spr.set_label('"%s"' % (str(label)))
else:
self.status_spr.set_label(str(label))
@@ -4483,16 +4587,16 @@ before making changes to your Turtle Blocks program'))
if not self.interactive_mode:
return False
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
if isinstance(label, unicode):
- label = label.encode('ascii', 'replace')
+ label = label.encode('utf-8')
i = palette_name_to_index(palette)
for blk in self.palettes[i]:
blk_label = blk.spr.labels[0]
if isinstance(blk.name, unicode):
- blk.name = blk.name.encode('ascii', 'replace')
+ blk.name = blk.name.encode('utf-8')
if isinstance(blk_label, unicode):
- blk_label = blk_label.encode('ascii', 'replace')
+ blk_label = blk_label.encode('utf-8')
if blk.name == name and blk_label == label:
return True
# Check labels[1] too (e.g., store in block)
@@ -4509,7 +4613,7 @@ before making changes to your Turtle Blocks program'))
if isinstance(name, (float, int)):
return
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
if name == _('action'):
return
# Choose a palette for the new block.
@@ -4538,7 +4642,7 @@ before making changes to your Turtle Blocks program'))
if isinstance(name, (float, int)):
return
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
if name == _('my box'):
return
# Choose a palette for the new block.
@@ -4568,7 +4672,7 @@ before making changes to your Turtle Blocks program'))
if isinstance(name, (float, int)):
return
if isinstance(name, unicode):
- name = name.encode('ascii', 'replace')
+ name = name.encode('utf-8')
if name == _('my box'):
return
# Choose a palette for the new block.