Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter.bender@gmail.com>2012-04-27 23:10:00 (GMT)
committer Walter Bender <walter.bender@gmail.com>2012-04-27 23:10:00 (GMT)
commit2244bb4d29527fd6937373f4f040301b6b423469 (patch)
treea0cabb9cd8efabc938e4567ffebd25bc7a55a39c
parenta57abdea9a51ed7079437796c012702b529ba095 (diff)
refactoring to address OOM issues
-rw-r--r--AbacusActivity.py235
-rw-r--r--abacus_window.py684
2 files changed, 542 insertions, 377 deletions
diff --git a/AbacusActivity.py b/AbacusActivity.py
index 068f6ec..bc3beb6 100644
--- a/AbacusActivity.py
+++ b/AbacusActivity.py
@@ -13,35 +13,48 @@
from gi.repository import Gtk
from gi.repository import Gdk
+from gi.repository import GObject
+from gi.repository import Pango
from sugar3.activity import activity
from sugar3 import profile
-try: # 0.86+ toolbar widgets
- from sugar3.graphics.toolbarbox import ToolbarBox
- HAS_TOOLBARBOX = True
-except ImportError:
- HAS_TOOLBARBOX = False
-if HAS_TOOLBARBOX:
- from sugar3.activity.widgets import ActivityToolbarButton
- from sugar3.activity.widgets import StopButton
- from sugar3.graphics.toolbarbox import ToolbarButton
+from sugar3.graphics.toolbarbox import ToolbarBox
+from sugar3.activity.widgets import ActivityToolbarButton
+from sugar3.activity.widgets import StopButton
+from sugar3.graphics.toolbarbox import ToolbarButton
+from sugar3.graphics.alert import NotifyAlert
from gettext import gettext as _
import logging
_logger = logging.getLogger('abacus-activity')
-from abacus_window import Abacus
+from abacus_window import Abacus, Custom
from toolbar_utils import separator_factory, radio_factory, label_factory, \
button_factory, spin_factory
+NAMES = {'suanpan': _('Suanpan'),
+ 'soroban': _('Soroban'),
+ 'decimal': _('Decimal'),
+ 'nepohualtzintzin': _('Nepohualtzintzin'),
+ 'hexadecimal': _('Hexadecimal'),
+ 'binary': _('Binary'),
+ 'schety': _('Schety'),
+ 'fraction': _('Fraction'),
+ 'caacupe': _('Caacupé'),
+ 'cuisenaire': _('Rods'),
+ 'custom': _('Custom')
+ }
+
+
class AbacusActivity(activity.Activity):
def __init__(self, handle):
''' Initiate activity. '''
super(AbacusActivity, self).__init__(handle)
+ self._setting_up = True
self.bead_colors = profile.get_color().to_string().split(',')
# no sharing
@@ -51,128 +64,116 @@ class AbacusActivity(activity.Activity):
custom_toolbar = Gtk.Toolbar()
edit_toolbar = Gtk.Toolbar()
- if HAS_TOOLBARBOX:
- # Use 0.86 toolbar design
- toolbox = ToolbarBox()
-
- activity_button = ActivityToolbarButton(self)
- toolbox.toolbar.insert(activity_button, 0)
- activity_button.show()
-
- edit_toolbar_button = ToolbarButton(label=_('Edit'),
- page=edit_toolbar,
- icon_name='toolbar-edit')
- edit_toolbar_button.show()
- toolbox.toolbar.insert(edit_toolbar_button, -1)
- edit_toolbar_button.show()
-
- abacus_toolbar_button = ToolbarButton(
- page=abacus_toolbar,
- icon_name='abacus-list')
- abacus_toolbar.show()
- toolbox.toolbar.insert(abacus_toolbar_button, -1)
- abacus_toolbar_button.show()
+ toolbox = ToolbarBox()
- custom_toolbar_button = ToolbarButton(
- page=custom_toolbar,
- icon_name='view-source')
- custom_toolbar.show()
- toolbox.toolbar.insert(custom_toolbar_button, -1)
- custom_toolbar_button.show()
+ activity_button = ActivityToolbarButton(self)
+ toolbox.toolbar.insert(activity_button, 0)
+ activity_button.show()
- separator_factory(toolbox.toolbar, False, True)
+ edit_toolbar_button = ToolbarButton(label=_('Edit'),
+ page=edit_toolbar,
+ icon_name='toolbar-edit')
+ edit_toolbar_button.show()
+ toolbox.toolbar.insert(edit_toolbar_button, -1)
+ edit_toolbar_button.show()
- button_factory('edit-delete', toolbox.toolbar,
- self._reset_cb, tooltip=_('Reset'))
+ abacus_toolbar_button = ToolbarButton(
+ page=abacus_toolbar,
+ icon_name='abacus-list')
+ abacus_toolbar.show()
+ toolbox.toolbar.insert(abacus_toolbar_button, -1)
+ abacus_toolbar_button.show()
- separator_factory(toolbox.toolbar, True, False)
+ custom_toolbar_button = ToolbarButton(
+ page=custom_toolbar,
+ icon_name='view-source')
+ custom_toolbar.show()
+ toolbox.toolbar.insert(custom_toolbar_button, -1)
+ custom_toolbar_button.show()
- stop_button = StopButton(self)
- stop_button.props.accelerator = _('<Ctrl>Q')
- toolbox.toolbar.insert(stop_button, -1)
- stop_button.show()
+ separator_factory(toolbox.toolbar, False, True)
- self.set_toolbar_box(toolbox)
- toolbox.show()
+ button_factory('edit-delete', toolbox.toolbar,
+ self._reset_cb, tooltip=_('Reset'))
- else:
- # Use pre-0.86 toolbar design
- toolbox = activity.ActivityToolbox(self)
- self.set_toolbox(toolbox)
-
- toolbox.add_toolbar(_('Project'), abacus_toolbar)
- toolbox.add_toolbar(_('Custom'), custom_toolbar)
- toolbox.add_toolbar(_('Edit'), edit_toolbar)
+ separator_factory(toolbox.toolbar, False, True)
- button_factory('edit-delete', edit_toolbar,
- self._reset_cb, tooltip=_('Reset'))
+ self._label = label_factory(NAMES['suanpan'], toolbox.toolbar)
+ '''
+ # FIXME: Temporary fix to style problem
+ attr = Pango.AttrList()
+ # fg_color = Pango.AttrForeground(65535, 65535, 65535, 0, -1)
+ fg_color = Pango.pango_attr_foreground_new(65535, 65535, 65535)
+ attr.insert(fg_color)
+ self._label.set_attributes(attr)
+ '''
- separator_factory(edit_toolbar, False, True)
+ separator_factory(toolbox.toolbar, True, False)
- toolbox.set_current_toolbar(1)
+ stop_button = StopButton(self)
+ stop_button.props.accelerator = _('<Ctrl>Q')
+ toolbox.toolbar.insert(stop_button, -1)
+ stop_button.show()
- # no sharing
- if hasattr(toolbox, 'share'):
- toolbox.share.hide()
- elif hasattr(toolbox, 'props'):
- toolbox.props.visible = False
+ self.set_toolbar_box(toolbox)
+ toolbox.show()
# TRANS: simple decimal abacus
self.decimal = radio_factory('decimal', abacus_toolbar,
self._radio_cb, cb_arg='decimal',
- tooltip=_('Decimal'),
+ tooltip=NAMES['decimal'],
group=None)
# TRANS: http://en.wikipedia.org/wiki/Soroban (Japanese abacus)
self.japanese = radio_factory('soroban', abacus_toolbar,
- self._radio_cb, cb_arg='japanese',
+ self._radio_cb, cb_arg='soroban',
tooltip=_('Soroban'),
group=self.decimal)
# TRANS: http://en.wikipedia.org/wiki/Suanpan (Chinese abacus)
self.chinese = radio_factory('suanpan', abacus_toolbar,
- self._radio_cb, cb_arg='chinese',
- tooltip=_('Suanpan'),
+ self._radio_cb, cb_arg='suanpan',
+ tooltip=NAMES['suanpan'],
group=self.decimal)
separator_factory(abacus_toolbar)
# TRANS: http://en.wikipedia.org/wiki/Abacus#Native_American_abaci
self.mayan = radio_factory('nepohualtzintzin', abacus_toolbar,
- self._radio_cb, cb_arg='mayan',
- tooltip=_('Nepohualtzintzin'),
+ self._radio_cb, cb_arg='nepohualtzintzin',
+ tooltip=NAMES['nepohualtzintzin'],
group=self.decimal)
# TRANS: hexidecimal abacus
self.hex = radio_factory('hexadecimal', abacus_toolbar,
- self._radio_cb, cb_arg='hex',
- tooltip=_('Hexadecimal'),
+ self._radio_cb, cb_arg='hexadecimal',
+ tooltip=NAMES['hexadecimal'],
group=self.decimal)
# TRANS: binary abacus
self.binary = radio_factory('binary', abacus_toolbar,
self._radio_cb, cb_arg='binary',
- tooltip=_('Binary'),
+ tooltip=NAMES['binary'],
group=self.decimal)
separator_factory(abacus_toolbar)
# TRANS: http://en.wikipedia.org/wiki/Abacus#Russian_abacus
self.russian = radio_factory('schety', abacus_toolbar,
- self._radio_cb, cb_arg='russian',
- tooltip=_('Schety'),
+ self._radio_cb, cb_arg='schety',
+ tooltip=NAMES['schety'],
group=self.decimal)
# TRANS: abacus for adding fractions
self.fraction = radio_factory('fraction', abacus_toolbar,
self._radio_cb, cb_arg='fraction',
- tooltip=_('Fraction'),
+ tooltip=NAMES['fraction'],
group=self.decimal)
# TRANS: Abacus invented by teachers in Caacupé, Paraguay
self.caacupe = radio_factory('caacupe', abacus_toolbar,
self._radio_cb, cb_arg='caacupe',
- tooltip=_('Caacupé'),
+ tooltip=NAMES['caacupe'],
group=self.decimal)
separator_factory(abacus_toolbar)
@@ -181,14 +182,15 @@ class AbacusActivity(activity.Activity):
self.cuisenaire = radio_factory('cuisenaire', abacus_toolbar,
self._radio_cb,
cb_arg='cuisenaire',
- tooltip=_('Rods'), group=self.decimal)
+ tooltip=NAMES['cuisenaire'],
+ group=self.decimal)
separator_factory(abacus_toolbar)
self.custom = radio_factory('custom', abacus_toolbar,
self._radio_cb,
cb_arg='custom',
- tooltip=_('Custom'), group=self.decimal)
+ tooltip=NAMES['custom'], group=self.decimal)
# TRANS: Number of rods on the abacus
self._rods_label = label_factory(_('Rods:') + ' ', custom_toolbar)
@@ -223,11 +225,8 @@ class AbacusActivity(activity.Activity):
button_factory('edit-paste', edit_toolbar, self._paste_cb,
tooltip=_('Paste'), accelerator='<Ctrl>v')
- if HAS_TOOLBARBOX:
- # start with abacus toolbar expanded
- abacus_toolbar_button.set_expanded(True)
- else:
- self.toolbox.show()
+ # start with abacus toolbar expanded
+ abacus_toolbar_button.set_expanded(True)
self.chinese.set_active(True)
@@ -242,6 +241,8 @@ class AbacusActivity(activity.Activity):
# Initialize the canvas
self.abacus = Abacus(canvas, self)
+ self._setting_up = False
+
# Read the current mode from the Journal
if 'rods' in self.metadata:
self._rods_spin.set_value(int(self.metadata['rods']))
@@ -257,19 +258,19 @@ class AbacusActivity(activity.Activity):
# Default is Chinese
_logger.debug('restoring %s', self.metadata['abacus'])
if self.metadata['abacus'] == 'soroban':
- self._select_abacus('japanese')
+ self._select_abacus('soroban')
self.japanese.set_active(True)
elif self.metadata['abacus'] == 'schety':
- self._select_abacus('russian')
+ self._select_abacus('schety')
self.russian.set_active(True)
elif self.metadata['abacus'] == 'nepohualtzintzin':
- self._select_abacus('mayan')
+ self._select_abacus('nepohualtzintzin')
self.mayan.set_active(True)
elif self.metadata['abacus'] == 'binary':
self._select_abacus('binary')
self.binary.set_active(True)
elif self.metadata['abacus'] == 'hexadecimal':
- self._select_abacus('hex')
+ self._select_abacus('hexadecimal')
self.hex.set_active(True)
elif self.metadata['abacus'] == 'fraction':
self._select_abacus('fraction')
@@ -298,13 +299,45 @@ class AbacusActivity(activity.Activity):
self.abacus.mode.reset_abacus()
self.abacus.mode.label(self.abacus.generate_label())
+ def _notify_new_abacus(self, prompt):
+ ''' Loading a new abacus can be slooow, so alert the user. '''
+ alert = NotifyAlert(3)
+ alert.props.title = prompt
+ alert.props.msg = _('A new abacus is loading.')
+
+ # FIXME: set color of text for alert due to style bug
+ def _notification_alert_response_cb(alert, response_id, self):
+ self.remove_alert(alert)
+
+ alert.connect('response', _notification_alert_response_cb, self)
+ self.add_alert(alert)
+ alert.show()
+
def _select_abacus(self, abacus):
''' Display the selected abacus; hide the others '''
if not hasattr(self, 'abacus'):
return
- if abacus == 'custom' and self.abacus.custom is None:
+ if self._setting_up:
+ return
+ if self.abacus.mode.name == abacus:
+ return
+
+ self._notify_new_abacus(NAMES[abacus])
+ # Give the alert time to load
+ GObject.timeout_add(1000, self._switch_modes, abacus)
+
+ def _switch_modes(self, abacus):
+ # Save current value
+ value = int(float(self.abacus.mode.value()))
+ if abacus == 'custom':
self._custom_cb()
- self.abacus.select_abacus(abacus)
+ self.abacus.mode = self.abacus.custom
+ else:
+ self.abacus.select_abacus(abacus)
+ # Load saved value
+ self.abacus.mode.set_value_from_number(value)
+ self.abacus.mode.label(self.abacus.generate_label())
+ self._label.set_text(NAMES[abacus])
def _rods_spin_cb(self, button=None):
return
@@ -321,20 +354,26 @@ class AbacusActivity(activity.Activity):
def _base_spin_cb(self, button=None):
return
+
def _custom_cb(self, button=None):
''' Display the custom abacus; hide the others '''
value = float(self.abacus.mode.value(count_beads=False))
+ self.abacus.mode.hide()
if self.abacus.custom is not None:
self.abacus.custom.hide()
- self.abacus.custom = Custom(self.abacus,
- self._rods_spin.get_value_as_int(),
- self._top_spin.get_value_as_int(),
- self._bottom_spin.get_value_as_int(),
- self._value_spin.get_value_as_int(),
- self._base_spin.get_value_as_int(),
- self.bead_colors)
+ self.abacus.custom = Custom(self.abacus, self.abacus.bead_colors)
+ self.abacus.custom.set_custom_parameters(
+ rods=self._rods_spin.get_value_as_int(),
+ top=self._top_spin.get_value_as_int(),
+ bot=self._bottom_spin.get_value_as_int(),
+ factor=self._value_spin.get_value_as_int(),
+ base=self._base_spin.get_value_as_int())
+ self.abacus.custom.create()
+ self.abacus.custom.draw_rods_and_beads()
+ self.abacus.custom.show()
+ self.abacus.mode = self.abacus.custom
self.custom.set_active(True)
- self.abacus.select_abacus('custom')
+ self._label.set_text(NAMES['custom'])
def _copy_cb(self, arg=None):
''' Copy a number to the clipboard from the active abacus. '''
diff --git a/abacus_window.py b/abacus_window.py
index 83887b3..028b80f 100644
--- a/abacus_window.py
+++ b/abacus_window.py
@@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
-#Copyright (c) 2010,11 Walter Bender
+#Copyright (c) 2010-12, Walter Bender
#Copyright (c) 2010, Tuukka Hastrup
#
# This program is free software; you can redistribute it and/or modify
@@ -12,6 +12,29 @@
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
+import gi
+from gi.repository import Gtk, Gdk, GdkPixbuf
+from math import floor, ceil
+
+import locale
+
+import traceback
+import logging
+_logger = logging.getLogger('abacus-activity')
+
+try:
+ from sugar3.graphics import style
+ GRID_CELL_SIZE = style.GRID_CELL_SIZE
+except ImportError:
+ GRID_CELL_SIZE = 0
+
+from sprites import Sprites, Sprite
+
+
+MAX_RODS = 18
+MAX_TOP = 4
+MAX_BOT = 14
+MAX_BEADS = MAX_RODS * (MAX_TOP + MAX_BOT)
BEAD_WIDTH = 40
BEAD_HEIGHT = 30
BEAD_OFFSET = 10
@@ -33,24 +56,6 @@ COLORS = ('#FFFFFF', '#FF0000', '#88FF00', '#FF00FF', '#FFFF00',
LABELS = ('#000000', '#FFFFFF', '#000000', '#FFFFFF', '#000000',
'#000000', '#FFFFFF', '#FFFFFF', '#000000', '#000000')
-import gi
-from gi.repository import Gtk, Gdk, GdkPixbuf
-from math import floor, ceil
-
-import locale
-
-import traceback
-import logging
-_logger = logging.getLogger('abacus-activity')
-
-try:
- from sugar3.graphics import style
- GRID_CELL_SIZE = style.GRID_CELL_SIZE
-except ImportError:
- GRID_CELL_SIZE = 0
-
-from sprites import Sprites, Sprite
-
def dec2frac(d):
''' Convert float to its approximate fractional representation. '''
@@ -188,10 +193,22 @@ def _calc_fade(bead_color, fade_color, i, n):
class Bead():
''' The Bead class is used to define the individual beads. '''
- def __init__(self, sprite, offset, value, max_fade=MAX_FADE_LEVEL,
+ def __init__(self):
+ self.spr = None
+ self.state = 0
+ self.fade_level = 0
+ self.value = 0
+ self.offset = 0
+
+ def update(self, sprites, pixbuf, offset, value, max_fade=MAX_FADE_LEVEL,
tristate=False):
''' We store a sprite, an offset, and a value for each bead. '''
- self.spr = sprite
+ if self.spr is None:
+ self.spr = Sprite(sprites, 0, 0, pixbuf)
+ else:
+ self.spr.set_image(pixbuf)
+ self.spr.set_label('')
+ self.spr.set_label_color('black')
self.offset = offset
# Decimals will be converted to fractions;
# and we want to avoid decimal points in our whole numbers.
@@ -207,15 +224,20 @@ class Bead():
def hide(self):
''' Hide the sprite associated with the bead. '''
- self.spr.hide()
+ if self.spr is not None:
+ self.spr.hide()
def show(self):
''' Show the sprite associated with the bead. '''
- self.spr.set_layer(BEAD_LAYER)
+ if self.spr is not None:
+ self.spr.set_layer(BEAD_LAYER)
- def move(self, offset):
+ def move(self, offset, move_the_bead=True):
''' Generic move method: sets state and level. '''
- self.spr.move_relative((0, offset))
+ if self.spr is None:
+ return
+ if move_the_bead:
+ self.spr.move_relative((0, offset))
if not self.tristate:
self.state = 1 - self.state
elif self.state == 1: # moving bead back to center
@@ -248,12 +270,16 @@ class Bead():
def set_color(self, color):
''' Set the color of the bead. '''
+ if self.spr is None:
+ return
self.spr.set_image(color)
self.spr.inval()
self.show()
def set_label_color(self, color):
''' Set the label color for a bead (default is black). '''
+ if self.spr is None:
+ return
self.spr.set_label_color(color)
def get_fade_level(self):
@@ -266,6 +292,8 @@ class Bead():
def update_label(self):
''' Label active beads. '''
+ if self.spr is None:
+ return
value = self.get_value()
if self.state == 1 and value < 10000 and value > 0.05:
value = self.get_value()
@@ -286,9 +314,17 @@ class Bead():
class Rod():
''' The Rod class is used to define a rod to hold beads. '''
- def __init__(self, sprites, color, frame_height, i, x, y, scale,
- cuisenaire=False, bead_color=None):
+ def __init__(self, beads):
''' We store a sprite for each rod and allocate its beads. '''
+ self.spr = None
+ self.label = None
+ self.beads = beads
+
+ def update(self, sprites, color, frame_height, i, x, y, scale,
+ bead_count, cuisenaire=False, bead_color=None):
+ self._bead_count = bead_count
+ self.sprites = sprites
+
rod = _svg_header(10, frame_height - (FRAME_STROKE_WIDTH * 2),
scale) + \
_svg_rect(10, frame_height - (FRAME_STROKE_WIDTH * 2),
@@ -297,10 +333,13 @@ class Rod():
self.index = i
self.scale = scale
- self.sprites = sprites
- self.spr = Sprite(sprites, x, y, _svg_str_to_pixbuf(rod))
+ if self.spr is None:
+ self.spr = Sprite(sprites, x, y, _svg_str_to_pixbuf(rod))
+ else:
+ self.spr.set_image(_svg_str_to_pixbuf(rod))
+ self.spr.move((x, y))
+
self.spr.type = 'frame'
- self.beads = []
self.lozenge = False
self.white_beads = []
self.color_beads = []
@@ -337,15 +376,18 @@ class Rod():
bo = (BEAD_WIDTH - BEAD_OFFSET) * self.scale / 2
ro = (BEAD_WIDTH + 5) * self.scale / 2
- self.label = Sprite(self.sprites, x - bo, y + self.spr.rect[3],
- _svg_str_to_pixbuf(
- _svg_header(BEAD_WIDTH, BEAD_HEIGHT, self.scale,
- stretch=1.0) + \
- _svg_rect(BEAD_WIDTH, BEAD_HEIGHT, 0, 0, 0, 0,
- 'none', 'none') + \
- _svg_footer()))
+ if self.label is None:
+ self.label = Sprite(self.sprites, x - bo, y + self.spr.rect[3],
+ _svg_str_to_pixbuf(
+ _svg_header(BEAD_WIDTH, BEAD_HEIGHT, self.scale,
+ stretch=1.0) + \
+ _svg_rect(BEAD_WIDTH, BEAD_HEIGHT, 0, 0, 0, 0,
+ 'none', 'none') + \
+ _svg_footer()))
+ else:
+ self.label.move((x - bo, y + self.spr.rect[3]))
self.label.type = 'frame'
- self.label.set_label_color('#FFFFFF')
+ self.label.set_label_color('white')
self.label.set_layer(MARK_LAYER)
def allocate_beads(self, top_beads, bot_beads, top_factor,
@@ -388,21 +430,23 @@ class Rod():
else:
max_fade_level = 0
- for b in range(top_beads):
- self.beads.append(Bead(Sprite(
- self.sprites, x - ro + bo, y + b * BEAD_HEIGHT * self.scale,
- bead_color), bead_displacement,
- top_factor * bead_value, max_fade=max_fade_level))
- for b in range(bot_beads):
+ for i in range(top_beads):
+ self.beads[i + self._bead_count].update(
+ self.sprites, bead_color, bead_displacement,
+ top_factor * bead_value, max_fade=max_fade_level)
+ self.beads[i + self._bead_count].spr.move(
+ (x - ro + bo, y + i * BEAD_HEIGHT * self.scale))
+
+ for i in range(bot_beads):
displacement = bead_displacement
if top_beads > 0:
- yy = y + (top_beads + 5 + b) * BEAD_HEIGHT * self.scale
+ yy = y + (top_beads + 5 + i) * BEAD_HEIGHT * self.scale
else:
- yy = y + (2 + b) * BEAD_HEIGHT * self.scale
+ yy = y + (2 + i) * BEAD_HEIGHT * self.scale
if all_black:
bead_color = self.black_bead
elif middle_black:
- if b in middle:
+ if i in middle:
bead_color = self.black_bead
else:
bead_color = self.white_beads[0]
@@ -423,65 +467,87 @@ class Rod():
BEAD_HEIGHT * self.scale / 2
yy -= offset
displacement -= offset
- self.beads.append(Bead(Sprite(self.sprites, x - ro + bo,
- yy, bead_color), displacement,
- bead_value, tristate=tristate,
- max_fade=max_fade_level))
+ self.beads[i + self._bead_count + top_beads].update(
+ self.sprites, bead_color, displacement,
+ bead_value, tristate=tristate, max_fade=max_fade_level)
+ self.beads[i + self._bead_count + top_beads].spr.move(
+ (x - ro + bo, yy))
+
if bead_color == self.black_bead:
- self.beads[-1].set_label_color('#ffffff')
- # Lozenged-shaped beads need to be spaced out more
- if self.beads[-1].spr.rect[3] > BEAD_HEIGHT * self.scale:
- self.beads[-1].spr.move_relative((0, b * (
- self.beads[-1].spr.rect[3] - (BEAD_HEIGHT * self.scale))))
+ self.beads[i + self._bead_count + top_beads].set_label_color(
+ '#ffffff')
+ # FIXME
+ # Lozenged-shaped beads need to be spaced out more
+ if self.beads[i + self._bead_count + top_beads].spr.rect[3] > \
+ BEAD_HEIGHT * self.scale:
+ self.beads[i + self._bead_count + top_beads].spr.move_relative(
+ (0, i * (
+ self.beads[i + self._bead_count + top_beads].spr.rect[3] - \
+ (BEAD_HEIGHT * self.scale))))
+
+ # self._bead_count -= (self.top_beads + self.bot_beads)
if color:
- for bead in self.beads:
- bead.set_label_color(LABELS[self.index])
+ for i in range(self.top_beads + self.bot_beads):
+ self.beads[i + self._bead_count].set_label_color(
+ LABELS[self.index])
def hide(self):
- for bead in self.beads:
- bead.hide()
+ if self.spr is None:
+ return
+ for i in range(self.top_beads + self.bot_beads):
+ self.beads[i + self._bead_count].hide()
self.spr.hide()
self.label.hide()
def show(self):
- for bead in self.beads:
- bead.show()
+ if self.spr is None:
+ return
+ for i in range(self.top_beads + self.bot_beads):
+ self.beads[i + self._bead_count].show()
self.spr.set_layer(ROD_LAYER)
self.label.set_layer(MARK_LAYER)
def get_max_value(self):
''' Returns maximum numeric value for this rod '''
+ if self.spr is None:
+ return 0
max = 0
- for bead in self.beads:
- max += bead.value
+ for i in range(self.top_beads + self.bot_beads):
+ max += self.beads[i + self._bead_count].value
return max
def get_value(self):
+ if self.spr is None:
+ return 0
sum = 0
- for bead in self.beads:
- sum += bead.get_value()
+ for i in range(self.top_beads + self.bot_beads):
+ sum += self.beads[i + self._bead_count].get_value()
return sum
def get_bead_count(self):
''' Returns number of active bottom-bead equivalents on this rod'''
+ if self.spr is None:
+ return 0
count = 0
- for i, bead in enumerate(self.beads):
- if bead.get_state() == 1:
+ for i in range(self.top_beads + self.bot_beads):
+ if self.beads[i + self._bead_count].get_state() == 1:
if i < self.top_beads:
count += self.top_factor
else:
count += 1
- if bead.get_state() == -1:
+ if self.beads[i + self._bead_count].get_state() == -1:
count -= 1
return count
def set_number(self, number):
''' Try to set a value equal to number; return any remainder '''
+ if self.spr is None:
+ return 0
count = 0
- for i, bead in enumerate(self.beads):
- if number >= bead.value:
- number -= bead.value
+ for i in range(self.top_beads + self.bot_beads):
+ if number >= self.beads[i + self._bead_count].value:
+ number -= self.beads[i + self._bead_count].value
if i < self.top_beads:
count += self.top_factor
else:
@@ -491,6 +557,8 @@ class Rod():
def set_value(self, value):
''' Move beads to represent a numeric value '''
+ if self.spr is None:
+ return
if self.top_beads > 0:
bot = value % self.top_factor
top = (value - bot) / self.top_factor
@@ -500,10 +568,10 @@ class Rod():
self.reset()
# Set the top.
for i in range(top):
- self.beads[self.top_beads - i - 1].move_down()
+ self.beads[self._bead_count + self.top_beads - i - 1].move_down()
# Set the bottom
for i in range(bot):
- self.beads[self.top_beads + i].move_up()
+ self.beads[self._bead_count + self.top_beads + i].move_up()
if value > 0:
self.set_label(self.get_bead_count())
@@ -511,108 +579,122 @@ class Rod():
self.label.set_label('')
def reset(self):
+ if self.spr is None:
+ return
# Clear the top.
for i in range(self.top_beads):
- if self.beads[i].get_state() == 1:
+ if self.beads[i + self._bead_count].get_state() == 1:
self.beads[i].move_up()
# Clear the bottom.
for i in range(self.bot_beads):
- if self.beads[self.top_beads + i].get_state() == 1:
- self.beads[self.top_beads + i].move_down()
+ if self.beads[self.top_beads + i + self._bead_count].get_state() \
+ == 1:
+ self.beads[self.top_beads + i + self._bead_count].move_down()
# Fade beads
- for bead in self.beads:
- if bead.fade_level > 0:
- bead.fade_level = 0
- bead.set_color(self.white_beads[0])
+ for i in range(self.top_beads + self.bot_beads):
+ if self.beads[self._bead_count + i].fade_level > 0:
+ self.beads[self._bead_count + i].fade_level = 0
+ self.beads[self._bead_count + i].set_color(self.white_beads[0])
self.label.set_label('')
def fade_colors(self):
''' Reduce the saturation level of every bead. '''
+ if self.spr is None:
+ return
if self.fade:
- for bead in self.beads:
- if bead.get_fade_level() > 0:
- bead.set_color(self.white_beads[bead.get_fade_level() - 1])
- bead.set_fade_level(bead.get_fade_level() - 1)
+ for i in range(self.top_beads + self.bot_beads):
+ if self.beads[self._bead_count + i].get_fade_level() > 0:
+ self.beads[self._bead_count + i].set_color(
+ self.white_beads[self.beads[
+ self._bead_count + i].get_fade_level() - 1])
+ self.beads[self._bead_count + i].set_fade_level(
+ self.beads[self._bead_count + i].get_fade_level() - 1)
def move_bead(self, sprite, dy):
''' Move a bead (or beads) up or down a rod. '''
-
+ if self.spr is None:
+ return False
# Find the bead associated with the sprite.
i = -1
- for bead in self.beads:
- if sprite == bead.spr:
- i = self.beads.index(bead)
+ for j in range(self.top_beads + self.bot_beads):
+ if sprite == self.beads[self._bead_count + j].spr:
+ i = j
break
if i == -1:
- # _logger.debug('bead not found')
return False
+ if self.fade and self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i].set_color(self.white_beads[3])
if i < self.top_beads:
- if dy > 0 and bead.get_state() == 0:
- if self.fade and bead.max_fade_level > 0:
- bead.set_color(self.white_beads[3])
- bead.move_down()
+ if dy > 0 and self.beads[self._bead_count + i].get_state() == 0:
+ self.beads[self._bead_count + i].move_down()
# Make sure beads below this bead are also moved.
for ii in range(self.top_beads - i):
- if self.beads[i + ii].state == 0:
- if self.fade and bead.max_fade_level > 0:
- self.beads[i + ii].set_color(self.white_beads[3])
- self.beads[i + ii].move_down()
- elif dy < 0 and bead.state == 1:
- if self.fade and bead.max_fade_level > 0:
- bead.set_color(self.white_beads[3])
- bead.move_up()
+ if self.beads[self._bead_count + i + ii].state == 0:
+ if self.fade and \
+ self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i + ii].set_color(
+ self.white_beads[3])
+ self.beads[self._bead_count + i + ii].move_down()
+ elif dy < 0 and self.beads[self._bead_count + i].state == 1:
+ self.beads[self._bead_count + i].move_up()
# Make sure beads above this bead are also moved.
for ii in range(i + 1):
- if self.beads[i - ii].state == 1:
- if self.fade and bead.max_fade_level > 0:
- self.beads[i - ii].set_color(self.white_beads[3])
- self.beads[i - ii].move_up()
+ if self.beads[self._bead_count + i - ii].state == 1:
+ if self.fade and \
+ self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i - ii].set_color(
+ self.white_beads[3])
+ self.beads[self._bead_count + i - ii].move_up()
else:
- if dy < 0 and bead.state == 0:
- if self.fade and bead.max_fade_level > 0:
- bead.set_color(self.white_beads[3])
- bead.move_up()
+ if dy < 0 and self.beads[self._bead_count + i].state == 0:
+ self.beads[self._bead_count + i].move_up()
# Make sure beads above this bead are also moved.
for ii in range(i - self.top_beads + 1):
- if self.beads[i - ii].state == 0:
- if self.fade and bead.max_fade_level > 0:
- self.beads[i - ii].set_color(self.white_beads[3])
- self.beads[i - ii].move_up()
- elif dy < 0 and bead.state == -1:
- if self.fade and bead.max_fade_level > 0:
- bead.set_color(self.white_beads[3])
- bead.move_up()
+ if self.beads[self._bead_count + i - ii].state == 0:
+ if self.fade and \
+ self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i - ii].set_color(
+ self.white_beads[3])
+ self.beads[self._bead_count + i - ii].move_up()
+ elif dy < 0 and self.beads[self._bead_count + i].state == -1:
+ self.beads[self._bead_count + i].move_up()
for ii in range(i - self.top_beads + 1):
- if self.beads[i - ii].state == -1:
- if self.fade and bead.max_fade_level > 0:
- self.beads[i - ii].set_color(self.white_beads[3])
- self.beads[i - ii].move_up()
- elif dy > 0 and bead.state == 1:
- if self.fade and bead.max_fade_level > 0:
- bead.set_color(self.white_beads[3])
- bead.move_down()
+ if self.beads[self._bead_count + i - ii].state == -1:
+ if self.fade and \
+ self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i - ii].set_color(
+ self.white_beads[3])
+ self.beads[self._bead_count + i - ii].move_up()
+ elif dy > 0 and self.beads[self._bead_count + i].state == 1:
+ self.beads[self._bead_count + i].move_down()
# Make sure beads below this bead are also moved.
for ii in range(self.top_beads + self.bot_beads - i):
- if self.beads[i + ii].state == 1:
- if self.fade and bead.max_fade_level > 0:
- self.beads[i + ii].set_color(self.white_beads[3])
- self.beads[i + ii].move_down()
- elif dy > 0 and bead.state == 0 and bead.tristate:
- if self.fade and bead.max_fade_level > 0:
- bead.set_color(self.white_beads[3])
- bead.move_down()
+ if self.beads[self._bead_count + i + ii].state == 1:
+ if self.fade and \
+ self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i + ii].set_color(
+ self.white_beads[3])
+ self.beads[self._bead_count + i + ii].move_down()
+ elif dy > 0 and self.beads[self._bead_count + i].state == 0 and \
+ self.beads[self._bead_count + i].tristate:
+ self.beads[self._bead_count + i].move_down()
# Make sure beads below this bead are also moved.
for ii in range(self.top_beads + self.bot_beads - i):
- if self.beads[i + ii].state == 0:
- if self.fade and bead.max_fade_level > 0:
- self.beads[i + ii].set_color(self.white_beads[3])
- self.beads[i + ii].move_down()
+ if self.beads[self._bead_count + i + ii].state == 0:
+ if self.fade and \
+ self.beads[self._bead_count + i].max_fade_level > 0:
+ self.beads[self._bead_count + i + ii].set_color(
+ self.white_beads[3])
+ self.beads[self._bead_count + i + ii].move_down()
self.set_label(self.get_bead_count())
+
def set_label(self, n):
''' Different abaci use different labeling schemes. '''
+ if self.spr is None:
+ return
# Use hex notation on hex abacus
if self.top_beads == 1 and self.bot_beads == 7 and \
self.top_factor == 8:
@@ -622,7 +704,7 @@ class Rod():
self.label.set_label('')
else:
self.label.set_label(n)
- return True
+ return
class Abacus():
@@ -642,8 +724,6 @@ class Abacus():
self.bead_colors = parent.bead_colors
parent.show_all()
- _logger.debug('bead colors %s %s', self.bead_colors[0],
- self.bead_colors[1])
self.canvas.set_can_focus(True)
self.canvas.add_events(Gdk.EventMask.BUTTON_PRESS_MASK)
self.canvas.add_events(Gdk.EventMask.BUTTON_RELEASE_MASK)
@@ -674,72 +754,54 @@ class Abacus():
_svg_str_to_pixbuf(background_svg))
background.set_layer(1)
+ self.decimal = None
self.japanese = None
- self.russian = None
+ self.chinese = None
self.mayan = None
- self.binary = None
self.hex = None
- self.decimal = None
+ self.binary = None
+ self.russian = None
self.fraction = None
self.caacupe = None
self.cuisenaire = None
self.custom = None
+ self.mode_dict = {'decimal': [self.decimal, Decimal],
+ 'soroban': [self.japanese, Soroban],
+ 'suanpan': [self.chinese, Suanpan],
+ 'nepohualtzintzin': [self.mayan, Nepohualtzintzin],
+ 'hexadecimal': [self.hex, Hex],
+ 'binary': [self.binary, Binary],
+ 'schety': [self.russian, Schety],
+ 'fraction': [self.fraction, Fractions],
+ 'caacupe': [self.caacupe, Caacupe],
+ 'cuisenaire': [self.cuisenaire, Cuisenaire],
+ 'custom': [self.custom, Custom]
+ }
+
+ self.bead_cache = []
+ for i in range(MAX_BEADS):
+ self.bead_cache.append(Bead())
+
+ self.rod_cache = []
+ for i in range(MAX_BEADS):
+ self.rod_cache.append(Rod(self.bead_cache))
+
self.chinese = Suanpan(self, self.bead_colors)
self.mode = self.chinese
self.mode.show()
def select_abacus(self, abacus):
self.mode.hide()
- value = int(float(self.mode.value()))
- if abacus == 'chinese':
- if self.chinese is None:
- self.chinese = Suanpan(self, self.bead_colors)
- self.mode = self.chinese
- elif abacus == 'japanese':
- if self.japanese is None:
- self.japanese = Soroban(self, self.bead_colors)
- self.mode = self.japanese
- elif abacus == 'decimal':
- if self.decimal is None:
- self.decimal = Decimal(self, self.bead_colors)
- self.mode = self.decimal
- elif abacus == 'mayan':
- if self.mayan is None:
- self.mayan = Nepohualtzintzin(self, self.bead_colors)
- self.mode = self.mayan
- elif abacus == 'hex':
- if self.hex is None:
- self.hex = Hex(self, self.bead_colors)
- self.mode = self.hex
- elif abacus == 'binary':
- if self.binary is None:
- self.binary = Binary(self, self.bead_colors)
- self.mode = self.binary
- elif abacus == 'custom':
- if self.custom is None:
- self.custom = Custom(self, self.bead_colors)
- self.mode = self.custom
- elif abacus == 'russian':
- if self.russian is None:
- self.russian = Schety(self, self.bead_colors)
- self.mode = self.russian
- elif abacus == 'fraction':
- if self.fraction is None:
- self.fraction = Fractions(self, self.bead_colors)
- self.mode = self.fraction
- elif abacus == 'caacupe':
- if self.caacupe is None:
- self.caacupe = Caacupe(self, self.bead_colors)
- self.mode = self.caacupe
- elif abacus == 'cuisenaire':
- if self.cuisenaire is None:
- self.cuisenaire = Cuisenaire(self)
- self.mode = self.cuisenaire
- self.mode.set_value_from_number(value)
+
+ if self.mode_dict[abacus][0] is None:
+ self.mode_dict[abacus][0] = self.mode_dict[abacus][1](
+ self, self.bead_colors)
+ else:
+ self.mode_dict[abacus][0].draw_rods_and_beads()
+ self.mode = self.mode_dict[abacus][0]
self.mode.show()
self.mode.label(self.generate_label())
- _logger.debug('Setting mode to %s' % (self.mode.name))
def _button_press_cb(self, win, event):
''' Callback to handle the button presses '''
@@ -860,7 +922,7 @@ class Abacus():
def _destroy_cb(self, win, event):
''' Callback to handle quit '''
- Gtk.main_quit()
+ gtk.main_quit()
def generate_label(self, sum_only=False):
''' The complexity below is to make the label as simple as possible '''
@@ -941,14 +1003,14 @@ class AbacusGeneric():
self.set_parameters()
self.create()
- def set_parameters(self):
+ def set_parameters(self, rods=15, top=2, bot=5, factor=5, base=10):
''' Define the physical paramters. '''
self.name = 'suanpan'
- self.num_rods = 15
- self.bot_beads = 5
- self.top_beads = 2
- self.base = 10
- self.top_factor = 5
+ self.num_rods = rods
+ self.bot_beads = top
+ self.top_beads = bot
+ self.top_factor = factor
+ self.base = base
def create(self, dots=False):
''' Create and position the sprites that compose the abacus '''
@@ -1040,8 +1102,7 @@ class AbacusGeneric():
x += FRAME_STROKE_WIDTH * self.abacus.scale
y += FRAME_STROKE_WIDTH * self.abacus.scale
- self.rods = []
- self.beads = []
+ self.rods = self.abacus.rod_cache
self.draw_rods_and_beads(x, y)
@@ -1072,29 +1133,38 @@ class AbacusGeneric():
_svg_str_to_pixbuf(mark))
self.mark.type = 'mark'
- def draw_rods_and_beads(self, x, y):
+ def draw_rods_and_beads(self, x=None, y=None):
''' Draw the rods and beads '''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
+
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
bead_value = pow(self.base, self.num_rods - i - 1)
- self.rods.append(Rod(self.abacus.sprites,
- ROD_COLORS[i % len(ROD_COLORS)],
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- bead_color=bead_color))
- self.rods[-1].allocate_beads(self.top_beads, self.bot_beads,
+ self.rods[i].update(self.abacus.sprites,
+ ROD_COLORS[i % len(ROD_COLORS)],
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
+ self.rods[i].allocate_beads(self.top_beads, self.bot_beads,
self.top_factor,
bead_value, self.bot_beads)
def hide(self):
''' Hide the rod, beads, mark, and frame. '''
- for rod in self.rods:
- rod.hide()
+ for i in range(self.num_rods):
+ self.rods[i].hide()
self.bar.hide()
self.label_bar.hide()
self.frame.hide()
@@ -1106,8 +1176,8 @@ class AbacusGeneric():
def show(self):
''' Show the rod, beads, mark, and frame. '''
self.frame.set_layer(FRAME_LAYER)
- for rod in self.rods:
- rod.show()
+ for i in range(self.num_rods):
+ self.rods[i].show()
self.bar.set_layer(BAR_LAYER)
self.label_bar.set_layer(BAR_LAYER)
if hasattr(self, 'dots'):
@@ -1120,8 +1190,8 @@ class AbacusGeneric():
value = string.split()
# Move the beads to correspond to column values.
try:
- for i, rod in enumerate(self.rods):
- rod.set_value(int(value[i]))
+ for i in range(self.num_rods):
+ self.rods[i].set_value(int(value[i]))
except IndexError:
_logger.debug('bad saved string length %s (%d != 2 * %d)',
string, len(string), self.num_rods)
@@ -1132,45 +1202,44 @@ class AbacusGeneric():
def max_value(self):
''' Maximum value possible on abacus '''
max = 0
- for rod in self.rods:
- max += rod.get_max_value()
+ for i in range(self.num_rods):
+ max += self.rods[i].get_max_value()
return max
def set_value_from_number(self, number):
''' Set abacus to value in string '''
self.reset_abacus()
if number <= self.max_value():
- for rod in self.rods:
- number = rod.set_number(number)
+ for i in range(self.num_rods):
+ number = self.rods[i].set_number(number)
if number == 0:
break
def reset_abacus(self):
''' Reset beads to original position '''
- for rod in self.rods:
- rod.reset()
+ for i in range(self.num_rods):
+ self.rods[i].reset()
def value(self, count_beads=False):
''' Return a string representing the value of each rod. '''
-
if count_beads:
# Save the value associated with each rod as a 2-byte integer.
string = ''
value = []
- for r in range(self.num_rods + 1): # +1 for overflow
+ for i in range(self.num_rods + 1): # +1 for overflow
value.append(0)
# Tally the values on each rod.
- for r, rod in enumerate(self.rods):
- value[r + 1] = rod.get_bead_count()
+ for i in range(self.num_rods):
+ value[i + 1] = self.rods[i].get_bead_count()
# Save the value associated with each rod as a 2-byte integer.
- for j in value[1:]:
- string += '%2d ' % (j)
+ for i in value[1:]:
+ string += '%2d ' % (i)
else:
rod_sum = 0
- for rod in self.rods:
- rod_sum += rod.get_value()
+ for i in range(self.num_rods):
+ rod_sum += self.rods[i].get_value()
string = str(rod_sum)
return(string)
@@ -1184,40 +1253,47 @@ class AbacusGeneric():
def fade_colors(self):
''' Reduce the saturation level of every bead. '''
- for rod in self.rods:
- rod.fade_colors()
+ for i in range(self.num_rods):
+ self.rods[i].fade_colors()
def move_bead(self, sprite, dy):
''' Move a bead (or beads) up or down a rod. '''
self.fade_colors()
- for rod in self.rods:
- if rod.move_bead(sprite, dy):
+ for i in range(self.num_rods):
+ if self.rods[i].move_bead(sprite, dy):
break
def get_rod_values(self):
''' Return the sum of the values per rod as an array '''
v = [0] * (self.num_rods + 1)
- for r, rod in enumerate(self.rods):
- v[r + 1] = rod.get_value()
+ for i in range(self.num_rods):
+ v[i + 1] = self.rods[i].get_value()
return v[1:]
class Custom(AbacusGeneric):
''' A custom-made abacus '''
- def __init__(self, abacus, rods, top, bottom, factor, base,
- bead_colors=None):
+ def __init__(self, abacus, bead_colors=None):
''' Specify parameters that define the abacus '''
self.abacus = abacus
+ self.name = 'custom'
+ self.num_rods = 15
+ self.bot_beads = 5
+ self.top_beads = 2
+ self.top_factor = 5
+ self.base = 10
self.bead_colors = bead_colors
+
+ def set_custom_parameters(self, rods=15, top=2, bot=5, factor=5, base=10):
+ ''' Specify parameters that define the abacus '''
self.name = 'custom'
self.num_rods = rods
- self.bot_beads = bottom
+ self.bot_beads = bot
self.top_beads = top
- self.base = base
self.top_factor = factor
- self.create()
+ self.base = base
class Nepohualtzintzin(AbacusGeneric):
@@ -1279,22 +1355,31 @@ class Soroban(AbacusGeneric):
self.base = 10
self.top_factor = 5
- def draw_rods_and_beads(self, x, y):
+ def draw_rods_and_beads(self, x=None, y=None):
''' Draw the rods and beads: units offset to center'''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
+
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
bead_value = pow(self.base, int(self.num_rods / 2) - i)
- self.rods.append(Rod(self.abacus.sprites,
- ROD_COLORS[i % len(ROD_COLORS)],
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- bead_color=bead_color))
- self.rods[-1].allocate_beads(self.top_beads, self.bot_beads,
+ self.rods[i].update(self.abacus.sprites,
+ ROD_COLORS[i % len(ROD_COLORS)],
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
+ self.rods[i].allocate_beads(self.top_beads, self.bot_beads,
self.top_factor,
bead_value, self.bot_beads)
@@ -1338,21 +1423,29 @@ class Decimal(AbacusGeneric):
self.base = 10
self.top_factor = 1
- def draw_rods_and_beads(self, x, y):
+ def draw_rods_and_beads(self, x=None, y=None):
''' Draw the rods and beads: override bead color'''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
bead_value = pow(self.base, self.num_rods - i - 1)
- self.rods.append(Rod(self.abacus.sprites, '#404040',
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- bead_color=bead_color))
- self.rods[-1].allocate_beads(self.top_beads, self.bot_beads,
+ self.rods[i].update(self.abacus.sprites, '#404040',
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
+ self.rods[i].allocate_beads(self.top_beads, self.bot_beads,
self.top_factor,
bead_value, self.bot_beads,
color=True)
@@ -1401,22 +1494,30 @@ class Schety(AbacusGeneric):
self.base = 10
self.top_factor = 1
- def draw_rods_and_beads(self, x, y):
+ def draw_rods_and_beads(self, x=None, y=None):
''' Draw the rods and beads: short column for 1/4 '''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
- self.rods.append(Rod(self.abacus.sprites, '#404040',
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- bead_color=bead_color))
- self.rods[-1].allocate_beads(self.top_beads, self.bead_count[i],
+ self.rods[i].update(self.abacus.sprites, '#404040',
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
+ self.rods[i].allocate_beads(self.top_beads, self.bead_count[i],
self.top_factor, self.bead_value[i],
- self.bead_count[0], middle_black=True)
+ self.bead_count[-1], middle_black=True)
class Fractions(Schety):
@@ -1442,24 +1543,32 @@ class Fractions(Schety):
self.base = 10
self.top_factor = 1
- def draw_rods_and_beads(self, x, y):
- ''' Draw the rods and beads: short column for 1/4 '''
+ def draw_rods_and_beads(self, x=None, y=None):
+ ''' Draw the rods and beads: short columns for fractions '''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
- self.rods.append(Rod(self.abacus.sprites, '#404040',
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- bead_color=bead_color))
+ self.rods[i].update(self.abacus.sprites, '#404040',
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
if i < 6:
all_black = False
else:
all_black = True
- self.rods[-1].allocate_beads(self.top_beads, self.bead_count[i],
+ self.rods[i].allocate_beads(self.top_beads, self.bead_count[i],
self.top_factor,
self.bead_value[i],
self.bead_count[-1],
@@ -1489,24 +1598,32 @@ class Caacupe(Fractions):
self.base = 10
self.top_factor = 1
- def draw_rods_and_beads(self, x, y):
- ''' Draw the rods and beads: short column for 1/4 '''
+ def draw_rods_and_beads(self, x=None, y=None):
+ ''' Draw the rods and beads: short columns for fractions '''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
- self.rods.append(Rod(self.abacus.sprites, '#404040',
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- bead_color=bead_color))
+ self.rods[i].update(self.abacus.sprites, '#404040',
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
if i < 6:
all_black = False
else:
all_black = True
- self.rods[-1].allocate_beads(self.top_beads, self.bead_count[i],
+ self.rods[i].allocate_beads(self.top_beads, self.bead_count[i],
self.top_factor,
self.bead_value[i],
self.bead_count[-1],
@@ -1536,20 +1653,29 @@ class Cuisenaire(Caacupe):
self.base = 10
self.top_factor = 1
- def draw_rods_and_beads(self, x, y):
- ''' Draw the rods and beads: short column for 1/4 '''
+ def draw_rods_and_beads(self, x=None, y=None):
+ ''' Draw the rods and beads: short columns for fractions '''
+ if x is None:
+ x = self.rod_x
+ y = self.rod_y
+ else:
+ self.rod_x = x
+ self.rod_y = y
dx = (BEAD_WIDTH + BEAD_OFFSET) * self.abacus.scale
ro = (BEAD_WIDTH + 5) * self.abacus.scale / 2
+ bead_count = 0
for i in range(self.num_rods):
if self.bead_colors is not None:
bead_color = self.bead_colors[i % 2]
else:
bead_color = None
- self.rods.append(Rod(self.abacus.sprites, '#404040',
- self.frame_height,
- i, x + i * dx + ro, y, self.abacus.scale,
- cuisenaire=True, bead_color=bead_color))
- self.rods[-1].allocate_beads(self.top_beads, self.bead_count[i],
+ self.rods[i].update(self.abacus.sprites, '#404040',
+ self.frame_height,
+ i, x + i * dx + ro, y, self.abacus.scale,
+ bead_count, cuisenaire=True,
+ bead_color=bead_color)
+ bead_count += (self.top_beads + self.bot_beads)
+ self.rods[i].allocate_beads(self.top_beads, self.bead_count[i],
self.top_factor,
self.bead_value[i],
self.bead_count[-1],