From 6acdbc3db543f2692ee336a99722f5ab0b46c77e Mon Sep 17 00:00:00 2001 From: Walter Bender Date: Wed, 13 Nov 2013 22:42:18 +0000 Subject: convert to new primitive type --- (limited to 'plugins') diff --git a/plugins/accelerometer/accelerometer.py b/plugins/accelerometer/accelerometer.py index 26aefd4..57aadea 100644 --- a/plugins/accelerometer/accelerometer.py +++ b/plugins/accelerometer/accelerometer.py @@ -22,8 +22,8 @@ from gettext import gettext as _ from plugins.plugin import Plugin from TurtleArt.tapalette import make_palette -from TurtleArt.talogo import primitive_dictionary from TurtleArt.tautils import debug_output +from TurtleArt.taprimitive import Primitive import logging _logger = logging.getLogger('turtleart-activity accelerometer plugin') @@ -35,6 +35,7 @@ ACCELEROMETER_DEVICE = '/sys/devices/platform/lis3lv02d/position' class Accelerometer(Plugin): def __init__(self, parent): + Plugin.__init__(self) self._parent = parent if os.path.exists(ACCELEROMETER_DEVICE): self._status = True @@ -49,7 +50,6 @@ class Accelerometer(Plugin): help_string=_('Palette of sensor blocks'), position=6) - primitive_dictionary['xyz'] = self.prim_xyz if self._status: palette.add_block('xyz', style='basic-style-extended-vertical', @@ -67,7 +67,8 @@ class Accelerometer(Plugin): prim_name='xyz') self._parent.lc.def_prim( - 'xyz', 0, lambda self: primitive_dictionary['xyz']()) + 'xyz', 0, + Primitive(self.prim_xyz)) def _status_report(self): debug_output('Reporting accelerator status: %s' % (str(self._status))) diff --git a/plugins/audio_sensors/audio_sensors.py b/plugins/audio_sensors/audio_sensors.py index 8d45395..d62ca65 100644 --- a/plugins/audio_sensors/audio_sensors.py +++ b/plugins/audio_sensors/audio_sensors.py @@ -18,7 +18,6 @@ from gettext import gettext as _ try: - from numpy import append from numpy.fft import rfft PITCH_AVAILABLE = True except: @@ -33,8 +32,9 @@ from plugins.audio_sensors.ringbuffer import RingBuffer1d from TurtleArt.tapalette import make_palette from TurtleArt.taconstants import XO1, XO15, XO175, XO30, XO4 -from TurtleArt.talogo import primitive_dictionary from TurtleArt.tautils import debug_output +from TurtleArt.taprimitive import (ConstantArg, Primitive) +from TurtleArt.tatype import TYPE_NUMBER import logging _logger = logging.getLogger('turtleart-activity audio sensors plugin') @@ -57,7 +57,9 @@ def _avg(array, abs_value=False): class Audio_sensors(Plugin): def __init__(self, parent): + Plugin.__init__(self) self._parent = parent + self.audio_started = False self._status = True # TODO: test for audio device # These flags are referenced by audiograb self.hw = self._parent.hw @@ -65,152 +67,145 @@ class Audio_sensors(Plugin): def setup(self): ''' set up audio-sensor-specific blocks ''' + self._sound = [0, 0] + self._volume = [0, 0] + self._pitch = [0, 0] + self._resistance = [0, 0] + self._voltage = [0, 0] self.max_samples = 1500 self.input_step = 1 - self.ringbuffer = [] palette = make_palette('sensor', colors=["#FF6060", "#A06060"], help_string=_('Palette of sensor blocks'), position=6) - - primitive_dictionary['sound'] = self.prim_sound - primitive_dictionary['volume'] = self.prim_volume + hidden = True if self._status: - palette.add_block('sound', - style='box-style', - label=_('sound'), - help_string=_('raw microphone input signal'), - value_block=True, - prim_name='sound') - - palette.add_block('volume', - style='box-style', - label=_('loudness'), - help_string=_('microphone input volume'), - value_block=True, - prim_name='volume') - else: - palette.add_block('sound', - hidden=True, - style='box-style', - label=_('sound'), - help_string=_('raw microphone input signal'), - value_block=True, - prim_name='sound') - palette.add_block('volume', - hidden=True, - style='box-style', - label=_('loudness'), - help_string=_('microphone input volume'), - value_block=True, - prim_name='volume') + hidden = False + + palette.add_block('sound', + hidden=hidden, + style='box-style', + label=_('sound'), + help_string=_('raw microphone input signal'), + value_block=True, + prim_name='sound') + palette.add_block('volume', + hidden=hidden, + style='box-style', + label=_('loudness'), + help_string=_('microphone input volume'), + value_block=True, + prim_name='volume') self._parent.lc.def_prim( - 'sound', 0, lambda self: primitive_dictionary['sound'](0)) + 'sound', 0, + Primitive(self.prim_sound, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(0)}, + call_afterwards=self.after_sound)) + self._parent.lc.def_prim( - 'volume', 0, lambda self: primitive_dictionary['volume'](0)) + 'volume', 0, + Primitive(self.prim_volume, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(0)}, + call_afterwards=self.after_volume)) - primitive_dictionary['pitch'] = self.prim_pitch + hidden = True if PITCH_AVAILABLE and self._status: - palette.add_block('pitch', - style='box-style', - label=_('pitch'), - help_string=_('microphone input pitch'), - value_block=True, - prim_name='pitch') - else: - palette.add_block('pitch', - hidden=True, - style='box-style', - label=_('pitch'), - help_string=_('microphone input pitch'), - value_block=True, - prim_name='pitch') - self._parent.lc.def_prim('pitch', 0, - lambda self: primitive_dictionary['pitch'](0)) - - primitive_dictionary['resistance'] = self.prim_resistance - primitive_dictionary['voltage'] = self.prim_voltage + hidden = False + + palette.add_block('pitch', + hidden=hidden, + style='box-style', + label=_('pitch'), + help_string=_('microphone input pitch'), + value_block=True, + prim_name='pitch') + self._parent.lc.def_prim( + 'pitch', 0, + Primitive(self.prim_pitch, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(0)}, + call_afterwards=self.after_pitch)) + + hidden = True if self.hw in [XO1, XO15, XO175, XO4, XO30] and self._status: + # Calibration based on http://bugs.sugarlabs.org/ticket/4649 if self.hw == XO1: self.voltage_gain = 0.000022 self.voltage_bias = 1.14 elif self.hw == XO15: self.voltage_gain = -0.00015 self.voltage_bias = 1.70 - elif self.hw in [XO175, XO4]: # recalibrate in light of #3675? - self.voltage_gain = 0.000071 - self.voltage_bias = 0.55 + elif self.hw == XO175: # Range 0.01V to 3.01V + self.voltage_gain = 0.0000516 + self.voltage_bias = 1.3598 + elif self.hw == XO4: # Range 0.17V to 3.08V + self.voltage_gain = 0.0004073 + self.voltage_bias = 1.6289 else: # XO 3.0 self.voltage_gain = 0.000077 self.voltage_bias = 0.72 - palette.add_block('resistance', - style='box-style', - label=_('resistance'), - help_string=_('microphone input resistance'), - value_block=True, - prim_name='resistance') - palette.add_block('voltage', - style='box-style', - label=_('voltage'), - help_string=_('microphone input voltage'), - value_block=True, - prim_name='voltage') - else: - palette.add_block('resistance', - hidden=True, - style='box-style', - label=_('resistance'), - help_string=_('microphone input resistance'), - prim_name='resistance') - palette.add_block('voltage', - hidden=True, - style='box-style', - label=_('voltage'), - help_string=_('microphone input voltage'), - prim_name='voltage') - - # FIXME: Only add stereo capture for XO15 (broken on ARM #3675) + hidden = False + + palette.add_block('resistance', + hidden=hidden, + style='box-style', + label=_('resistance'), + help_string=_('microphone input resistance'), + prim_name='resistance') + palette.add_block('voltage', + hidden=hidden, + style='box-style', + label=_('voltage'), + help_string=_('microphone input voltage'), + prim_name='voltage') + + hidden = True + # Only add stereo capture for XO15 (broken on ARM #3675) if self.hw in [XO15] and self._status: - palette.add_block('resistance2', - style='box-style', - label=_('resistance') + '2', - help_string=_('microphone input resistance'), - value_block=True, - prim_name='resistance2') - palette.add_block('voltage2', - style='box-style', - label=_('voltage') + '2', - help_string=_('microphone input voltage'), - value_block=True, - prim_name='voltage2') - else: - palette.add_block('resistance2', - hidden=True, - style='box-style', - label=_('resistance') + '2', - help_string=_('microphone input resistance'), - prim_name='resistance2') - palette.add_block('voltage2', - hidden=True, - style='box-style', - label=_('voltage') + '2', - help_string=_('microphone input voltage'), - prim_name='voltage2') + hidden = False + + palette.add_block('resistance2', + hidden=hidden, + style='box-style', + label=_('resistance') + '2', + help_string=_('microphone input resistance'), + prim_name='resistance2') + palette.add_block('voltage2', + hidden=hidden, + style='box-style', + label=_('voltage') + '2', + help_string=_('microphone input voltage'), + prim_name='voltage2') self._parent.lc.def_prim( 'resistance', 0, - lambda self: primitive_dictionary['resistance'](0)) + Primitive(self.prim_resistance, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(0)}, + call_afterwards=self.after_resistance)) self._parent.lc.def_prim( - 'voltage', 0, lambda self: primitive_dictionary['voltage'](0)) + 'voltage', 0, + Primitive(self.prim_voltage, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(0)}, + call_afterwards=self.after_voltage)) self._parent.lc.def_prim( 'resistance2', 0, - lambda self: primitive_dictionary['resistance'](1)) + Primitive(self.prim_resistance, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(1)}, + call_afterwards=self.after_resistance)) self._parent.lc.def_prim( - 'voltage2', 0, lambda self: primitive_dictionary['voltage'](1)) + 'voltage2', 0, + Primitive(self.prim_voltage, + return_type=TYPE_NUMBER, + kwarg_descs={'channel': ConstantArg(1)}, + call_afterwards=self.after_voltage)) - self.audio_started = False if self.hw in [XO175, XO30, XO4]: self.PARAMETERS = { SENSOR_AC_BIAS: (False, True, 80, True), @@ -240,6 +235,11 @@ class Audio_sensors(Plugin): ''' Start grabbing audio if there is an audio block in use ''' if not self._status: return + self._sound = [0, 0] + self._volume = [0, 0] + self._pitch = [0, 0] + self._resistance = [0, 0] + self._voltage = [0, 0] if self.audio_started: self.audiograb.stop_grabbing() if len(self._parent.block_list.get_similar_blocks( @@ -292,177 +292,181 @@ class Audio_sensors(Plugin): self._parent.running_sugar) return self._status - # Block primitives used in talogo + # Block primitives - def prim_volume(self, channel): + def prim_sound(self, channel=0): if not self._status: return 0 + self._prim_sound(0) # Return average of both channels if sampling in stereo if self._channels == 2: - chan0 = self._prim_volume(0) - chan1 = self._prim_volume(1) - return (chan0 + chan1) / 2 + self._prim_sound(1) + return (self._sound[0] + self._sound[1]) / 2.0 else: - return self._prim_volume(0) + return self._sound[0] - def _prim_volume(self, channel): - ''' return mic in value ''' + def _prim_sound(self, channel): + ''' return raw mic in value ''' buf = self.ringbuffer[channel].read(None, self.input_step) if len(buf) > 0: - volume = float(_avg(buf, abs_value=True)) - self._parent.lc.update_label_value('volume', volume) - return volume + self._sound[channel] = float(buf[0]) else: - return 0 + self._sound[channel] = 0 + + def after_sound(self, channel=0): + if self._parent.lc.update_values: + self._parent.lc.update_label_value('sound', self._sound[channel]) - def prim_sound(self, channel): + def prim_volume(self, channel=0): if not self._status: return 0 + self._prim_volume(0) # Return average of both channels if sampling in stereo if self._channels == 2: - chan0 = self._prim_sound(0) - chan1 = self._prim_sound(1) - return (chan0 + chan1) / 2 + self._prim_volume(1) + return (self._volume[0] + self._volume[1]) / 2.0 else: - return self._prim_sound(0) + return self._volume[0] - def _prim_sound(self, channel): + def _prim_volume(self, channel): ''' return raw mic in value ''' buf = self.ringbuffer[channel].read(None, self.input_step) if len(buf) > 0: - sound = float(buf[0]) - if self._parent.lc.update_values: - self._parent.lc.update_label_value('sound', sound) - return sound + self._volume[channel] = float(_avg(buf, abs_value=True)) else: - return 0 + self._volume[channel] = 0 + + def after_volume(self, channel=0): + if self._parent.lc.update_values: + self._parent.lc.update_label_value('volume', self._volume[channel]) - def prim_pitch(self, channel): - if not PITCH_AVAILABLE or not self._status: + def prim_pitch(self, channel=0): + if not self._status: return 0 + self._prim_pitch(0) # Return average of both channels if sampling in stereo if self._channels == 2: - chan0 = self._prim_pitch(0) - chan1 = self._prim_pitch(1) - return (chan0 + chan1) / 2 + self._prim_pitch(1) + return (self._pitch[0] + self._pitch[1]) / 2.0 else: - return self._prim_pitch(0) + return self._pitch[0] def _prim_pitch(self, channel): - ''' return index of max value in fft of mic in values ''' + ''' return raw mic in value ''' buf = self.ringbuffer[channel].read(None, self.input_step) if len(buf) > 0: buf = rfft(buf) buf = abs(buf) maxi = buf.argmax() if maxi == 0: - pitch = 0 + self._pitch[channel] = 0 else: # Simple interpolation a, b, c = buf[maxi - 1], buf[maxi], buf[maxi + 1] maxi -= a / float(a + b + c) maxi += c / float(a + b + c) - pitch = maxi * 48000 / (len(buf) * 2) - - if self._parent.lc.update_values: - self._parent.lc.update_label_value('pitch', pitch) - return pitch + self._pitch[channel] = maxi * 48000 / (len(buf) * 2) else: - return 0 + self._pitch[channel] = 0 + + def after_pitch(self, channel=0): + if self._parent.lc.update_values: + self._parent.lc.update_label_value('pitch', self._pitch[channel]) - def prim_resistance(self, channel): + def prim_resistance(self, channel=0): if not self.hw in [XO1, XO15, XO175, XO30, XO4] or not self._status: return 0 if self.hw in [XO1, XO4]: - resistance = self._prim_resistance(0) - if self._parent.lc.update_values: - self._update_resistance_labels(0, resistance) - return resistance + self._prim_resistance(0) + return self._resistance[0] elif self.hw == XO15: - resistance = self._prim_resistance(channel) - if self._parent.lc.update_values: - self._update_resistance_labels(channel, resistance) - return resistance - # FIXME: For XO175: channel assignment is seemingly random - # (#3675), so sum both channels (one of them will be 0) + self._prim_resistance(channel) + return self._resistance[channel] + # For XO175: channel assignment is seemingly random + # (#3675), one of them will be 0 else: - chan0 = self._prim_resistance(0) - chan1 = self._prim_resistance(1) - resistance = chan0 + chan1 - if self._parent.lc.update_values: - self._update_resistance_labels(0, resistance) - return resistance + self._prim_resistance(0) + if self._resistance[0] != 999999999: + return self._resistance[0] + else: + self._prim_resistance(1) + return self._resistance[1] def _prim_resistance(self, channel): ''' return resistance sensor value ''' buf = self.ringbuffer[channel].read(None, self.input_step) if len(buf) > 0: - # See - # TODO: test this calibration on XO 1.5, XO 1.75 + # See http://bugs.sugarlabs.org/ticket/552#comment:7 + # and http://bugs.sugarlabs.org/ticket/4649 avg_buf = float(_avg(buf)) if self.hw == XO1: - resistance = 2.718 ** ((avg_buf * 0.000045788) + 8.0531) + self._resistance[channel] = \ + 2.718 ** ((avg_buf * 0.000045788) + 8.0531) elif self.hw == XO15: if avg_buf > 0: - resistance = (420000000 / avg_buf) - 13500 + self._resistance[channel] = (420000000 / avg_buf) - 13500 else: - resistance = 420000000 - elif self.hw in [XO175, XO4]: - if avg_buf < 30700: - resistance = .12 * ((180000000 / (30700 - avg_buf)) - 3150) + self._resistance[channel] = 420000000 + elif self.hw == XO175: # Range 0 to inf ohms + if avg_buf < 30519: + self._resistance[channel] = \ + (92000000. / (30519 - avg_buf)) - 1620 else: - resistance = 999999999 + self._resistance[channel] = 999999999 + elif self.hw == XO4: # Range 0 to inf ohms + if avg_buf < 6629: + self._resistance[channel] = \ + (50000000. / (6629 - avg_buf)) - 3175 + else: + self._resistance[channel] = 999999999 else: # XO 3.0 if avg_buf < 30514: - resistance = (46000000 / (30514 - avg_buf)) - 1150 + self._resistance[channel] = \ + (46000000. / (30514 - avg_buf)) - 1150 else: - resistance = 999999999 - if resistance < 0: - resistance = 0 - return resistance + self._resistance[channel] = 999999999 + if self._resistance[channel] < 0: + self._resistance[channel] = 0 else: - return 0 + self._resistance[channel] = 0 - def _update_resistance_labels(self, channel, resistance): - if channel == 0: - self._parent.lc.update_label_value('resistance', resistance) - else: - self._parent.lc.update_label_value('resistance2', resistance) + def after_resistance(self, channel=0): + if self._parent.lc.update_values: + self._parent.lc.update_label_value( + ['resistance', 'resistance2'][channel], + self._resistance[channel]) - def prim_voltage(self, channel): + def prim_voltage(self, channel=0): if not self.hw in [XO1, XO15, XO175, XO30, XO4] or not self._status: return 0 if self.hw in [XO1, XO4]: - voltage = self._prim_voltage(0) - if self._parent.lc.update_values: - self._update_voltage_labels(0, voltage) - return voltage + self._prim_voltage(0) + return self._voltage[0] elif self.hw == XO15: - voltage = self._prim_voltage(channel) - if self._parent.lc.update_values: - self._update_voltage_labels(channel, voltage) - return voltage + self._prim_voltage(channel) + return self._voltage[channel] # FIXME: For XO175: channel assignment is seemingly random - # (#3675), so sum both channels (one of them will be 0) + # (#3675), one of them will be 0 else: - chan0 = self._prim_voltage(0) - chan1 = self._prim_voltage(1) - voltage = chan0 + chan1 - if self._parent.lc.update_values: - self._update_voltage_labels(0, voltage) - return voltage + self._prim_voltage(0) + if self._voltage[0] != 0: + return self._voltage[0] + else: + self._prim_voltage(1) + return self._voltage[1] def _prim_voltage(self, channel): ''' return voltage sensor value ''' buf = self.ringbuffer[channel].read(None, self.input_step) + buf = self.ringbuffer[channel].read(None, self.input_step) if len(buf) > 0: # See - voltage = float(_avg(buf)) * self.voltage_gain + self.voltage_bias - return voltage + self._voltage[channel] = \ + float(_avg(buf)) * self.voltage_gain + self.voltage_bias else: - return 0 + self._voltage[channel] = 0 - def _update_voltage_labels(self, channel, voltage): - if channel == 0: - self._parent.lc.update_label_value('voltage', voltage) - else: - self._parent.lc.update_label_value('voltage2', voltage) + def after_voltage(self, channel=0): + if self._parent.lc.update_values: + self._parent.lc.update_label_value( + ['voltage', 'voltage2'][channel], + self._voltage[channel]) diff --git a/plugins/camera_sensor/camera_sensor.py b/plugins/camera_sensor/camera_sensor.py index 6509a88..5f79d15 100644 --- a/plugins/camera_sensor/camera_sensor.py +++ b/plugins/camera_sensor/camera_sensor.py @@ -30,21 +30,25 @@ from plugins.camera_sensor.v4l2 import v4l2_control, V4L2_CID_AUTOGAIN, \ from plugins.plugin import Plugin from TurtleArt.tapalette import make_palette -from TurtleArt.talogo import media_blocks_dictionary, primitive_dictionary +from TurtleArt.talogo import media_blocks_dictionary from TurtleArt.tautils import get_path, debug_output from TurtleArt.taconstants import MEDIA_SHAPES, NO_IMPORT, SKIN_PATHS, \ BLOCKS_WITH_SKIN +from TurtleArt.taprimitive import (ConstantArg, Primitive) +from TurtleArt.tatype import TYPE_NUMBER class Camera_sensor(Plugin): def __init__(self, parent): + Plugin.__init__(self) ''' Make sure there is a camera device ''' self._parent = parent self._status = False self._ag_control = None self.devices = [] self.cameras = [] + self.luminance = 0 if os.path.exists('/dev/video0'): self.devices.append('/dev/video0') @@ -68,7 +72,6 @@ class Camera_sensor(Plugin): position=7) # set up camera-specific blocks - primitive_dictionary['read_camera'] = self.prim_read_camera media_blocks_dictionary['camera'] = self.prim_take_picture0 media_blocks_dictionary['camera1'] = self.prim_take_picture1 @@ -82,9 +85,12 @@ class Camera_sensor(Plugin): 'light level detected by camera'), value_block=True, prim_name='luminance') - self._parent.lc.def_prim('luminance', 0, - lambda self: primitive_dictionary['read_camera']( - luminance_only=True)) + self._parent.lc.def_prim( + 'luminance', 0, + Primitive(self.prim_read_camera, + return_type=TYPE_NUMBER, + kwarg_descs={'luminance_only': ConstantArg(True)}, + call_afterwards=self.after_luminance)) # Depreciated block sensors_palette.add_block('read_camera', @@ -96,8 +102,10 @@ class Camera_sensor(Plugin): is pushed to the stack'), value_block=True, prim_name='read_camera') - self._parent.lc.def_prim('read_camera', 0, - lambda self: primitive_dictionary['read_camera']()) + self._parent.lc.def_prim( + 'read_camera', 0, + Primitive(self.prim_read_camera, + kwarg_descs={'luminance_only': ConstantArg(False)})) media_palette.add_block('camera', style='box-style-media', @@ -130,9 +138,12 @@ is pushed to the stack'), _('light level detected by camera'), value_block=True, prim_name='read_camera') - self._parent.lc.def_prim('luminance', 0, - lambda self: primitive_dictionary['read_camera']( - luminance_only=True)) + self._parent.lc.def_prim( + 'luminance', 0, + Primitive(self.prim_read_camera, + return_type=TYPE_NUMBER, + kwarg_descs={'luminance_only': ConstantArg(True)}, + call_afterwards=self.after_luminance)) # Depreciated block sensors_palette.add_block('read_camera', @@ -144,8 +155,11 @@ is pushed to the stack'), is pushed to the stack'), value_block=True, prim_name='read_camera') - self._parent.lc.def_prim('read_camera', 0, - lambda self: primitive_dictionary['read_camera']()) + self._parent.lc.def_prim( + 'read_camera', 0, + Primitive(self.prim_read_camera, + return_type=TYPE_NUMBER, + kwarg_descs={'luminance_only': ConstantArg(False)})) media_palette.add_block('camera', hidden=True, @@ -227,19 +241,19 @@ is pushed to the stack'), self._parent.lc.heap.append(-1) self._parent.lc.heap.append(-1) self._parent.lc.heap.append(-1) - return + return array = None self._set_autogain(0, camera=camera) # disable AUTOGAIN self._get_pixbuf_from_camera(camera=camera) self.calc_luminance(camera=camera) if self.luminance_only: - self._parent.lc.update_label_value('luminance', self.luminance) - return self.luminance + return int(self.luminance) else: self._parent.lc.heap.append(self.b) self._parent.lc.heap.append(self.g) self._parent.lc.heap.append(self.r) + return def calc_luminance(self, camera=0): array = self.cameras[camera].pixbuf.get_pixels() @@ -281,6 +295,10 @@ is pushed to the stack'), self.g = -1 self.b = -1 + def after_luminance(self, luminance_only=False): + if self._parent.lc.update_values and luminance_only: + self._parent.lc.update_label_value('luminance', self.luminance) + def _set_autogain(self, state, camera=0): ''' 0 is off; 1 is on ''' if self._ag_control is not None and self._ag_control.value == state: diff --git a/plugins/light_sensor/light_sensor.py b/plugins/light_sensor/light_sensor.py index bd5655e..dc4ebb1 100644 --- a/plugins/light_sensor/light_sensor.py +++ b/plugins/light_sensor/light_sensor.py @@ -22,8 +22,9 @@ from gettext import gettext as _ from plugins.plugin import Plugin from TurtleArt.tapalette import make_palette -from TurtleArt.talogo import primitive_dictionary from TurtleArt.tautils import debug_output +from TurtleArt.taprimitive import Primitive +from TurtleArt.tatype import TYPE_NUMBER import logging _logger = logging.getLogger('turtleart-activity light-sensor plugin') @@ -35,11 +36,13 @@ LIGHT_SENSOR_DEVICE = '/sys/devices/platform/olpc-ols.0/level' class Light_sensor(Plugin): def __init__(self, parent): + Plugin.__init__(self) self._parent = parent if os.path.exists(LIGHT_SENSOR_DEVICE): self._status = True else: self._status = False + self._light = 0 self.running_sugar = self._parent.running_sugar def setup(self): @@ -49,11 +52,11 @@ class Light_sensor(Plugin): help_string=_('Palette of sensor blocks'), position=6) - primitive_dictionary['lightsensor'] = self.prim_lightsensor if self._status: palette.add_block('lightsensor', style='box-style', label=_('brightness'), + value_block=True, help_string=\ _('light level detected by light sensor'), prim_name='lightsensor') @@ -61,6 +64,7 @@ class Light_sensor(Plugin): palette.add_block('lightsensor', style='box-style', label=_('brightness'), + value_block=True, help_string=\ _('light level detected by light sensor'), hidden=True, @@ -68,20 +72,26 @@ class Light_sensor(Plugin): self._parent.lc.def_prim( 'lightsensor', 0, - lambda self: primitive_dictionary['lightsensor']()) + Primitive(self.prim_lightsensor, + return_type=TYPE_NUMBER, + call_afterwards=self.after_light)) def _status_report(self): debug_output('Reporting light-sensor status: %s' % (str(self._status))) return self._status - # Block primitives used in talogo + # Block primitives def prim_lightsensor(self): - ''' push accelerometer xyz to stack ''' if not self._status: return -1 else: fh = open(LIGHT_SENSOR_DEVICE) string = fh.read() fh.close() - return float(string) + self._light = float(string) + return self._light + + def after_light(self): + if self._parent.lc.update_values: + self._parent.lc.update_label_value('lightsensor', self._light) diff --git a/plugins/rfid/rfid.py b/plugins/rfid/rfid.py index de96a1f..c8742ff 100644 --- a/plugins/rfid/rfid.py +++ b/plugins/rfid/rfid.py @@ -24,8 +24,9 @@ from plugins.rfid.rfidutils import strhex2bin, strbin2dec, find_device from plugins.plugin import Plugin from TurtleArt.tapalette import make_palette -from TurtleArt.talogo import primitive_dictionary from TurtleArt.tautils import debug_output +from TurtleArt.taprimitive import Primitive +from TurtleArt.tatype import TYPE_STRING import logging _logger = logging.getLogger('turtleart-activity RFID plugin') @@ -41,6 +42,7 @@ REGEXP_SERUSB = '\/org\/freedesktop\/Hal\/devices\/usb_device['\ class Rfid(Plugin): def __init__(self, parent): + Plugin.__init__(self) self._parent = parent self._status = False @@ -80,7 +82,6 @@ class Rfid(Plugin): def setup(self): # set up RFID-specific blocks - primitive_dictionary['rfid'] = self.prim_read_rfid palette = make_palette('sensor', colors=["#FF6060", "#A06060"], help_string=_('Palette of sensor blocks'), @@ -103,7 +104,10 @@ class Rfid(Plugin): prim_name='rfid') self._parent.lc.def_prim( - 'rfid', 0, lambda self: primitive_dictionary['rfid']()) + 'rfid', 0, + Primitive(self.prim_read_rfid, + return_type=TYPE_STRING, + call_afterwards=self.after_rfid)) def _status_report(self): debug_output('Reporting RFID status: %s' % (str(self._status))) @@ -149,3 +153,7 @@ class Rfid(Plugin): return self.rfid_idn else: return '0' + + def after_rfid(self): + if self._parent.lc.update_values: + self._parent.lc.update_label_value('rfid', self.rfid_idn) diff --git a/plugins/turtle_blocks_extras/turtle_blocks_extras.py b/plugins/turtle_blocks_extras/turtle_blocks_extras.py index e31cb27..1e9b2e4 100644 --- a/plugins/turtle_blocks_extras/turtle_blocks_extras.py +++ b/plugins/turtle_blocks_extras/turtle_blocks_extras.py @@ -15,8 +15,6 @@ # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -import gtk -import gobject from time import time import os import glob @@ -24,37 +22,19 @@ import glob from gettext import gettext as _ from plugins.plugin import Plugin -from TurtleArt.tapalette import (make_palette, define_logo_function, - block_names, block_primitives, special_names, - content_blocks, palette_name_to_index, - palette_names, palette_i18n_names) -from TurtleArt.talogo import (primitive_dictionary, logoerror, - media_blocks_dictionary) -from TurtleArt.taconstants import (DEFAULT_SCALE, ICON_SIZE, CONSTANTS, - MEDIA_SHAPES, SKIN_PATHS, BLOCKS_WITH_SKIN, - PYTHON_SKIN, PREFIX_DICTIONARY, VOICES, - MACROS, COLORDICT) -from TurtleArt.tautils import (round_int, debug_output, get_path, - data_to_string, find_group, image_to_base64, - hat_on_top, listify, data_from_file, - data_to_file, chooser_dialog, get_load_name) -from TurtleArt.tajail import (myfunc, myfunc_import) - - -def _num_type(x): - """ Is x a number type? """ - if type(x) == int: - return True - if type(x) == float: - return True - if type(x) == ord: - return True - return False - - -def _millisecond(): - """ Current time in milliseconds """ - return time() * 1000 +from TurtleArt.tapalette import (make_palette, define_logo_function) +from TurtleArt.talogo import (primitive_dictionary, logoerror) +from TurtleArt.taconstants import (CONSTANTS, MACROS, KEY_DICT, MEDIA_SHAPES, + REVERSE_KEY_DICT, SKIN_PATHS, + BLOCKS_WITH_SKIN, PYTHON_SKIN, + MEDIA_BLOCK2TYPE, VOICES) +from TurtleArt.tautils import (debug_output, get_path, data_to_string, + hat_on_top, listify, data_from_file) +from TurtleArt.taprimitive import (ArgSlot, ConstantArg, Primitive) +from TurtleArt.tatype import (TYPE_BOOL, TYPE_BOX, TYPE_CHAR, TYPE_INT, + TYPE_FLOAT, TYPE_OBJECT, TYPE_STRING, + TYPE_NUMBER) +from TurtleArt.taturtle import Turtle class Turtle_blocks_extras(Plugin): @@ -62,13 +42,13 @@ class Turtle_blocks_extras(Plugin): from Turtle Art """ def __init__(self, turtle_window): + Plugin.__init__(self) self.tw = turtle_window def setup(self): SKIN_PATHS.append('plugins/turtle_blocks_extras/images') self.heap = self.tw.lc.heap - self.keyboard = self.tw.lc.keyboard self.title_height = int((self.tw.canvas.height / 20) * self.tw.scale) # set up Turtle Block palettes @@ -91,7 +71,6 @@ class Turtle_blocks_extras(Plugin): colors=["#FFC000", "#A08000"], help_string=_('Palette of flow operators')) - # internally expanded macro palette.add_block('while', style='clamp-style-boolean', label=_('while'), @@ -100,8 +79,19 @@ class Turtle_blocks_extras(Plugin): special_name=_('while'), help_string=_('do-while-True operator that uses \ boolean operators from Numbers palette')) + self.tw.lc.def_prim( + 'while', 2, + Primitive(self.tw.lc.prim_loop, + arg_descs=[ + ArgSlot(TYPE_OBJECT, + call_arg=False, + wrapper=Primitive( + Primitive.controller_while, + arg_descs=[ArgSlot(TYPE_BOOL, + call_arg=False)])), + ArgSlot(TYPE_OBJECT)]), + True) - # internally expanded macro palette.add_block('until', style='clamp-style-boolean', label=_('until'), @@ -110,23 +100,39 @@ boolean operators from Numbers palette')) special_name=_('until'), help_string=_('do-until-True operator that uses \ boolean operators from Numbers palette')) + self.tw.lc.def_prim( + 'until', 2, + Primitive(self.tw.lc.prim_loop, + arg_descs=[ + ArgSlot(TYPE_OBJECT, + call_arg=False, + # TODO can we use controller_while in + # combination with not_? + wrapper=Primitive( + Primitive.controller_until, + arg_descs=[ArgSlot(TYPE_BOOL, + call_arg=False)])), + ArgSlot(TYPE_OBJECT)]), + True) - primitive_dictionary['clamp'] = self._prim_clamp palette.add_block('sandwichclamp', style='clamp-style-collapsible', label=' ', special_name=_('top'), prim_name='clamp', help_string=_('top of a collapsible stack')) - self.tw.lc.def_prim('clamp', 1, primitive_dictionary['clamp'], True) + self.tw.lc.def_prim('clamp', 1, + Primitive(self.tw.lc.prim_clamp, + arg_descs=[ArgSlot(TYPE_OBJECT)]), + True) def _media_palette(self): - debug_output('creating %s palette' % _('media'), - self.tw.running_sugar) + palette = make_palette('media', colors=["#A0FF00", "#80A000"], help_string=_('Palette of media objects'), - position=7) + position=7, + translation=_('media')) palette.add_block('journal', style='box-style-media', @@ -134,7 +140,7 @@ boolean operators from Numbers palette')) default='None', special_name=_('journal'), help_string=_('Sugar Journal media object')) - PREFIX_DICTIONARY['journal'] = '#smedia_' + MEDIA_BLOCK2TYPE['journal'] = 'media' BLOCKS_WITH_SKIN.append('journal') MEDIA_SHAPES.append('journalsmall') MEDIA_SHAPES.append('journaloff') @@ -147,7 +153,7 @@ boolean operators from Numbers palette')) default='None', help_string=_('Sugar Journal audio object')) BLOCKS_WITH_SKIN.append('audio') - PREFIX_DICTIONARY['audio'] = '#saudio_' + MEDIA_BLOCK2TYPE['audio'] = 'audio' MEDIA_SHAPES.append('audiosmall') MEDIA_SHAPES.append('audiooff') MEDIA_SHAPES.append('audioon') @@ -159,7 +165,7 @@ boolean operators from Numbers palette')) default='None', help_string=_('Sugar Journal video object')) BLOCKS_WITH_SKIN.append('video') - PREFIX_DICTIONARY['video'] = '#svideo_' + MEDIA_BLOCK2TYPE['video'] = 'video' MEDIA_SHAPES.append('videosmall') MEDIA_SHAPES.append('videooff') MEDIA_SHAPES.append('videoon') @@ -171,7 +177,7 @@ boolean operators from Numbers palette')) default='None', help_string=_('Sugar Journal description field')) BLOCKS_WITH_SKIN.append('description') - PREFIX_DICTIONARY['description'] = '#sdescr_' + MEDIA_BLOCK2TYPE['description'] = 'descr' MEDIA_SHAPES.append('descriptionsmall') MEDIA_SHAPES.append('descriptionoff') MEDIA_SHAPES.append('descriptionon') @@ -183,7 +189,6 @@ boolean operators from Numbers palette')) special_name=_('text'), help_string=_('string value')) - primitive_dictionary['show'] = self._prim_show palette.add_block('show', style='basic-style-1arg', label=_('show'), @@ -193,8 +198,9 @@ boolean operators from Numbers palette')) help_string=_('draws text or show media from the \ Journal')) self.tw.lc.def_prim('show', 1, - lambda self, x: - primitive_dictionary['show'](x, True)) + Primitive(self.tw.lc.show, + arg_descs=[ArgSlot(TYPE_OBJECT), + ConstantArg(True)])) palette.add_block('showaligned', hidden=True, @@ -207,10 +213,10 @@ Journal')) help_string=_('draws text or show media from the \ Journal')) self.tw.lc.def_prim('showaligned', 1, - lambda self, x: - primitive_dictionary['show'](x, False)) + Primitive(self.tw.lc.show, + arg_descs=[ArgSlot(TYPE_OBJECT), + ConstantArg(False)])) - primitive_dictionary['setscale'] = self._prim_setscale palette.add_block('setscale', style='basic-style-1arg', label=_('set scale'), @@ -218,11 +224,13 @@ Journal')) default=33, logo_command='setlabelheight', help_string=_('sets the scale of media')) - self.tw.lc.def_prim('setscale', 1, - lambda self, x: - primitive_dictionary['setscale'](x)) + self.tw.lc.def_prim( + 'setscale', 1, + Primitive(self.tw.lc.set_scale, + arg_descs=[ArgSlot(TYPE_NUMBER)], + call_afterwards=lambda value: self.after_set( + 'scale', value))) - primitive_dictionary['savepix'] = self._prim_save_picture palette.add_block('savepix', style='basic-style-1arg', label=_('save picture'), @@ -231,9 +239,9 @@ Journal')) help_string=_('saves a picture to the Sugar \ Journal')) self.tw.lc.def_prim('savepix', 1, - lambda self, x: primitive_dictionary['savepix'](x)) + Primitive(self.tw.save_as_image, + arg_descs=[ArgSlot(TYPE_STRING)])) - primitive_dictionary['savesvg'] = self._prim_save_svg palette.add_block('savesvg', style='basic-style-1arg', label=_('save SVG'), @@ -242,7 +250,9 @@ Journal')) help_string=_('saves turtle graphics as an SVG file \ in the Sugar Journal')) self.tw.lc.def_prim('savesvg', 1, - lambda self, x: primitive_dictionary['savesvg'](x)) + Primitive(self.tw.save_as_image, + arg_descs=[ArgSlot(TYPE_STRING)], + kwarg_descs={'svg': ConstantArg(True)})) palette.add_block('scale', style='box-style', @@ -251,7 +261,9 @@ in the Sugar Journal')) value_block=True, logo_command='labelsize', help_string=_('holds current scale value')) - self.tw.lc.def_prim('scale', 0, lambda self: self.tw.lc.scale) + self.tw.lc.def_prim('scale', 0, + Primitive(self.tw.lc.get_scale, + return_type=TYPE_NUMBER)) palette.add_block('mediawait', style='basic-style-extended-vertical', @@ -282,7 +294,6 @@ complete')) help_string=_('resume playing video or audio')) self.tw.lc.def_prim('mediaplay', 0, self.tw.lc.media_play, True) - primitive_dictionary['speak'] = self._prim_speak palette.add_block('speak', style='basic-style-1arg', label=_('speak'), @@ -290,9 +301,9 @@ complete')) default=_('hello'), help_string=_('speaks text')) self.tw.lc.def_prim('speak', 1, - lambda self, x: primitive_dictionary['speak'](x)) + Primitive(self.prim_speak, + arg_descs=[ArgSlot(TYPE_STRING)])) - primitive_dictionary['sinewave'] = self._prim_sinewave palette.add_block('sinewave', style='basic-style-3arg', # TRANS: pitch, duration, amplitude @@ -303,18 +314,19 @@ complete')) help_string=_('plays a sinewave at frequency, \ amplitude, and duration (in seconds)')) self.tw.lc.def_prim('sinewave', 3, - lambda self, x, y, z: - primitive_dictionary['sinewave'](x, y, z)) + Primitive(self.prim_sinewave, + arg_descs=[ArgSlot(TYPE_NUMBER), + ArgSlot(TYPE_NUMBER), + ArgSlot(TYPE_NUMBER)])) def _sensor_palette(self): - debug_output('creating %s palette' % _('sensor'), - self.tw.running_sugar) + palette = make_palette('sensor', colors=["#FF6060", "#A06060"], help_string=_('Palette of sensor blocks'), - position=6) + position=6, + translation=_('sensor')) - primitive_dictionary['mousebutton'] = self._prim_mouse_button palette.add_block('mousebutton', hidden=True, style='box-style', @@ -324,9 +336,9 @@ amplitude, and duration (in seconds)')) help_string=_('returns 1 if mouse button is \ pressed')) self.tw.lc.def_prim('mousebutton', 0, - lambda self: primitive_dictionary['mousebutton']()) + Primitive(self.tw.get_mouse_flag, + return_type=TYPE_NUMBER)) - primitive_dictionary['mousebutton2'] = self._prim_mouse_button_bool palette.add_block('mousebutton2', style='boolean-block-style', label=_('button down'), @@ -335,10 +347,9 @@ pressed')) help_string=_('returns True if mouse button is \ pressed')) self.tw.lc.def_prim('mousebutton2', 0, - lambda self: - primitive_dictionary['mousebutton2']()) + Primitive(self.tw.get_mouse_button, + return_type=TYPE_BOOL)) - primitive_dictionary['mousex'] = self._prim_mouse_x palette.add_block('mousex', style='box-style', label=_('mouse x'), @@ -346,10 +357,10 @@ pressed')) value_block=True, help_string=_('returns mouse x coordinate')) self.tw.lc.def_prim('mousex', 0, - lambda self: - primitive_dictionary['mousex']()) + Primitive(self.tw.get_mouse_x, + return_type=TYPE_NUMBER, + call_afterwards=self.after_mouse_x)) - primitive_dictionary['mousey'] = self._prim_mouse_y palette.add_block('mousey', style='box-style', label=_('mouse y'), @@ -357,10 +368,10 @@ pressed')) value_block=True, help_string=_('returns mouse y coordinate')) self.tw.lc.def_prim('mousey', 0, - lambda self: - primitive_dictionary['mousey']()) + Primitive(self.tw.get_mouse_y, + return_type=TYPE_NUMBER, + call_afterwards=self.after_mouse_y)) - primitive_dictionary['kbinput'] = self._prim_kbinput palette.add_block('kbinput', style='basic-style-extended-vertical', label=_('query keyboard'), @@ -368,9 +379,9 @@ pressed')) help_string=_('query for keyboard input (results \ stored in keyboard block)')) self.tw.lc.def_prim('kbinput', 0, - lambda self: primitive_dictionary['kbinput']()) + Primitive(self.tw.get_keyboard_input, + call_afterwards=self.after_keypress)) - primitive_dictionary['keyboard'] = self._prim_keyboard palette.add_block('keyboard', style='box-style', label=_('keyboard'), @@ -380,9 +391,9 @@ stored in keyboard block)')) help_string=_('holds results of query-keyboard \ block as ASCII')) self.tw.lc.def_prim('keyboard', 0, - lambda self: primitive_dictionary['keyboard']()) + Primitive(self.tw.get_keyboard, + return_type=TYPE_NUMBER)) - primitive_dictionary['readpixel'] = self._prim_readpixel palette.add_block('readpixel', style='basic-style-extended-vertical', label=_('read pixel'), @@ -391,9 +402,8 @@ block as ASCII')) help_string=_('RGB color under the turtle is pushed \ to the stack')) self.tw.lc.def_prim('readpixel', 0, - lambda self: primitive_dictionary['readpixel']()) + Primitive(Turtle.read_pixel)) - primitive_dictionary['see'] = self._prim_see palette.add_block('see', style='box-style', label=_('turtle sees'), @@ -402,9 +412,10 @@ to the stack')) help_string=_('returns the color that the turtle \ "sees"')) self.tw.lc.def_prim('see', 0, - lambda self: primitive_dictionary['see']()) + Primitive(Turtle.get_color_index, + return_type=TYPE_NUMBER, + call_afterwards=self.after_see)) - primitive_dictionary['time'] = self._prim_time palette.add_block('time', style='box-style', label=_('time'), @@ -412,18 +423,33 @@ to the stack')) value_block=True, help_string=_('elapsed time (in seconds) since \ program started')) - self.tw.lc.def_prim('time', 0, - lambda self: primitive_dictionary['time']()) + self.tw.lc.def_prim( + 'time', 0, + Primitive( + Primitive.identity, + return_type=TYPE_INT, + arg_descs=[ + ConstantArg( + Primitive( + int, + arg_descs=[ConstantArg( + Primitive(Primitive.minus, + arg_descs=[ + ConstantArg(Primitive(time)), + ConstantArg(Primitive( + self.tw.lc.get_start_time))]) + )] + ))], + call_afterwards=self.after_time)) def _extras_palette(self): - debug_output('creating %s palette' % _('extras'), - self.tw.running_sugar) + palette = make_palette('extras', colors=["#FF0000", "#A00000"], help_string=_('Palette of extra options'), - position=8) + position=8, + translation=_('extras')) - primitive_dictionary['push'] = self._prim_push palette.add_block('push', style='basic-style-1arg', #TRANS: push adds a new item to the program stack @@ -432,12 +458,14 @@ program started')) logo_command='tapush', help_string=_('pushes value onto FILO (first-in \ last-out heap)')) - self.tw.lc.def_prim('push', 1, - lambda self, x: primitive_dictionary['push'](x)) + self.tw.lc.def_prim( + 'push', 1, + Primitive(self.tw.lc.heap.append, + arg_descs=[ArgSlot(TYPE_OBJECT)], + call_afterwards=self.after_push)) define_logo_function('tapush', 'to tapush :foo\nmake "taheap fput \ :foo :taheap\nend\nmake "taheap []\n') - primitive_dictionary['printheap'] = self._prim_printheap palette.add_block('printheap', style='basic-style-extended-vertical', label=_('show heap'), @@ -445,12 +473,14 @@ last-out heap)')) logo_command='taprintheap', help_string=_('shows values in FILO (first-in \ last-out heap)')) - self.tw.lc.def_prim('printheap', 0, - lambda self: primitive_dictionary['printheap']()) + self.tw.lc.def_prim( + 'printheap', 0, + Primitive(self.tw.print_, + arg_descs=[ConstantArg(Primitive(self.tw.lc.get_heap)), + ConstantArg(False)])) define_logo_function('taprintheap', 'to taprintheap \nprint :taheap\n\ end\n') - primitive_dictionary['clearheap'] = self._prim_emptyheap palette.add_block('clearheap', style='basic-style-extended-vertical', label=_('empty heap'), @@ -458,12 +488,12 @@ end\n') logo_command='taclearheap', help_string=_('emptys FILO (first-in-last-out \ heap)')) - self.tw.lc.def_prim('clearheap', 0, - lambda self: primitive_dictionary['clearheap']()) + self.tw.lc.def_prim( + 'clearheap', 0, + Primitive(self.tw.lc.reset_heap, call_afterwards=self.after_pop)) define_logo_function('taclearheap', 'to taclearheap\nmake "taheap []\n\ end\n') - primitive_dictionary['pop'] = self._prim_pop palette.add_block('pop', style='box-style', #TRANS: pop removes a new item from the program stack @@ -473,12 +503,13 @@ end\n') logo_command='tapop', help_string=_('pops value off FILO (first-in \ last-out heap)')) - self.tw.lc.def_prim('pop', 0, - lambda self: primitive_dictionary['pop']()) + self.tw.lc.def_prim( + 'pop', 0, + Primitive(self.tw.lc.heap.pop, return_type=TYPE_BOX, + call_afterwards=self.after_pop)) define_logo_function('tapop', 'to tapop\nif emptyp :taheap [stop]\n\ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n') - primitive_dictionary['isheapempty'] = self._prim_is_heap_empty palette.add_block('isheapempty', hidden=True, style='box-style', @@ -486,10 +517,15 @@ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n') prim_name='isheapempty', value_block=True, help_string=_('returns True if heap is empty')) - self.tw.lc.def_prim('isheapempty', 0, - lambda self: primitive_dictionary['isheapempty']()) + self.tw.lc.def_prim( + 'isheapempty', 0, + Primitive(int, return_type=TYPE_INT, + arg_descs=[ConstantArg( + Primitive(Primitive.not_, return_type=TYPE_BOOL, + arg_descs=[ConstantArg( + Primitive(self.tw.lc.get_heap, + return_type=TYPE_BOOL))]))])) - primitive_dictionary['saveheap'] = self._prim_save_heap palette.add_block('saveheap', style='basic-style-1arg', label=_('save heap to file'), @@ -498,9 +534,9 @@ make "tmp first :taheap\nmake "taheap butfirst :taheap\noutput :tmp\nend\n') help_string=_('saves FILO (first-in \ last-out heap) to a file')) self.tw.lc.def_prim('saveheap', 1, - lambda self, x: primitive_dictionary['saveheap'](x)) + Primitive(self.tw.lc.save_heap, + arg_descs=[ArgSlot(TYPE_STRING)])) - primitive_dictionary['loadheap'] = self._prim_load_heap palette.add_block('loadheap', style='basic-style-1arg', label=_('load heap from file'), @@ -509,20 +545,26 @@ last-out heap) to a file')) help_string=_('loads FILO (first-in \ last-out heap) from a file')) self.tw.lc.def_prim('loadheap', 1, - lambda self, x: primitive_dictionary['loadheap'](x)) + Primitive(self.tw.lc.load_heap, + arg_descs=[ArgSlot(TYPE_STRING)], + return_type=TYPE_STRING, + call_afterwards=self.after_push)) - primitive_dictionary['isheapempty2'] = self._prim_is_heap_empty_bool palette.add_block('isheapempty2', style='boolean-block-style', label=_('empty heap?'), prim_name='isheapempty2', value_block=True, help_string=_('returns True if heap is empty')) - self.tw.lc.def_prim('isheapempty2', 0, - lambda self: - primitive_dictionary['isheapempty2']()) + self.tw.lc.def_prim( + 'isheapempty2', 0, + # Python automatically converts the heap to a boolean in contexts + # where a boolean is needed + Primitive(Primitive.not_, return_type=TYPE_BOOL, + arg_descs=[ConstantArg( + Primitive(self.tw.lc.get_heap, + return_type=TYPE_BOOL))])) - primitive_dictionary['print'] = self._prim_print palette.add_block('comment', style='basic-style-1arg', label=_('comment'), @@ -530,9 +572,9 @@ last-out heap) from a file')) default=_('comment'), string_or_number=True, help_string=_('places a comment in your code')) - self.tw.lc.def_prim('comment', 1, - lambda self, x: - primitive_dictionary['print'](x, True)) + self.tw.lc.def_prim( + 'comment', 1, + Primitive(Primitive.comment, arg_descs=[ArgSlot(TYPE_STRING)])) palette.add_block('print', style='basic-style-1arg', @@ -542,27 +584,32 @@ last-out heap) from a file')) string_or_number=True, help_string=_('prints value in status block at \ bottom of the screen')) - self.tw.lc.def_prim('print', 1, - lambda self, x: - primitive_dictionary['print'](x, False)) + self.tw.lc.def_prim( + 'print', 1, + Primitive(self.tw.print_, + arg_descs=[ArgSlot(TYPE_OBJECT), ConstantArg(False)])) - primitive_dictionary['chr'] = self._prim_chr palette.add_block('chr', style='number-style-1arg', label='chr', prim_name='chr', help_string=_('Python chr operator')) - self.tw.lc.def_prim('chr', 1, - lambda self, x: primitive_dictionary['chr'](x)) + self.tw.lc.def_prim( + 'chr', 1, + Primitive(chr, return_type=TYPE_CHAR, + arg_descs=[ArgSlot(TYPE_INT)])) - primitive_dictionary['int'] = self._prim_int palette.add_block('int', style='number-style-1arg', label='int', prim_name='int', help_string=_('Python int operator')) - self.tw.lc.def_prim('int', 1, - lambda self, x: primitive_dictionary['int'](x)) + self.tw.lc.def_prim( + 'int', 1, + # leave over the actual work to the type system, and just demand + # that the argument be converted to an integer + Primitive(Primitive.identity, return_type=TYPE_INT, + arg_descs=[ArgSlot(TYPE_INT)])) palette.add_block('polar', style='basic-style-extended-vertical', @@ -572,7 +619,6 @@ bottom of the screen')) self.tw.lc.def_prim('polar', 0, lambda self: self.tw.set_polar(True)) - primitive_dictionary['myfunction'] = self._prim_myfunction palette.add_block('myfunc1arg', style='number-style-var-arg', label=[_('Python'), 'f(x)', 'x'], @@ -581,9 +627,10 @@ bottom of the screen')) string_or_number=True, help_string=_('a programmable block: used to add \ advanced single-variable math equations, e.g., sin(x)')) - self.tw.lc.def_prim('myfunction', 2, - lambda self, f, x: - primitive_dictionary['myfunction'](f, [x])) + self.tw.lc.def_prim( + 'myfunction', 2, + Primitive(self.tw.lc.prim_myfunction, return_type=TYPE_FLOAT, + arg_descs=[ArgSlot(TYPE_STRING), ArgSlot(TYPE_FLOAT)])) palette.add_block('myfunc2arg', hidden=True, @@ -595,9 +642,11 @@ advanced single-variable math equations, e.g., sin(x)')) string_or_number=True, help_string=_('a programmable block: used to add \ advanced multi-variable math equations, e.g., sqrt(x*x+y*y)')) - self.tw.lc.def_prim('myfunction2', 3, - lambda self, f, x, y: - primitive_dictionary['myfunction'](f, [x, y])) + self.tw.lc.def_prim( + 'myfunction2', 3, + Primitive(self.tw.lc.prim_myfunction, return_type=TYPE_FLOAT, + arg_descs=[ArgSlot(TYPE_STRING), ArgSlot(TYPE_FLOAT), + ArgSlot(TYPE_FLOAT)])) palette.add_block('myfunc3arg', hidden=True, @@ -609,9 +658,11 @@ advanced multi-variable math equations, e.g., sqrt(x*x+y*y)')) string_or_number=True, help_string=_('a programmable block: used to add \ advanced multi-variable math equations, e.g., sin(x+y+z)')) - self.tw.lc.def_prim('myfunction3', 4, - lambda self, f, x, y, z: - primitive_dictionary['myfunction'](f, [x, y, z])) + self.tw.lc.def_prim( + 'myfunction3', 4, + Primitive(self.tw.lc.prim_myfunction, return_type=TYPE_FLOAT, + arg_descs=[ArgSlot(TYPE_STRING), ArgSlot(TYPE_FLOAT), + ArgSlot(TYPE_FLOAT), ArgSlot(TYPE_FLOAT)])) palette.add_block('cartesian', style='basic-style-extended-vertical', @@ -621,7 +672,6 @@ advanced multi-variable math equations, e.g., sin(x+y+z)')) self.tw.lc.def_prim('cartesian', 0, lambda self: self.tw.set_cartesian(True)) - primitive_dictionary['userdefined'] = self._prim_myblock palette.add_block('userdefined', style='basic-style-var-arg', label=' ', @@ -632,8 +682,8 @@ advanced multi-variable math equations, e.g., sin(x+y+z)')) help_string=_('runs code found in the tamyblock.py \ module found in the Journal')) self.tw.lc.def_prim('userdefined', 1, - lambda self, x: - primitive_dictionary['userdefined']([x])) + Primitive(self.tw.lc.prim_myblock, + arg_descs=[ArgSlot(TYPE_OBJECT)])) BLOCKS_WITH_SKIN.append('userdefined') PYTHON_SKIN.append('userdefined') @@ -649,8 +699,9 @@ module found in the Journal')) help_string=_('runs code found in the tamyblock.py \ module found in the Journal')) self.tw.lc.def_prim('userdefined2', 2, - lambda self, x, y: - primitive_dictionary['userdefined']([x, y])) + Primitive(self.tw.lc.prim_myblock, + arg_descs=[ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT)])) BLOCKS_WITH_SKIN.append('userdefined2args') PYTHON_SKIN.append('userdefined2args') @@ -666,15 +717,16 @@ module found in the Journal')) help_string=_('runs code found in the tamyblock.py \ module found in the Journal')) self.tw.lc.def_prim('userdefined3', 3, - lambda self, x, y, z: - primitive_dictionary['userdefined']([x, y, z])) + Primitive(self.tw.lc.prim_myblock, + arg_descs=[ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT)])) BLOCKS_WITH_SKIN.append('userdefined3args') PYTHON_SKIN.append('userdefined3args') MEDIA_SHAPES.append('pythonsmall') MEDIA_SHAPES.append('pythonoff') MEDIA_SHAPES.append('pythonon') - primitive_dictionary['loadblock'] = self._prim_load_block palette.add_block('loadblock', style='basic-style-var-arg', label=_('load'), @@ -682,8 +734,9 @@ module found in the Journal')) default=_('forward'), help_string=_('loads a block')) self.tw.lc.def_prim('loadblock', 1, - lambda self, x: - primitive_dictionary['loadblock'](x)) + Primitive(self.tw.prim_load_block, + export_me=False, + arg_descs=[ArgSlot(TYPE_STRING)])) palette.add_block('loadblock2arg', style='basic-style-var-arg', @@ -694,8 +747,10 @@ module found in the Journal')) default=[_('forward'), 100], help_string=_('loads a block')) self.tw.lc.def_prim('loadblock2', 2, - lambda self, x, y: - primitive_dictionary['loadblock']([x, y])) + Primitive(self.tw.prim_load_block, + export_me=False, + arg_descs=[ArgSlot(TYPE_STRING), + ArgSlot(TYPE_OBJECT)])) palette.add_block('loadblock3arg', style='basic-style-var-arg', @@ -706,10 +761,12 @@ module found in the Journal')) default=[_('setxy'), 0, 0], help_string=_('loads a block')) self.tw.lc.def_prim('loadblock3', 3, - lambda self, x, y, z: - primitive_dictionary['loadblock']([x, y, z])) + Primitive(self.tw.prim_load_block, + export_me=False, + arg_descs=[ArgSlot(TYPE_STRING), + ArgSlot(TYPE_OBJECT), + ArgSlot(TYPE_OBJECT)])) - primitive_dictionary['loadpalette'] = self._prim_load_palette palette.add_block('loadpalette', style='basic-style-1arg', string_or_number=True, @@ -718,8 +775,9 @@ module found in the Journal')) default=_('turtle'), help_string=_('selects a palette')) self.tw.lc.def_prim('loadpalette', 1, - lambda self, x: - primitive_dictionary['loadpalette'](x)) + Primitive(self.tw.prim_load_palette, + export_me=False, + arg_descs=[ArgSlot(TYPE_STRING)])) palette.add_block('addturtle', style='basic-style-1arg', @@ -729,52 +787,56 @@ module found in the Journal')) string_or_number=True, help_string=_('chooses which turtle to command')) self.tw.lc.def_prim('addturtle', 1, - lambda self, x: - self.tw.turtles.set_turtle(x)) + Primitive(self.tw.lc.prim_turtle, + arg_descs=[ArgSlot(TYPE_STRING)])) - primitive_dictionary['turtlex'] = self._prim_turtle_x palette.add_block('turtlex', style='number-style-1arg', label=_('turtle x'), prim_name='turtlex', default=['Yertle'], help_string=_('Returns x coordinate of turtle')) - self.tw.lc.def_prim('turtlex', 1, - lambda self, t: primitive_dictionary['turtlex'](t)) + self.tw.lc.def_prim( + 'turtlex', 1, + Primitive(self.tw.turtles.get_turtle_x, + arg_descs=[ArgSlot(TYPE_OBJECT)], + return_type=TYPE_BOX)) - primitive_dictionary['turtley'] = self._prim_turtle_y palette.add_block('turtley', style='number-style-1arg', label=_('turtle y'), prim_name='turtley', default=['Yertle'], help_string=_('Returns y coordinate of turtle')) - self.tw.lc.def_prim('turtley', 1, - lambda self, t: primitive_dictionary['turtley'](t)) + self.tw.lc.def_prim( + 'turtley', 1, + Primitive(self.tw.turtles.get_turtle_y, + arg_descs=[ArgSlot(TYPE_OBJECT)], + return_type=TYPE_BOX)) - primitive_dictionary['activeturtle'] = self._prim_active_turtle palette.add_block('activeturtle', style='box-style', - #TRANS: pop removes a new item from the program stack label=_('active turtle'), prim_name='activeturtle', value_block=True, help_string=_('the name of the active turtle')) - self.tw.lc.def_prim('activeturtle', 0, - lambda self: - primitive_dictionary['activeturtle']()) + self.tw.lc.def_prim( + 'activeturtle', 0, + Primitive(Turtle.get_name, + return_type=TYPE_BOX)) - primitive_dictionary['turtleh'] = self._prim_turtle_h palette.add_block('turtleh', style='number-style-1arg', label=_('turtle heading'), prim_name='turtleh', default=['Yertle'], help_string=_('Returns heading of turtle')) - self.tw.lc.def_prim('turtleh', 1, - lambda self, t: primitive_dictionary['turtleh'](t)) + self.tw.lc.def_prim( + 'turtleh', 1, + Primitive(self.tw.turtles.get_turtle_heading, + arg_descs=[ArgSlot(TYPE_OBJECT)], + return_type=TYPE_BOX)) - primitive_dictionary['skin'] = self._prim_reskin palette.add_block('skin', hidden=True, colors=["#FF0000", "#A00000"], @@ -783,8 +845,8 @@ module found in the Journal')) prim_name='skin', help_string=_("put a custom 'shell' on the turtle")) self.tw.lc.def_prim('skin', 1, - lambda self, x: - primitive_dictionary['skin'](x)) + Primitive(self.tw.lc.reskin, + arg_descs=[ArgSlot(TYPE_OBJECT)])) # macro palette.add_block('reskin', @@ -801,39 +863,40 @@ module found in the Journal')) help_string=_('top of a collapsed stack')) def _portfolio_palette(self): - debug_output('creating %s palette' % _('portfolio'), - self.tw.running_sugar) + palette = make_palette('portfolio', colors=["#0606FF", "#0606A0"], help_string=_('Palette of presentation \ templates'), - position=9) + position=9, + translation=_('portfolio')) - primitive_dictionary['hideblocks'] = self._prim_hideblocks palette.add_block('hideblocks', style='basic-style-extended-vertical', label=_('hide blocks'), prim_name='hideblocks', help_string=_('declutters canvas by hiding blocks')) - self.tw.lc.def_prim('hideblocks', 0, - lambda self: primitive_dictionary['hideblocks']()) + self.tw.lc.def_prim( + 'hideblocks', 0, + Primitive(self._prim_hideblocks, export_me=False)) - primitive_dictionary['showblocks'] = self._prim_showblocks palette.add_block('showblocks', style='basic-style-extended-vertical', label=_('show blocks'), prim_name='showblocks', help_string=_('restores hidden blocks')) - self.tw.lc.def_prim('showblocks', 0, - lambda self: primitive_dictionary['showblocks']()) + self.tw.lc.def_prim( + 'showblocks', 0, + Primitive(self._prim_showblocks, export_me=False)) palette.add_block('fullscreen', style='basic-style-extended-vertical', label=_('Fullscreen').lower(), prim_name='fullscreen', help_string=_('hides the Sugar toolbars')) - self.tw.lc.def_prim('fullscreen', 0, - lambda self: self.tw.set_fullscreen()) + self.tw.lc.def_prim( + 'fullscreen', 0, + Primitive(self.tw.set_fullscreen, export_me=False)) primitive_dictionary['bulletlist'] = self._prim_list palette.add_block('list', @@ -898,7 +961,10 @@ Journal objects')) prim_name='lpos', logo_command='lpos', help_string=_('xcor of left of screen')) - self.tw.lc.def_prim('lpos', 0, lambda self: CONSTANTS['leftpos']) + self.tw.lc.def_prim( + 'lpos', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('leftpos')])) palette.add_block('bottompos', style='box-style', @@ -906,7 +972,10 @@ Journal objects')) prim_name='bpos', logo_command='bpos', help_string=_('ycor of bottom of screen')) - self.tw.lc.def_prim('bpos', 0, lambda self: CONSTANTS['bottompos']) + self.tw.lc.def_prim( + 'bpos', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('bottompos')])) palette.add_block('width', style='box-style', @@ -914,7 +983,10 @@ Journal objects')) prim_name='hres', logo_command='width', help_string=_('the canvas width')) - self.tw.lc.def_prim('hres', 0, lambda self: CONSTANTS['width']) + self.tw.lc.def_prim( + 'hres', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('width')])) palette.add_block('rightpos', style='box-style', @@ -922,7 +994,10 @@ Journal objects')) prim_name='rpos', logo_command='rpos', help_string=_('xcor of right of screen')) - self.tw.lc.def_prim('rpos', 0, lambda self: CONSTANTS['rightpos']) + self.tw.lc.def_prim( + 'rpos', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('rightpos')])) palette.add_block('toppos', style='box-style', @@ -930,7 +1005,10 @@ Journal objects')) prim_name='tpos', logo_command='tpos', help_string=_('ycor of top of screen')) - self.tw.lc.def_prim('tpos', 0, lambda self: CONSTANTS['toppos']) + self.tw.lc.def_prim( + 'tpos', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('toppos')])) palette.add_block('height', style='box-style', @@ -938,7 +1016,10 @@ Journal objects')) prim_name='vres', logo_command='height', help_string=_('the canvas height')) - self.tw.lc.def_prim('vres', 0, lambda self: CONSTANTS['height']) + self.tw.lc.def_prim( + 'vres', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('height')])) palette.add_block('titlex', hidden=True, @@ -947,7 +1028,10 @@ Journal objects')) label=_('title x'), logo_command='titlex', prim_name='titlex') - self.tw.lc.def_prim('titlex', 0, lambda self: CONSTANTS['titlex']) + self.tw.lc.def_prim( + 'titlex', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('titlex')])) palette.add_block('titley', hidden=True, @@ -956,7 +1040,10 @@ Journal objects')) label=_('title y'), logo_command='titley', prim_name='titley') - self.tw.lc.def_prim('titley', 0, lambda self: CONSTANTS['titley']) + self.tw.lc.def_prim( + 'titley', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('titley')])) palette.add_block('leftx', hidden=True, @@ -965,7 +1052,10 @@ Journal objects')) label=_('left x'), prim_name='leftx', logo_command='leftx') - self.tw.lc.def_prim('leftx', 0, lambda self: CONSTANTS['leftx']) + self.tw.lc.def_prim( + 'leftx', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('leftx')])) palette.add_block('topy', hidden=True, @@ -974,7 +1064,10 @@ Journal objects')) label=_('top y'), prim_name='topy', logo_command='topy') - self.tw.lc.def_prim('topy', 0, lambda self: CONSTANTS['topy']) + self.tw.lc.def_prim( + 'topy', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('topy')])) palette.add_block('rightx', hidden=True, @@ -983,7 +1076,10 @@ Journal objects')) label=_('right x'), prim_name='rightx', logo_command='rightx') - self.tw.lc.def_prim('rightx', 0, lambda self: CONSTANTS['rightx']) + self.tw.lc.def_prim( + 'rightx', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('rightx')])) palette.add_block('bottomy', hidden=True, @@ -992,7 +1088,10 @@ Journal objects')) label=_('bottom y'), prim_name='bottomy', logo_command='bottomy') - self.tw.lc.def_prim('bottomy', 0, lambda self: CONSTANTS['bottomy']) + self.tw.lc.def_prim( + 'bottomy', 0, + Primitive(CONSTANTS.get, return_type=TYPE_INT, + arg_descs=[ConstantArg('bottomy')])) def _myblocks_palette(self): ''' User-defined macros are saved as a json-encoded file; @@ -1002,12 +1101,11 @@ Journal objects')) os.path.exists(self.tw.macros_path): files = glob.glob(os.path.join(self.tw.macros_path, '*.tb')) if len(files) > 0: - debug_output('creating %s palette' % _('my blocks'), - self.tw.running_sugar) palette = make_palette( - 'my blocks', + 'myblocks', colors=["#FFFF00", "#A0A000"], - help_string=_('Palette of user-defined operators')) + help_string=_('Palette of user-defined operators'), + translation=_('my blocks')) for tafile in files: data = data_from_file(tafile) @@ -1020,360 +1118,36 @@ Journal objects')) # Block primitives - def _prim_emptyheap(self): - """ Empty FILO """ - self.tw.lc.heap = [] - - def _prim_keyboard(self): - """ Return last character typed """ - return self.tw.lc.keyboard - - def _prim_kbinput(self): - """ Query keyboard """ - DICT = { - 'Left': 1, - 'KP_Left': 1, - 'Up': 2, - 'KP_Up': 2, - 'Right': 3, - 'KP_Right': 3, - 'Down': 4, - 'KP_Down': 4, - 'BackSpace': 8, - 'Tab': 9, - 'Return': 13, - 'Escape': 27, - 'space': 32, - ' ': 32, - 'exclam': 33, - 'quotedbl': 34, - 'numbersign': 35, - 'dollar': 36, - 'percent': 37, - 'ampersand': 38, - 'apostrophe': 39, - 'parenleft': 40, - 'parenright': 41, - 'asterisk': 42, - 'plus': 43, - 'comma': 44, - 'minus': 45, - 'period': 46, - 'slash': 47, - 'colon': 58, - 'semicolon': 59, - 'less': 60, - 'equal': 61, - 'greater': 62, - 'question': 63, - 'at': 64, - 'underscore': 95, - 'bracketleft': 91, - 'backslash': 92, - 'bracketright': 93, - 'asciicircum': 94, - 'grave': 96, - 'braceleft': 123, - 'bar': 124, - 'braceright': 125, - 'asciitilde': 126, - 'Delete': 127, - } - REVERSE_DICT = { - 1: _('left'), - 2: _('up'), - 3: _('right'), - 4: _('down'), - 8: _('backspace'), - 9: _('tab'), - # TRANS: enter is the name of the enter (or return) key - 13: _('enter'), - 27: 'esc', - # TRANS: space is the name of the space key - 32: _('space'), - 127: _('delete') - } - - if len(self.tw.keypress) == 1: - self.tw.lc.keyboard = ord(self.tw.keypress[0]) - elif self.tw.keypress in DICT: - self.tw.lc.keyboard = DICT[self.tw.keypress] - else: - self.tw.lc.keyboard = 0 + def after_keypress(self): if self.tw.lc.update_values: - if self.tw.keypress in DICT: - if DICT[self.tw.keypress] in REVERSE_DICT: + if self.tw.keypress in KEY_DICT: + if KEY_DICT[self.tw.keypress] in REVERSE_KEY_DICT: self.tw.lc.update_label_value( - 'keyboard', REVERSE_DICT[DICT[self.tw.keypress]]) + 'keyboard', REVERSE_KEY_DICT[ + KEY_DICT[self.tw.keypress]]) else: - self.tw.lc.update_label_value('keyboard', - chr(DICT[self.tw.keypress])) - elif self.tw.lc.keyboard > 0: + self.tw.lc.update_label_value( + 'keyboard', chr(KEY_DICT[self.tw.keypress])) + elif self.tw.keyboard > 0: self.tw.lc.update_label_value('keyboard', - chr(self.tw.lc.keyboard)) + chr(self.tw.keyboard)) self.tw.keypress = '' - def _prim_list(self, blklist): - """ Expandable list block """ - self._prim_showlist(blklist) - self.tw.lc.ireturn() - yield True - - def _prim_myblock(self, x): - """ Run Python code imported from Journal """ - if self.tw.lc.bindex is not None and \ - self.tw.lc.bindex in self.tw.myblock: - try: - if len(x) == 1: - myfunc_import(self, self.tw.myblock[self.tw.lc.bindex], - x[0]) - else: - myfunc_import(self, self.tw.myblock[self.tw.lc.bindex], x) - except: - raise logoerror("#syntaxerror") - - def _prim_myfunction(self, f, x): - """ Programmable block """ - for i, v in enumerate(x): - if type(v) == int: # Pass float values to Python block - x[i] = float(v) - try: - y = myfunc(f, x) - if str(y) == 'nan': - debug_output('Python function returned NAN', - self.tw.running_sugar) - self.tw.lc.stop_logo() - raise logoerror("#notanumber") - else: - return y - except ZeroDivisionError: - self.tw.lc.stop_logo() - raise logoerror("#zerodivide") - except ValueError, e: - self.tw.lc.stop_logo() - raise logoerror('#' + str(e)) - except SyntaxError, e: - self.tw.lc.stop_logo() - raise logoerror('#' + str(e)) - except NameError, e: - self.tw.lc.stop_logo() - raise logoerror('#' + str(e)) - except OverflowError: - self.tw.lc.stop_logo() - raise logoerror("#overflowerror") - except TypeError: - self.tw.lc.stop_logo() - raise logoerror("#notanumber") - - def _prim_is_heap_empty(self): - """ is FILO empty? """ - if len(self.tw.lc.heap) == 0: - return 1 - else: - return 0 - - def _prim_is_heap_empty_bool(self): - """ is FILO empty? """ - if len(self.tw.lc.heap) == 0: - return True - else: - return False - - def _prim_pop(self): - """ Pop value off of FILO """ - if len(self.tw.lc.heap) == 0: - raise logoerror("#emptyheap") - else: - if self.tw.lc.update_values: - if len(self.tw.lc.heap) == 1: - self.tw.lc.update_label_value('pop') - else: - self.tw.lc.update_label_value('pop', self.tw.lc.heap[-2]) - return self.tw.lc.heap.pop(-1) - - def _prim_print(self, n, flag): - """ Print object n """ - if flag and (self.tw.hide or self.tw.step_time == 0): - return - if type(n) == list: - self.tw.showlabel('print', n) - elif type(n) == str or type(n) == unicode: - if n in COLORDICT: - if COLORDICT[n][0] is None: - self.tw.showlabel('print', '%s %d, %s %d' % - (_('shade'), COLORDICT[n][1], - _('gray'), COLORDICT[n][2])) - else: - self.tw.showlabel('print', '%s %d, %s %d, %s %d' % - (_('color'), COLORDICT[n][0], - _('shade'), COLORDICT[n][1], - _('gray'), COLORDICT[n][2])) - elif n[0:6] == 'media_' and \ - n[6:].lower not in media_blocks_dictionary: - try: - if self.tw.running_sugar: - from sugar.datastore import datastore - try: - dsobject = datastore.get(n[6:]) - except: - debug_output("Couldn't open %s" % (n[6:]), - self.tw.running_sugar) - self.tw.showlabel('print', dsobject.metadata['title']) - dsobject.destroy() - else: - self.tw.showlabel('print', n[6:]) - except IOError: - self.tw.showlabel('print', n) + def after_pop(self, *ignored_args): + if self.tw.lc.update_values: + if not self.tw.lc.heap: + self.tw.lc.update_label_value('pop') else: - self.tw.showlabel('print', n) - elif type(n) == int: - self.tw.showlabel('print', n) - else: - self.tw.showlabel( - 'print', - str(round_int(n)).replace('.', self.tw.decimal_point)) - - def _prim_printheap(self): - """ Display contents of heap """ - heap_as_string = str(self.tw.lc.heap) - if len(heap_as_string) > 80: - self.tw.showlabel('print', str(self.tw.lc.heap)[0:79] + '…') - else: - self.tw.showlabel('print', str(self.tw.lc.heap)) - - def _prim_load_heap(self, path): - """ Load FILO from file """ - if type(path) == float: - path = '' - if self.tw.running_sugar: - # Choose a datastore object and push data to heap (Sugar only) - chooser_dialog(self.tw.parent, path, - self.tw.lc.push_file_data_to_heap) - else: - if not os.path.exists(path): - path, tw.load_save_folder = get_load_name( - '.*', self.tw.load_save_folder) - if path is None: - return - - data = data_from_file(path) - if data is not None: - for val in data: - self.tw.lc.heap.append(val) - - if len(self.tw.lc.heap) > 0: - self.tw.lc.update_label_value('pop', self.tw.lc.heap[-1]) - - def _prim_save_heap(self, path): - """ save FILO to file """ - # TODO: add GNOME save - - if self.tw.running_sugar: - from sugar import profile - from sugar.datastore import datastore - from sugar.activity import activity - - # Save JSON-encoded heap to temporary file - heap_file = os.path.join(get_path(activity, 'instance'), - str(path) + '.txt') - data_to_file(self.tw.lc.heap, heap_file) - - # Create a datastore object - dsobject = datastore.create() - - # Write any metadata (specifically set the title of the file - # and specify that this is a plain text file). - dsobject.metadata['title'] = str(path) - dsobject.metadata['icon-color'] = profile.get_color().to_string() - dsobject.metadata['mime_type'] = 'text/plain' - dsobject.set_file_path(heap_file) - datastore.write(dsobject) - dsobject.destroy() - else: - heap_file = path - data_to_file(self.tw.lc.heap, heap_file) + self.tw.lc.update_label_value('pop', self.tw.lc.heap[-1]) - def _prim_push(self, val): - """ Push value onto FILO """ - self.tw.lc.heap.append(val) + def after_push(self, *ignored_args): if self.tw.lc.update_values: - self.tw.lc.update_label_value('pop', val) - - def _prim_readpixel(self): - """ Read r, g, b, a from the canvas and push b, g, r to the stack """ - r, g, b, a = self.tw.turtles.get_active_turtle().get_pixel() - self.tw.lc.heap.append(b) - self.tw.lc.heap.append(g) - self.tw.lc.heap.append(r) - - def _prim_active_turtle(self): - return(self.tw.turtles.get_active_turtle().get_name()) - - def _prim_reskin(self, media): - """ Reskin the turtle with an image from a file """ - scale = int(ICON_SIZE * float(self.tw.lc.scale) / DEFAULT_SCALE) - if scale < 1: - return - self.tw.lc.filepath = None - dsobject = None - if os.path.exists(media[6:]): # is it a path? - self.tw.lc.filepath = media[6:] - elif self.tw.running_sugar: # is it a datastore object? - from sugar.datastore import datastore - try: - dsobject = datastore.get(media[6:]) - except: - debug_output("Couldn't open skin %s" % (media[6:]), - self.tw.running_sugar) - if dsobject is not None: - self.tw.lc.filepath = dsobject.file_path - if self.tw.lc.filepath is None: - self.tw.showlabel('nojournal', self.tw.lc.filepath) - return - pixbuf = None - try: - pixbuf = gtk.gdk.pixbuf_new_from_file_at_size(self.tw.lc.filepath, - scale, scale) - except: - self.tw.showlabel('nojournal', self.tw.lc.filepath) - debug_output("Couldn't open skin %s" % (self.tw.lc.filepath), - self.tw.running_sugar) - if pixbuf is not None: - self.tw.turtles.get_active_turtle().set_shapes([pixbuf]) - pen_state = self.tw.turtles.get_active_turtle().get_pen_state() - if pen_state: - self.tw.turtles.get_active_turtle().set_pen_state(False) - self.tw.turtles.get_active_turtle().forward(0) - if pen_state: - self.tw.turtles.get_active_turtle().set_pen_state(True) - - if self.tw.sharing(): - if self.tw.running_sugar: - tmp_path = get_path(self.tw.activity, 'instance') + if not self.tw.lc.heap: + self.tw.lc.update_label_value('pop') else: - tmp_path = '/tmp' - tmp_file = os.path.join(get_path(self.tw.activity, 'instance'), - 'tmpfile.png') - pixbuf.save(tmp_file, 'png', {'quality': '100'}) - data = image_to_base64(tmp_file, tmp_path) - height = pixbuf.get_height() - width = pixbuf.get_width() - event = 'R|%s' % (data_to_string([self.tw.nick, - [round_int(width), - round_int(height), - data]])) - gobject.idle_add(self.tw.send_event, event) - os.remove(tmp_file) - - def _prim_save_picture(self, name): - """ Save canvas to file as PNG """ - self.tw.save_as_image(name) - - def _prim_save_svg(self, name): - """ Save SVG to file """ - self.tw.save_as_image(name, svg=True) - - def _prim_speak(self, text): + self.tw.lc.update_label_value('pop', self.tw.lc.heap[-1]) + + def prim_speak(self, text): """ Speak text """ if type(text) == float and int(text) == text: text = int(text) @@ -1393,7 +1167,7 @@ Journal objects')) language_option, text])) self.tw.send_event(event) - def _prim_sinewave(self, pitch, amplitude, duration): + def prim_sinewave(self, pitch, amplitude, duration): """ Create a Csound score to play a sine wave. """ self.orchlines = [] self.scorelines = [] @@ -1467,139 +1241,34 @@ Journal objects')) csd.write("\n") csd.close() - def _prim_mouse_x(self): - """ Return mouse x coordinate """ - mousex = int(self.tw.mouse_x - (self.tw.canvas.width / 2)) + def after_mouse_x(self): + """ Show mouse x coordinate """ if self.tw.lc.update_values: - self.tw.lc.update_label_value('mousex', mousex) - return mousex + self.tw.lc.update_label_value('mousex', self.tw.get_mouse_x()) - def _prim_mouse_y(self): - """ Return mouse y coordinate """ - mousey = int((self.tw.canvas.height / 2) - self.tw.mouse_y) + def after_mouse_y(self): + """ Show mouse y coordinate """ if self.tw.lc.update_values: - self.tw.lc.update_label_value('mousey', mousey) - return mousey + self.tw.lc.update_label_value('mousey', self.tw.get_mouse_y()) - def _prim_mouse_button(self): - """ Return 1 if mouse button is pressed """ - if self.tw.mouse_flag == 1: - return 1 - else: - return 0 - - def _prim_mouse_button_bool(self): - """ Return True if mouse button is pressed """ - if self.tw.mouse_flag == 1: - return True - else: - return False - - def _prim_see(self): - """ Read r, g, b from the canvas and return a corresponding palette - color """ - r, g, b, a = self.tw.turtles.get_active_turtle().get_pixel() - color_index = self.tw.canvas.get_color_index(r, g, b) + def after_see(self): + """ Show color under turtle """ if self.tw.lc.update_values: - self.tw.lc.update_label_value('see', color_index) - return color_index + self.tw.lc.update_label_value( + 'see', + self.tw.turtles.get_active_turtle().get_color_index()) - def _prim_setscale(self, scale): - """ Set the scale used by the show block """ - self.tw.lc.scale = scale - if self.tw.lc.update_values: - self.tw.lc.update_label_value('scale', scale) - - def _prim_show(self, string, center=False): - """ Show is the general-purpose media-rendering block. """ - if type(string) == str or type(string) == unicode: - if string in ['media_', 'descr_', 'audio_', 'video_', - 'media_None', 'descr_None', 'audio_None', - 'video_None']: - pass - elif string[0:6] in ['media_', 'descr_', 'audio_', 'video_']: - self.tw.lc.filepath = None - self.tw.lc.pixbuf = None # Camera writes directly to pixbuf - self.tw.lc.dsobject = None - if string[6:].lower() in media_blocks_dictionary: - media_blocks_dictionary[string[6:].lower()]() - elif os.path.exists(string[6:]): # is it a path? - self.tw.lc.filepath = string[6:] - elif self.tw.running_sugar: # is it a datastore object? - from sugar.datastore import datastore - try: - self.tw.lc.dsobject = datastore.get(string[6:]) - except: - debug_output("Couldn't find dsobject %s" % - (string[6:]), self.tw.running_sugar) - if self.tw.lc.dsobject is not None: - self.tw.lc.filepath = self.tw.lc.dsobject.file_path - if self.tw.lc.pixbuf is not None: - self.tw.lc.insert_image(center=center, pixbuf=True) - elif self.tw.lc.filepath is None: - if self.tw.lc.dsobject is not None: - self.tw.showlabel( - 'nojournal', - self.tw.lc.dsobject.metadata['title']) - else: - self.tw.showlabel('nojournal', string[6:]) - debug_output("Couldn't open %s" % (string[6:]), - self.tw.running_sugar) - elif string[0:6] == 'media_': - self.tw.lc.insert_image(center=center) - elif string[0:6] == 'descr_': - mimetype = None - if self.tw.lc.dsobject is not None and \ - 'mime_type' in self.tw.lc.dsobject.metadata: - mimetype = self.tw.lc.dsobject.metadata['mime_type'] - description = None - if self.tw.lc.dsobject is not None and \ - 'description' in self.tw.lc.dsobject.metadata: - description = self.tw.lc.dsobject.metadata[ - 'description'] - self.tw.lc.insert_desc(mimetype, description) - elif string[0:6] == 'audio_': - self.tw.lc.play_sound() - elif string[0:6] == 'video_': - self.tw.lc.play_video() - if self.tw.lc.dsobject is not None: - self.tw.lc.dsobject.destroy() - else: # assume it is text to display - x, y = self.tw.lc.x2tx(), self.tw.lc.y2ty() - if center: - y -= self.tw.canvas.textsize - self.tw.turtles.get_active_turtle().draw_text(string, x, y, - int(self.tw.canvas.textsize * - self.tw.lc.scale / 100.), - self.tw.canvas.width - x) - elif type(string) == float or type(string) == int: - string = round_int(string) - x, y = self.tw.lc.x2tx(), self.tw.lc.y2ty() - if center: - y -= self.tw.canvas.textsize - self.tw.turtles.get_active_turtle().draw_text(string, x, y, - int(self.tw.canvas.textsize * - self.tw.lc.scale / 100.), - self.tw.canvas.width - x) - - def _prim_showlist(self, sarray): - """ Display list of media objects """ - x = (self.tw.turtles.get_active_turtle().get_xy()[0] / - self.tw.coord_scale) - y = (self.tw.turtles.get_active_turtle().get_xy()[1] / - self.tw.coord_scale) - for s in sarray: - self.tw.turtles.get_active_turtle().set_xy(x, y, pendown=False) - self._prim_show(s) - y -= int(self.tw.canvas.textsize * self.tw.lead) - - def _prim_time(self): - """ Number of seconds since program execution has started or - clean (prim_clear) block encountered """ - elapsed_time = int(time() - self.tw.lc.start_time) + def _prim_list(self, blklist): + """ Expandable list block """ + self.tw.lc.showlist(blklist) + self.tw.lc.ireturn() + yield True + + def after_time(self, elapsed_time): + """ Update the label of the 'time' block after computing the new + value. """ if self.tw.lc.update_values: self.tw.lc.update_label_value('time', elapsed_time) - return elapsed_time def _prim_hideblocks(self): """ hide blocks and show showblocks button """ @@ -1619,137 +1288,8 @@ Journal objects')) self.tw.activity.stop_turtle_button.set_icon("stopiton") self.tw.activity.stop_turtle_button.set_tooltip(_('Stop turtle')) - def _prim_chr(self, x): - """ Chr conversion """ - try: - return chr(int(x)) - except ValueError: - self.tw.lc.stop_logo() - raise logoerror("#notanumber") - - def _prim_int(self, x): - """ Int conversion """ - try: - return int(x) - except ValueError: - self.tw.lc.stop_logo() - raise logoerror("#notanumber") - - def _prim_turtle_x(self, t): - """ Return x coordinate of turtle t """ - return self.tw.turtles.get_turtle_x(t) - - def _prim_turtle_y(self, t): - """ Return y coordinate of turtle t """ - return self.tw.turtles.get_turtle_y(t) - - def _prim_turtle_h(self, t): - """ Return heading of turtle t """ - return self.tw.turtles.get_turtle_heading(t) - - def _prim_clamp(self, blklist): - """ Run clamp blklist """ - self.tw.lc.icall(self.tw.lc.evline, blklist[:]) - yield True - self.tw.lc.procstop = False - self.tw.lc.ireturn() - yield True - - def _prim_load_block(self, blkname): - ''' Load a block on to the canvas ''' - # Place the block at the active turtle (x, y) and move the turtle - # into position to place the next block in the stack. - # TODO: Add expandable argument - pos = self.tw.turtles.get_active_turtle().get_xy() - if isinstance(blkname, list): - name = blkname[0] - if len(blkname) > 1: - value = blkname[1:] - dy = int(self._find_block(name, pos[0], pos[1], value)) - else: - dy = int(self._find_block(name, pos[0], pos[1])) - else: - name = blkname - if name == 'delete': - for blk in self.tw.just_blocks(): - if blk.status == 'load block': - blk.type = 'trash' - blk.spr.hide() - dy = 0 - else: - dy = int(self._find_block(name, pos[0], pos[1])) - - # Reposition turtle to end of flow - pos = self.tw.turtles.get_active_turtle().get_xy() - pos[1] -= dy - self.tw.turtles.get_active_turtle().move_turtle(pos) - - def _make_block(self, name, x, y, defaults): - if defaults is None: - self.tw._new_block(name, x, y, defaults) - else: - for i, v in enumerate(defaults): - if type(v) == float and int(v) == v: - defaults[i] = int(v) - self.tw._new_block(name, x, y, defaults) - - # Find the block we just created and attach it to a stack. - self.tw.drag_group = None - spr = self.tw.sprite_list.find_sprite((x, y)) - if spr is not None: - blk = self.tw.block_list.spr_to_block(spr) - if blk is not None: - self.tw.drag_group = find_group(blk) - for b in self.tw.drag_group: - b.status = 'load block' - self.tw._snap_to_dock() - - # Disassociate new block from mouse. - self.tw.drag_group = None - return blk.docks[-1][3] - - def _find_block(self, blkname, x, y, defaults=None): - """ Create a new block. It is a bit more work than just calling - _new_block(). We need to: - (1) translate the label name into the internal block name; - (2) 'dock' the block onto a stack where appropriate; and - (3) disassociate the new block from the mouse. """ - x, y = self.tw.turtles.turtle_to_screen_coordinates((x, y)) - for name in block_names: - # Translate label name into block/prim name. - if blkname in block_names[name]: # block label is an array - # print 'found a match', blkname, name, block_names[name] - if name in content_blocks or \ - (name in block_primitives and - block_primitives[name] == name): - # print '_make_block', blkname, name - return self._make_block(name, x, y, defaults) - elif blkname in block_names: - # print '_make_block', blkname - return self._make_block(blkname, x, y, defaults) - for name in special_names: - # Translate label name into block/prim name. - if blkname in special_names[name]: - return self._make_block(name, x, y, defaults) - # Check for a macro - if blkname in MACROS: - self.tw.new_macro(blkname, x, y) - return 0 # Fix me: calculate flow position - # Block not found - raise logoerror("#syntaxerror") - return -1 - - def _prim_load_palette(self, arg): - ''' Select a palette ''' - if type(arg) in [int, float]: - if int(arg) < 0 or int(arg) > len(palette_names): - raise logoerror("#syntaxerror") - else: - self.tw.show_toolbar_palette(int(arg)) - else: - if type(arg) == unicode: - arg = arg.encode('utf-8') - if arg in palette_names or arg in palette_i18n_names: - self.tw.show_toolbar_palette(palette_name_to_index(arg)) - else: - raise logoerror("#syntaxerror") + def after_set(self, name, value=None): + ''' Update the associated value blocks ''' + if value is not None: + if self.tw.lc.update_values: + self.tw.lc.update_label_value(name, value) -- cgit v0.9.1