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 self.max_participants = 1 self.sep = [] self.abacus_toolbar = Gtk.Toolbar() custom_toolbar = Gtk.Toolbar() edit_toolbar = Gtk.Toolbar() 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() self.abacus_toolbar_button = ToolbarButton( page=self.abacus_toolbar, icon_name='abacus-list') self.abacus_toolbar.show() toolbox.toolbar.insert(self.abacus_toolbar_button, -1) self.abacus_toolbar_button.show() self.custom_toolbar_button = ToolbarButton( page=custom_toolbar, icon_name='view-source') custom_toolbar.show() toolbox.toolbar.insert(self.custom_toolbar_button, -1) self.custom_toolbar_button.show() separator_factory(toolbox.toolbar, False, True) button_factory('edit-delete', toolbox.toolbar, self._reset_cb, tooltip=_('Reset')) separator_factory(toolbox.toolbar, False, True) self._label = label_factory(NAMES['suanpan'], toolbox.toolbar) separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = _('<Ctrl>Q') toolbox.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.abacus_buttons = {} # Traditional self._add_abacus_button('decimal', None) self._add_abacus_button('soroban', self.abacus_buttons['decimal']) self._add_abacus_button('suanpan', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Bases other than 10 self._add_abacus_button('nepohualtzintzin', self.abacus_buttons['decimal']) self._add_abacus_button('hexadecimal', self.abacus_buttons['decimal']) self._add_abacus_button('binary', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Fractions self._add_abacus_button('schety', self.abacus_buttons['decimal']) # self._add_abacus_button('fraction', self.abacus_buttons['decimal']) self._add_abacus_button('caacupe', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Non-traditional self._add_abacus_button('cuisenaire', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Custom self._add_abacus_button('custom', self.abacus_buttons['decimal']) preferences_button = ToolButton('preferences-system') preferences_button.set_tooltip(_('Custom')) custom_toolbar.insert(preferences_button, -1) preferences_button.palette_invoker.props.toggle_palette = True preferences_button.palette_invoker.props.lock_palette = True preferences_button.props.hide_tooltip_on_click = False preferences_button.show() self._palette = preferences_button.get_palette() button_box = Gtk.VBox() # TRANS: Number of rods on the abacus self._rods_spin = add_spinner_and_label( 15, 1, MAX_RODS, _('Rods:'), self._rods_spin_cb, button_box) # TRANS: Number of beads in the top section of the abacus self._top_spin = add_spinner_and_label( 2, 0, MAX_TOP, _('Top:'), self._top_spin_cb, button_box) # TRANS: Number of beads in the bottom section of the abacus self._bottom_spin = add_spinner_and_label( 5, 0, MAX_BOT, _('Bottom:'), self._bottom_spin_cb, button_box) # TRANS: Scale factor between bottom and top beads self._value_spin = add_spinner_and_label( 5, 1, MAX_BOT + 1, _('Factor:'), self._value_spin_cb, button_box) # TRANS: Scale factor between rods self._base_spin = add_spinner_and_label( 10, 1, (MAX_TOP + 1) * MAX_BOT, _('Base:'), self._base_spin_cb, button_box) hbox = Gtk.HBox() hbox.pack_start(button_box, True, True, style.DEFAULT_SPACING) hbox.show_all() self._palette.set_content(hbox) separator_factory(custom_toolbar, False, False) self.custom_maker = button_factory('new-abacus', custom_toolbar, self._custom_cb, tooltip=_('Custom')) button_factory('edit-copy', edit_toolbar, self._copy_cb, tooltip=_('Copy'), accelerator='<Ctrl>c') button_factory('edit-paste', edit_toolbar, self._paste_cb, tooltip=_('Paste'), accelerator='<Ctrl>v') # Create a canvas canvas = Gtk.DrawingArea() canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self.set_canvas(canvas) canvas.show() self.show_all() # 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'])) if 'top' in self.metadata: self._top_spin.set_value(int(self.metadata['top'])) if 'bottom' in self.metadata: self._bottom_spin.set_value(int(self.metadata['bottom'])) if 'factor' in self.metadata: self._value_spin.set_value(int(self.metadata['factor'])) if 'base' in self.metadata: self._base_spin.set_value(int(self.metadata['base'])) if 'abacus' in self.metadata: if self.metadata['abacus'] in self.abacus_buttons: _logger.debug('restoring %s', self.metadata['abacus']) if self.metadata['abacus'] == 'custom': self._custom_cb() self.abacus_buttons[self.metadata['abacus']].set_active(True) else: # Default is Chinese self.abacus_buttons['suanpan'].set_active(True) if 'value' in self.metadata: _logger.debug('restoring value %s', self.metadata['value']) self.abacus.mode.set_value(self.metadata['value']) self.abacus.mode.label(self.abacus.generate_label()) self.abacus.init() # Start with abacus toolbar expanded and suanpan as default self.abacus_toolbar_button.set_expanded(True) def _add_abacus_button(self, name, group): self.abacus_buttons[name] = radio_factory( name, self.abacus_toolbar, self._radio_cb, cb_arg=name, tooltip=NAMES[name], group=group) def _radio_cb(self, button, abacus): self._select_abacus(abacus) def _reset_cb(self, button=None): 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. ''' # a busy cursor is adequate self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) def _select_abacus(self, abacus): ''' Notify the user of an expected delay and then... ''' if not hasattr(self, 'abacus') or self._setting_up: _logger.debug('setting up') return # Not selected? if not self.abacus_buttons[abacus].get_active(): _logger.debug('%s not active' % abacus) return self._notify_new_abacus(NAMES[abacus]) # Give the cursor/alert time to load GObject.idle_add(self._switch_modes, abacus) def _switch_modes(self, abacus): ''' Display the selected abacus ''' _logger.debug('switching modes to %s', abacus) if abacus == self.abacus.mode.name: _logger.debug('do not switch already in the same mode') self.get_window().set_cursor(None) return # Save current value value = int(float(self.abacus.mode.value())) if abacus == 'custom' and self.abacus.custom is None: self.custom_toolbar_button.set_expanded(True) # self.abacus.mode = self.abacus.custom self.get_window().set_cursor(None) else: _logger.debug('switch_mode: setting abacus to %s' % abacus) 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]) self.get_window().set_cursor(None) def _rods_spin_cb(self, button=None): return def _top_spin_cb(self, button=None): return def _bottom_spin_cb(self, button=None): return def _value_spin_cb(self, button=None): return 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.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._label.set_text(NAMES['custom']) self.abacus.mode = self.abacus.custom self.abacus.mode_dict['custom'][0] = self.abacus.custom self.abacus_toolbar_button.set_expanded(True) self.abacus.mode.set_value_from_number(value) def _copy_cb(self, arg=None): ''' Copy a number to the clipboard from the active abacus. ''' clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) text = self.abacus.generate_label(sum_only=True) if text is not None: clipboard.set_text(text, -1) return def _paste_cb(self, arg=None): ''' Paste a number from the clipboard to the active abacus. ''' clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD) text = clipboard.wait_for_text() if text is not None: try: self.abacus.mode.set_value_from_number(float(text)) except ValueError, e: _logger.debug(str(e)) return self.abacus.mode.label(self.abacus.generate_label()) return
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 self.max_participants = 1 self.sep = [] self.abacus_toolbar = Gtk.Toolbar() custom_toolbar = Gtk.Toolbar() edit_toolbar = Gtk.Toolbar() 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() self.abacus_toolbar_button = ToolbarButton( page=self.abacus_toolbar, icon_name='abacus-list') self.abacus_toolbar.show() toolbox.toolbar.insert(self.abacus_toolbar_button, -1) self.abacus_toolbar_button.show() self.custom_toolbar_button = ToolbarButton( page=custom_toolbar, icon_name='view-source') custom_toolbar.show() toolbox.toolbar.insert(self.custom_toolbar_button, -1) self.custom_toolbar_button.show() separator_factory(toolbox.toolbar, False, True) button_factory('edit-delete', toolbox.toolbar, self._reset_cb, tooltip=_('Reset')) separator_factory(toolbox.toolbar, False, True) self._label = label_factory(NAMES['suanpan'], toolbox.toolbar) separator_factory(toolbox.toolbar, True, False) stop_button = StopButton(self) stop_button.props.accelerator = _('<Ctrl>Q') toolbox.toolbar.insert(stop_button, -1) stop_button.show() self.set_toolbar_box(toolbox) toolbox.show() self.abacus_buttons = {} # Traditional self._add_abacus_button('decimal', None) self._add_abacus_button('soroban', self.abacus_buttons['decimal']) self._add_abacus_button('suanpan', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Bases other than 10 self._add_abacus_button('nepohualtzintzin', self.abacus_buttons['decimal']) self._add_abacus_button('hexadecimal', self.abacus_buttons['decimal']) self._add_abacus_button('binary', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Fractions self._add_abacus_button('schety', self.abacus_buttons['decimal']) # self._add_abacus_button('fraction', self.abacus_buttons['decimal']) self._add_abacus_button('caacupe', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Non-traditional self._add_abacus_button('cuisenaire', self.abacus_buttons['decimal']) self.sep.append(separator_factory(self.abacus_toolbar)) # Custom self._add_abacus_button('custom', self.abacus_buttons['decimal']) preferences_button = ToolButton('preferences-system') preferences_button.set_tooltip(_('Custom')) custom_toolbar.insert(preferences_button, -1) preferences_button.palette_invoker.props.toggle_palette = True preferences_button.palette_invoker.props.lock_palette = True preferences_button.props.hide_tooltip_on_click = False preferences_button.show() self._palette = preferences_button.get_palette() button_box = Gtk.VBox() # TRANS: Number of rods on the abacus self._rods_spin = add_spinner_and_label( 15, 1, MAX_RODS, _('Rods:'), self._rods_spin_cb, button_box) # TRANS: Number of beads in the top section of the abacus self._top_spin = add_spinner_and_label( 2, 0, MAX_TOP, _('Top:'), self._top_spin_cb, button_box) # TRANS: Number of beads in the bottom section of the abacus self._bottom_spin = add_spinner_and_label( 5, 0, MAX_BOT, _('Bottom:'), self._bottom_spin_cb, button_box) # TRANS: Scale factor between bottom and top beads self._value_spin = add_spinner_and_label( 5, 1, MAX_BOT + 1, _('Factor:'), self._value_spin_cb, button_box) # TRANS: Scale factor between rods self._base_spin = add_spinner_and_label( 10, 1, (MAX_TOP + 1) * MAX_BOT, _('Base:'), self._base_spin_cb, button_box) hbox = Gtk.HBox() hbox.pack_start(button_box, True, True, style.DEFAULT_SPACING) hbox.show_all() self._palette.set_content(hbox) separator_factory(custom_toolbar, False, False) self.custom_maker = button_factory('new-abacus', custom_toolbar, self._custom_cb, tooltip=_('Custom')) button_factory('edit-copy', edit_toolbar, self._copy_cb, tooltip=_('Copy'), accelerator='<Ctrl>c') button_factory('edit-paste', edit_toolbar, self._paste_cb, tooltip=_('Paste'), accelerator='<Ctrl>v') # Create a canvas canvas = Gtk.DrawingArea() canvas.set_size_request(Gdk.Screen.width(), Gdk.Screen.height()) self.set_canvas(canvas) canvas.show() self.show_all() # 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'])) if 'top' in self.metadata: self._top_spin.set_value(int(self.metadata['top'])) if 'bottom' in self.metadata: self._bottom_spin.set_value(int(self.metadata['bottom'])) if 'factor' in self.metadata: self._value_spin.set_value(int(self.metadata['factor'])) if 'base' in self.metadata: self._base_spin.set_value(int(self.metadata['base'])) if 'abacus' in self.metadata: if self.metadata['abacus'] in self.abacus_buttons: _logger.debug('restoring %s', self.metadata['abacus']) if self.metadata['abacus'] == 'custom': self._custom_cb() self.abacus_buttons[self.metadata['abacus']].set_active(True) else: # Default is Chinese self.abacus_buttons['suanpan'].set_active(True) if 'value' in self.metadata: _logger.debug('restoring value %s', self.metadata['value']) self.abacus.mode.set_value(self.metadata['value']) self.abacus.mode.label(self.abacus.generate_label()) self.abacus.init() # Start with abacus toolbar expanded and suanpan as default self.abacus_toolbar_button.set_expanded(True) def _add_abacus_button(self, name, group): self.abacus_buttons[name] = radio_factory( name, self.abacus_toolbar, self._radio_cb, cb_arg=name, tooltip=NAMES[name], group=group) def _radio_cb(self, button, abacus): self._select_abacus(abacus) def _reset_cb(self, button=None): 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. ''' # a busy cursor is adequate self.get_window().set_cursor(Gdk.Cursor.new(Gdk.CursorType.WATCH)) def _select_abacus(self, abacus): ''' Notify the user of an expected delay and then... ''' if not hasattr(self, 'abacus') or self._setting_up: _logger.debug('setting up') return # Not selected? if not self.abacus_buttons[abacus].get_active(): _logger.debug('%s not active' % abacus) return self._notify_new_abacus(NAMES[abacus]) # Give the cursor/alert time to load GObject.idle_add(self._switch_modes, abacus) def _switch_modes(self, abacus): ''' Display the selected abacus ''' _logger.debug('switching modes to %s', abacus) if abacus == self.abacus.mode.name: _logger.debug('do not switch already in the same mode') self.get_window().set_cursor(None) return # Save current value value = int(float(self.abacus.mode.value())) if abacus == 'custom' and self.abacus.custom is None: self.custom_toolbar_button.set_expanded(True) # self.abacus.mode = self.abacus.custom self.get_window().set_cursor(None) else: _logger.debug('switch_mode: setting abacus to %s' % abacus) 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]) self.get_window().set_cursor(None) def _rods_spin_cb(self, button=None): return def _top_spin_cb(self, button=None): return def _bottom_spin_cb(self, button=None): return def _value_spin_cb(self, button=None): return 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.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._label.set_text(NAMES['custom']) self.abacus.mode = self.abacus.custom self.abacus.mode_dict['custom'][0] = self.abacus.custom self.abacus_toolbar_button.set_expanded(True) self.abacus.mode.set_value_from_number(value) def _copy_cb(self, arg=None): ''' Copy a number to the clipboard from the active abacus. ''' clipBoard = Gtk.Clipboard() text = self.abacus.generate_label(sum_only=True) if text is not None: clipBoard.set_text(text) return def _paste_cb(self, arg=None): ''' Paste a number from the clipboard to the active abacus. ''' clipBoard = Gtk.Clipboard() text = clipBoard.wait_for_text() if text is not None: try: self.abacus.mode.set_value_from_number(float(text)) except ValueError, e: _logger.debug(str(e)) return self.abacus.mode.label(self.abacus.generate_label()) return
class AbacusMain: def __init__(self): self.r = 0 self.tw = None self.win = Gtk.Window(type=Gtk.WindowType.TOPLEVEL) try: data_file = open('.abacusrc', 'r') except IOError: data_file = open('.abacusrc', 'a+') data_file.write(str(50) + '\n') data_file.write(str(50) + '\n') data_file.write(str(800) + '\n') data_file.write(str(550) + '\n') data_file.seek(0) self.x = int(data_file.readline()) self.y = int(data_file.readline()) self.width = int(data_file.readline()) self.height = int(data_file.readline()) self.win.set_default_size(self.width, self.height) self.win.move(self.x, self.y) self.win.maximize() self.win.set_title(_('Abacus')) self.win.connect('delete_event', lambda w, e: Gtk.main_quit()) ABACI = { 'c': _('Suanpan'), 'j': _('Soroban'), 'r': _('Schety'), 'm': _('Nepohualtzintzin'), 'b': _('Binary'), 'h': _('Hexadecimal'), 'f': _('Fraction'), 'd': _('Decimal'), 'C': _('Caacupé'), 'R': _('Rods') } menu = Gtk.Menu() for k, v in ABACI.iteritems(): menu_items = Gtk.MenuItem.new_with_label(v) menu.append(menu_items) menu_items.connect('activate', self._switch_abacus_cb, k) menu_items = Gtk.MenuItem.new_with_label(_('Reset')) menu.append(menu_items) menu_items.connect('activate', self._reset) menu_items = Gtk.MenuItem.new_with_label(_('Quit')) menu.append(menu_items) menu_items.connect('activate', self.destroy) menu_items.show() root_menu = Gtk.MenuItem.new_with_label('Tools') root_menu.show() root_menu.set_submenu(menu) vbox = Gtk.VBox() self.win.add(vbox) vbox.show() menu_bar = Gtk.MenuBar() vbox.pack_start(menu_bar, False, False, 2) menu_bar.append(root_menu) menu_bar.show_all() canvas = Gtk.DrawingArea() width = Gdk.Screen.width() height = Gdk.Screen.height() canvas.set_size_request(width, height) vbox.pack_end(canvas, True, True, 0) self.win.show() self.abacus = Abacus(canvas) canvas.show() self.abacus.win = self.win self.abacus.activity = self self.abacus.init() def set_title(self, title): self.win.set_title(title) return def _switch_abacus_cb(self, widget, user): ABACI = { 'b': 'binary', 'c': 'saupan', 'f': 'fraction', 'h': 'hexadecimal', 'j': 'soroban', 'm': 'nepohualtzintzin', 'r': 'schety', 'd': 'decimal', 'C': 'caacupe', 'R': 'cuisenaire' } value = int(float(self.abacus.mode.value())) self.abacus.select_abacus(ABACI[user]) self.abacus.mode.set_value_from_number(value) self.abacus.mode.label(self.abacus.generate_label()) return True def _reset(self, event, data=None): ''' Reset beads to initial position ''' self.abacus.mode.reset_abacus() self.abacus.mode.label(self.abacus.generate_label()) return def destroy(self, event, data=None): ''' Callback for destroy event. ''' Gtk.main_quit()
class AbacusMain: ABACI = { 'b': 'binary', 'c': 'suanpan', 'f': 'fraction', 'h': 'hexadecimal', 'j': 'soroban', 'm': 'nepohualtzintzin', 'r': 'schety', 'd': 'decimal', 'C': 'caacupe', 'R': 'cuisenaire' } def __init__(self): self.r = 0 self.tw = None self.win = Gtk.Window(type=Gtk.WindowType.TOPLEVEL) self.x = 50 self.y = 50 self.width = 800 self.height = 550 self.win.set_default_size(self.width, self.height) self.win.move(self.x, self.y) self.win.maximize() self.win.set_title(_('Abacus')) self.win.connect('delete_event', lambda w, e: Gtk.main_quit()) menu = Gtk.Menu() for k, v in self.ABACI.iteritems(): menu_items = Gtk.MenuItem.new_with_label(v) menu.append(menu_items) menu_items.connect('activate', self._switch_abacus_cb, k) menu_items = Gtk.MenuItem.new_with_label(_('Reset')) menu.append(menu_items) menu_items.connect('activate', self._reset) menu_items = Gtk.MenuItem.new_with_label(_('Quit')) menu.append(menu_items) menu_items.connect('activate', self.destroy) menu_items.show() root_menu = Gtk.MenuItem.new_with_label('Tools') root_menu.show() root_menu.set_submenu(menu) vbox = Gtk.VBox() self.win.add(vbox) vbox.show() menu_bar = Gtk.MenuBar() vbox.pack_start(menu_bar, False, False, 2) menu_bar.append(root_menu) menu_bar.show_all() canvas = Gtk.DrawingArea() width = Gdk.Screen.width() height = Gdk.Screen.height() canvas.set_size_request(width, height) vbox.pack_end(canvas, True, True, 0) self.win.show() self.abacus = Abacus(canvas) canvas.show() self.abacus.win = self.win self.abacus.activity = self self.abacus.init() def set_title(self, title): self.win.set_title(title) return def _switch_abacus_cb(self, widget, user): value = int(float(self.abacus.mode.value())) self.abacus.select_abacus(self.ABACI[user]) self.abacus.mode.set_value_from_number(value) self.abacus.mode.label(self.abacus.generate_label()) return True def _reset(self, event, data=None): ''' Reset beads to initial position ''' self.abacus.mode.reset_abacus() self.abacus.mode.label(self.abacus.generate_label()) return def destroy(self, event, data=None): ''' Callback for destroy event. ''' Gtk.main_quit()