Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/turtleart.py
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2012-05-06 22:39:06 (GMT)
committer Walter Bender <walter.bender@gmail.com>2012-05-06 22:39:06 (GMT)
commitd082a08b7d60fa3b75f46940d772e176a6bdc046 (patch)
treefdc00aa7c7729267765b1e02441f706e793581a6 /turtleart.py
parent7c72f2ce22cc25272a24acf27551cb02af073cc8 (diff)
calling it by its proper name
Diffstat (limited to 'turtleart.py')
-rwxr-xr-xturtleart.py638
1 files changed, 0 insertions, 638 deletions
diff --git a/turtleart.py b/turtleart.py
deleted file mode 100755
index 17bc0e7..0000000
--- a/turtleart.py
+++ /dev/null
@@ -1,638 +0,0 @@
-#!/usr/bin/env python
-#Copyright (c) 2007-8, Playful Invention Company
-#Copyright (c) 2008-12, Walter Bender
-#Copyright (c) 2011 Collabora Ltd. <http://www.collabora.co.uk/>
-
-#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 cairo
-
-import getopt
-import sys
-import os
-import os.path
-import cStringIO
-import errno
-import ConfigParser
-
-try:
- # Try to use XDG Base Directory standard for config files.
- import xdg.BaseDirectory
- CONFIG_HOME = os.path.join(xdg.BaseDirectory.xdg_config_home, 'turtleart')
-except ImportError, e:
- # Default to `.config` per the spec.
- CONFIG_HOME = os.path.expanduser(os.path.join('~', '.config', 'turtleart'))
-
-argv = sys.argv[:] # Workaround for import behavior of gst in tagplay
-sys.argv[1:] = [] # Execution of import gst cannot see '--help' or '-h'
-
-import gettext
-
-# Commenting out bindtextdomain so that GNOME can find the installed .mo files,
-# but it will not find the .mo files in the local locale directory when running
-# from a git repository or the unzipped .xo file.
-# gettext.bindtextdomain('org.laptop.TurtleArtActivity', 'locale')
-
-from TurtleArt.taconstants import OVERLAY_LAYER, DEFAULT_TURTLE_COLORS
-from TurtleArt.tautils import data_to_string, data_from_string, get_save_name
-from TurtleArt.tawindow import TurtleArtWindow
-from TurtleArt.taexporthtml import save_html
-from TurtleArt.taexportlogo import save_logo
-
-from util.menubuilder import MenuBuilder
-
-
-class TurtleMain():
- ''' Launch Turtle Art in GNOME (from outside of Sugar). '''
- _INSTALL_PATH = '/usr/share/sugar/activities/TurtleArt.activity'
- _ALTERNATIVE_INSTALL_PATH = \
- '/usr/local/share/sugar/activities/TurtleArt.activity'
- _ICON_SUBPATH = 'images/turtle.png'
- _GNOME_PLUGIN_SUBPATH = 'gnome_plugins'
-
- def __init__(self):
- self._abspath = os.path.abspath('.')
- self._execdirname = self._get_execution_dir()
- if self._execdirname is not None:
- os.chdir(self._execdirname)
- file_activity_info = ConfigParser.ConfigParser()
- activity_info_path = os.path.abspath('./activity/activity.info')
- file_activity_info.read(activity_info_path)
- bundle_id = file_activity_info.get('Activity', 'bundle_id')
- gettext.textdomain(bundle_id)
- global _
- _ = gettext.gettext
- _HELP_MSG = 'turtleart.py: ' + _('usage is') + '''
- \tturtleart.py
- \tturtleart.py project.ta
- \tturtleart.py --output_png project.ta
- \tturtleart.py -o project
- \tturtleart.py --run project.ta
- \tturtleart.py -r project'''
- self._init_vars()
- self._parse_command_line()
- self._ensure_sugar_paths()
- self._plugins = []
-
- if self._output_png:
- # Outputing to file, so no need for a canvas
- self.canvas = None
- self._build_window(interactive=False)
- self._draw_and_quit()
- else:
- self._read_initial_pos()
- self._init_plugins()
- self._setup_gtk()
- self._build_window()
- self._run_plugins()
- self._start_gtk()
-
- def get_config_home(self):
- return CONFIG_HOME
-
- def _get_gnome_plugin_home(self):
- ''' Use plugin directory associated with execution path. '''
- if os.path.exists(os.path.join(self._execdirname,
- self._GNOME_PLUGIN_SUBPATH)):
- return os.path.join(self._execdirname, self._GNOME_PLUGIN_SUBPATH)
- else:
- return None
-
- def _get_plugin_candidates(self, path):
- ''' Look for plugin files in plugin directory. '''
- plugin_files = []
- if path is not None:
- candidates = os.listdir(path)
- for c in candidates:
- if c[-10:] == '_plugin.py' and c[0] != '#' and c[0] != '.':
- plugin_files.append(c.split('.')[0])
- return plugin_files
-
- def _init_plugins(self):
- ''' Try launching any plugins we may have found. '''
- for p in self._get_plugin_candidates(self._get_gnome_plugin_home()):
- P = p.capitalize()
- f = \
- "def f(self): from gnome_plugins.%s import %s; return %s(self)" % (p, P, P)
- plugin = {}
- try:
- exec f in globals(), plugin
- self._plugins.append(plugin.values()[0](self))
- except ImportError, e:
- print 'failed to import %s: %s' % (P, str(e))
-
- def _run_plugins(self):
- ''' Tell the plugin about the TurtleWindow instance. '''
- for p in self._plugins:
- p.set_tw(self.tw)
-
- def _mkdir_p(self, path):
- '''Create a directory in a fashion similar to `mkdir -p`.'''
- try:
- os.makedirs(path)
- except OSError, exc:
- if exc.errno == errno.EEXIST:
- pass
- else:
- raise
-
- def _makepath(self, path):
- ''' Make a path if it doesn't previously exist '''
- from os import makedirs
- from os.path import normpath, dirname, exists
-
- dpath = normpath(dirname(path))
- if not exists(dpath):
- makedirs(dpath)
-
- def _start_gtk(self):
- ''' Get a main window set up. '''
- self.win.connect('configure_event', self.tw.update_overlay_position)
- self.tw.parent = self.win
- if self._ta_file is None:
- self.tw.load_start()
- else:
- print self._ta_file
- self.tw.load_start(self._ta_file)
- self.tw.lc.trace = 0
- if self._run_on_launch:
- self._do_run_cb()
- gtk.main()
-
- def _draw_and_quit(self):
- ''' Non-interactive mode: run the project, save it to a file
- and quit. '''
- self.tw.load_start(self._ta_file)
- self.tw.lc.trace = 0
- self.tw.run_button(0)
- self.tw.save_as_image(self._ta_file)
-
- def _build_window(self, interactive=True):
- ''' Initialize the TurtleWindow instance. '''
- if interactive:
- win = self.canvas.get_window()
- cr = win.cairo_create()
- surface = cr.get_target()
- else:
- img_surface = cairo.ImageSurface(cairo.FORMAT_RGB24,
- 1024, 768)
- cr = cairo.Context(img_surface)
- surface = cr.get_target()
- self.turtle_canvas = surface.create_similar(
- cairo.CONTENT_COLOR, max(1024, gtk.gdk.screen_width() * 2),
- max(768, gtk.gdk.screen_height() * 2))
- self.tw = TurtleArtWindow(self.canvas, self._execdirname,
- turtle_canvas=self.turtle_canvas)
- self.tw.save_folder = os.path.expanduser('~')
-
- def _init_vars(self):
- ''' If we are invoked to start a project from Gnome, we should make
- sure our current directory is TA's source dir. '''
- self._ta_file = None
- self._output_png = False
- self._run_on_launch = False
- self.current_palette = 0
- self.scale = 2.0
- self.tw = None
-
- def _parse_command_line(self):
- ''' Try to make sense of the command-line arguments. '''
- try:
- opts, args = getopt.getopt(argv[1:], 'hor',
- ['help', 'output_png', 'run'])
- except getopt.GetoptError, err:
- print str(err)
- print self._HELP_MSG
- sys.exit(2)
- for o, a in opts:
- if o in ('-h', '--help'):
- print self._HELP_MSG
- sys.exit()
- if o in ('-o', '--output_png'):
- self._output_png = True
- elif o in ('-r', '--run'):
- self._run_on_launch = True
- else:
- assert False, _('No option action:') + ' ' + o
- if args:
- self._ta_file = args[0]
-
- if len(args) > 1 or self._output_png and self._ta_file is None:
- print self._HELP_MSG
- sys.exit()
-
- if self._ta_file is not None:
- if not self._ta_file.endswith(('.ta')):
- self._ta_file += '.ta'
- if not os.path.exists(self._ta_file):
- self._ta_file = os.path.join(self._abspath, self._ta_file)
- if not os.path.exists(self._ta_file):
- assert False, ('%s: %s' % (self._ta_file,
- _('File not found')))
-
- def _ensure_sugar_paths(self):
- ''' Make sure Sugar paths are present. '''
- tapath = os.path.join(os.environ['HOME'], '.sugar', 'default',
- 'org.laptop.TurtleArtActivity')
- map(self._makepath, (os.path.join(tapath, 'data/'),
- os.path.join(tapath, 'instance/')))
-
- def _read_initial_pos(self):
- ''' Read saved configuration. '''
- try:
- data_file = open(os.path.join(CONFIG_HOME, 'turtleartrc'), 'r')
- except IOError:
- # Opening the config file failed
- # We'll assume it needs to be created
- try:
- self._mkdir_p(CONFIG_HOME)
- data_file = open(os.path.join(CONFIG_HOME, 'turtleartrc'),
- 'a+')
- except IOError, e:
- # We can't write to the configuration file, use
- # a faux file that will persist for the length of
- # the session.
- print _('Configuration directory not writable: %s') % (e)
- data_file = cStringIO.StringIO()
- data_file.write(str(50) + '\n')
- data_file.write(str(50) + '\n')
- data_file.write(str(800) + '\n')
- data_file.write(str(550) + '\n')
- data_file.seek(0)
- try:
- self.x = int(data_file.readline())
- self.y = int(data_file.readline())
- self.width = int(data_file.readline())
- self.height = int(data_file.readline())
- except ValueError:
- self.x = 50
- self.y = 50
- self.width = 800
- self.height = 550
-
- def _setup_gtk(self):
- ''' Set up a scrolled window in which to run Turtle Blocks. '''
- win = gtk.Window(gtk.WINDOW_TOPLEVEL)
- win.set_default_size(self.width, self.height)
- win.move(self.x, self.y)
- win.maximize()
- win.set_title(_('Turtle Art'))
- if os.path.exists(os.path.join(self._execdirname, self._ICON_SUBPATH)):
- win.set_icon_from_file(os.path.join(self._execdirname,
- self._ICON_SUBPATH))
- win.connect('delete_event', self._quit_ta)
-
- vbox = gtk.VBox(False, 0)
- win.add(vbox)
- vbox.show()
-
- menu_bar = self._get_menu_bar()
- vbox.pack_start(menu_bar, False, False, 2)
- menu_bar.show()
-
- sw = gtk.ScrolledWindow()
- sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
- sw.show()
- canvas = gtk.DrawingArea()
- width = gtk.gdk.screen_width() * 2
- height = gtk.gdk.screen_height() * 2
- canvas.set_size_request(width, height)
- sw.add_with_viewport(canvas)
- canvas.show()
- vbox.pack_end(sw, True, True)
-
- win.show_all()
- self.win = win
- self.canvas = canvas
-
- def _get_menu_bar(self):
- ''' Instead of Sugar toolbars, use GNOME menus. '''
- menu = gtk.Menu()
- MenuBuilder.make_menu_item(menu, _('New'), self._do_new_cb)
- MenuBuilder.make_menu_item(menu, _('Open'), self._do_open_cb)
- MenuBuilder.make_menu_item(menu, _('Save'), self._do_save_cb)
- MenuBuilder.make_menu_item(menu, _('Save as'), self._do_save_as_cb)
- MenuBuilder.make_menu_item(menu, _('Save as image'),
- self._do_save_picture_cb)
- MenuBuilder.make_menu_item(menu, _('Save as HTML'),
- self._do_save_html_cb)
- MenuBuilder.make_menu_item(menu, _('Save as Logo'),
- self._do_save_logo_cb)
- MenuBuilder.make_menu_item(menu, _('Quit'), self._quit_ta)
- activity_menu = MenuBuilder.make_sub_menu(menu, _('File'))
-
- menu = gtk.Menu()
- MenuBuilder.make_menu_item(menu, _('Cartesian coordinates'),
- self._do_cartesian_cb)
- MenuBuilder.make_menu_item(menu, _('Polar coordinates'),
- self._do_polar_cb)
- MenuBuilder.make_menu_item(menu, _('Rescale coordinates'),
- self._do_rescale_cb)
- MenuBuilder.make_menu_item(menu, _('Grow blocks'),
- self._do_resize_cb, 1.5)
- MenuBuilder.make_menu_item(menu, _('Shrink blocks'),
- self._do_resize_cb, 0.667)
- MenuBuilder.make_menu_item(menu, _('Reset block size'),
- self._do_resize_cb, -1)
- MenuBuilder.make_menu_item(menu, _('Turn off hover help'),
- self._do_hover_help_off_cb)
- MenuBuilder.make_menu_item(menu, _('Turn on hover help'),
- self._do_hover_help_on_cb)
- view_menu = MenuBuilder.make_sub_menu(menu, _('View'))
-
- menu = gtk.Menu()
- MenuBuilder.make_menu_item(menu, _('Copy'), self._do_copy_cb)
- MenuBuilder.make_menu_item(menu, _('Paste'), self._do_paste_cb)
- edit_menu = MenuBuilder.make_sub_menu(menu, _('Edit'))
-
- menu = gtk.Menu()
- MenuBuilder.make_menu_item(menu, _('Show palette'),
- self._do_palette_cb)
- MenuBuilder.make_menu_item(menu, _('Hide palette'),
- self._do_hide_palette_cb)
- MenuBuilder.make_menu_item(menu, _('Show/hide blocks'),
- self._do_hideshow_cb)
- tool_menu = MenuBuilder.make_sub_menu(menu, _('Tools'))
-
- menu = gtk.Menu()
- MenuBuilder.make_menu_item(menu, _('Clean'), self._do_eraser_cb)
- MenuBuilder.make_menu_item(menu, _('Run'), self._do_run_cb)
- MenuBuilder.make_menu_item(menu, _('Step'), self._do_step_cb)
- MenuBuilder.make_menu_item(menu, _('Debug'), self._do_trace_cb)
- MenuBuilder.make_menu_item(menu, _('Stop'), self._do_stop_cb)
- turtle_menu = MenuBuilder.make_sub_menu(menu, _('Turtle'))
-
- menu_bar = gtk.MenuBar()
- menu_bar.append(activity_menu)
- menu_bar.append(edit_menu)
- menu_bar.append(view_menu)
- menu_bar.append(tool_menu)
- menu_bar.append(turtle_menu)
-
- # Add menus for plugins
- for p in self._plugins:
- menu_bar.append(p.get_menu())
- return menu_bar
-
- def _quit_ta(self, widget=None, e=None):
- ''' Save changes on exit '''
- project_empty = self.tw.is_project_empty()
- if not project_empty:
- if self.tw.is_new_project():
- self._show_save_dialog(True)
- else:
- if self.tw.project_has_changed():
- self._show_save_dialog(False)
- for plugin in self.tw._plugins:
- if hasattr(plugin, 'quit'):
- plugin.quit()
- gtk.main_quit()
- exit()
-
- def _show_save_dialog(self, new_project=True):
- ''' Dialog for save project '''
- dlg = gtk.MessageDialog(parent=None, type=gtk.MESSAGE_INFO,
- buttons=gtk.BUTTONS_OK_CANCEL,
- message_format=_(
- 'You have unsaved work. Would you like to save before quitting?'))
- dlg.set_title(_('Save project?'))
- dlg.set_property('skip-taskbar-hint', False)
-
- resp = dlg.run()
- dlg.destroy()
- if resp == gtk.RESPONSE_OK:
- if new_project:
- self._save_as()
- else:
- self._save_changes()
-
- def _do_new_cb(self, widget):
- ''' Callback for new project. '''
- self.tw.new_project()
- self.tw.load_start()
-
- def _do_open_cb(self, widget):
- ''' Callback for open project. '''
- self.tw.load_file(True)
-
- def _do_save_cb(self, widget):
- ''' Callback for save project. '''
- self.tw.save_file()
-
- def _do_save_as_cb(self, widget):
- ''' Callback for save-as project. '''
- self._save_as()
-
- def _save_as(self):
- ''' Save as is called from callback and quit '''
- self.tw.save_file_name = None
- self.tw.save_file()
-
- def _save_changes(self):
- ''' Save changes to current project '''
- self.tw.save_file_name = None
- self.tw.save_file(self.tw._loaded_project)
-
- def _do_save_picture_cb(self, widget):
- ''' Callback for save canvas. '''
- self.tw.save_as_image()
-
- def _do_save_html_cb(self, widget):
- ''' Callback for save project to HTML. '''
- html = save_html(self, self.tw, False)
- if len(html) == 0:
- return
- save_type = '.html'
- if len(self.tw.saved_pictures) > 0:
- if self.tw.saved_pictures[0].endswith(('.svg')):
- save_type = '.xml'
- filename, self.tw.load_save_folder = get_save_name(save_type,
- self.tw.load_save_folder, 'portfolio')
- f = file(filename, 'w')
- f.write(html)
- f.close()
- self.tw.saved_pictures = []
-
- def _do_save_logo_cb(self, widget):
- ''' Callback for save project to Logo. '''
- logocode = save_logo(self.tw)
- if len(logocode) == 0:
- return
- save_type = '.lg'
- filename, self.tw.load_save_folder = get_save_name(save_type,
- self.tw.load_save_folder, 'logosession')
- f = file(filename, 'w')
- f.write(logocode)
- f.close()
-
- def _do_resize_cb(self, widget, factor):
- ''' Callback to resize blocks. '''
- if factor == -1:
- self.tw.block_scale = 2.0
- else:
- self.tw.block_scale *= factor
- self.tw.resize_blocks()
-
- def _do_cartesian_cb(self, button):
- ''' Callback to display/hide Cartesian coordinate overlay. '''
- self.tw.set_cartesian(True)
-
- def _do_polar_cb(self, button):
- ''' Callback to display/hide Polar coordinate overlay. '''
- self.tw.set_polar(True)
-
- def _do_rescale_cb(self, button):
- ''' Callback to rescale coordinate space. '''
- if self.tw.coord_scale == 1:
- self.tw.coord_scale = self.tw.height / 200
- self.tw.eraser_button()
- if self.tw.cartesian is True:
- self.tw.overlay_shapes['Cartesian_labeled'].hide()
- self.tw.overlay_shapes['Cartesian'].set_layer(OVERLAY_LAYER)
- else:
- self.tw.coord_scale = 1
- self.tw.eraser_button()
- if self.tw.cartesian is True:
- self.tw.overlay_shapes['Cartesian'].hide()
- self.tw.overlay_shapes['Cartesian_labeled'].set_layer(
- OVERLAY_LAYER)
-
- def _do_hover_help_on_cb(self, button):
- ''' Turn hover help on '''
- self.tw.no_help = False
-
- def _do_hover_help_off_cb(self, button):
- ''' Turn hover help off '''
- self.tw.no_help = True
- self.tw.last_label = None
- self.tw.status_spr.hide()
-
- def _do_palette_cb(self, widget):
- ''' Callback to show/hide palette of blocks. '''
- self.tw.show_palette(self.current_palette)
- self.current_palette += 1
- if self.current_palette == len(self.tw.palettes):
- self.current_palette = 0
-
- def _do_hide_palette_cb(self, widget):
- ''' Hide the palette of blocks. '''
- self.tw.hide_palette()
-
- def _do_hideshow_cb(self, widget):
- ''' Hide/show the blocks. '''
- self.tw.hideshow_button()
-
- def _do_eraser_cb(self, widget):
- ''' Callback for eraser button. '''
- self.tw.eraser_button()
- return
-
- def _do_run_cb(self, widget=None):
- ''' Callback for run button (rabbit). '''
- self.tw.lc.trace = 0
- self.tw.hideblocks()
- self.tw.run_button(0, running_from_button_push=True)
- return
-
- def _do_step_cb(self, widget):
- ''' Callback for step button (turtle). '''
- self.tw.lc.trace = 1
- self.tw.run_button(3, running_from_button_push=True)
- return
-
- def _do_trace_cb(self, widget):
- ''' Callback for debug button (bug). '''
- self.tw.lc.trace = 1
- self.tw.run_button(9, running_from_button_push=True)
- return
-
- def _do_stop_cb(self, widget):
- ''' Callback for stop button. '''
- self.tw.lc.trace = 0
- self.tw.stop_button()
- return
-
- def _do_copy_cb(self, button):
- ''' Callback for copy button. '''
- clipBoard = gtk.Clipboard()
- data = self.tw.assemble_data_to_save(False, False)
- if data is not []:
- text = data_to_string(data)
- clipBoard.set_text(text)
-
- def _do_paste_cb(self, button):
- ''' Callback for paste button. '''
- clipBoard = gtk.Clipboard()
- text = clipBoard.wait_for_text()
- if text is not None:
- if self.tw.selected_blk is not None and\
- self.tw.selected_blk.name == 'string':
- for i in text:
- self.tw.process_alphanumeric_input(i, -1)
- self.tw.selected_blk.resize()
- else:
- self.tw.process_data(data_from_string(text),
- self.tw.paste_offset)
- self.tw.paste_offset += 20
-
- def _window_event(self, event, data):
- ''' Callback for resize event. '''
- data_file = open('.turtleartrc', 'w')
- data_file.write(str(data.x) + '\n')
- data_file.write(str(data.y) + '\n')
- data_file.write(str(data.width) + '\n')
- data_file.write(str(data.height) + '\n')
-
- def nick_changed(self, nick):
- ''' TODO: Rename default turtle in dictionary '''
- pass
-
- def color_changed(self, colors):
- ''' Reskin turtle with collaboration colors '''
- turtle = self.tw.turtles.get_turtle(self.tw.default_turtle_name)
- try:
- turtle.colors = colors.split(',')
- except:
- turtle.colors = DEFAULT_TURTLE_COLORS
- turtle.custom_shapes = True # Force regeneration of shapes
- turtle.reset_shapes()
- turtle.show()
-
- def _get_execution_dir(self):
- ''' From whence is the program being executed? '''
- dirname = os.path.dirname(__file__)
- if dirname == '':
- if os.path.exists(os.path.join('~', 'Activities',
- 'TurtleArt.activity')):
- return os.path.join('~', 'Activities', 'TurtleArt.activity')
- elif os.path.exists(self._INSTALL_PATH):
- return self._INSTALL_PATH
- elif os.path.exists(self._ALTERNATIVE_INSTALL_PATH):
- return self._ALTERNATIVE_INSTALL_PATH
- else:
- return os.path.abspath('.')
- else:
- return os.path.abspath(dirname)
-
-
-if __name__ == '__main__':
- TurtleMain()