diff options
author | Walter Bender <walter@sugarlabs.org> | 2010-04-02 16:27:20 (GMT) |
---|---|---|
committer | Walter Bender <walter@sugarlabs.org> | 2010-04-02 16:27:20 (GMT) |
commit | 8162f477074c485f417ffc7e5b2eb0f1022d3068 (patch) | |
tree | af0ee443b1537019e5743cf40aa70c93ca80b0ae |
New project
-rw-r--r-- | .abacusrc | 4 | ||||
-rw-r--r-- | AbacusActivity.py | 235 | ||||
-rw-r--r-- | COPYING | 12 | ||||
-rw-r--r-- | NEWS | 6 | ||||
-rwxr-xr-x | abacus.py | 161 | ||||
-rw-r--r-- | abacus_window.py | 507 | ||||
-rw-r--r-- | activity/activity-abacus.svg | 187 | ||||
-rw-r--r-- | activity/activity.info | 8 | ||||
-rw-r--r-- | constants.py | 26 | ||||
-rw-r--r-- | icons/Coff.svg | 184 | ||||
-rw-r--r-- | icons/Con.svg | 184 | ||||
-rw-r--r-- | icons/Joff.svg | 192 | ||||
-rw-r--r-- | icons/Jon.svg | 192 | ||||
-rw-r--r-- | icons/Roff.svg | 198 | ||||
-rw-r--r-- | icons/Ron.svg | 198 | ||||
-rw-r--r-- | images/black.svg | 22 | ||||
-rw-r--r-- | images/chinese_rod.svg | 15 | ||||
-rw-r--r-- | images/divider_bar.svg | 15 | ||||
-rw-r--r-- | images/japanese_rod.svg | 15 | ||||
-rw-r--r-- | images/russian_rod.svg | 15 | ||||
-rw-r--r-- | images/white.svg | 22 | ||||
-rwxr-xr-x | setup.py | 5 | ||||
-rw-r--r-- | sprites.py | 367 |
23 files changed, 2770 insertions, 0 deletions
diff --git a/.abacusrc b/.abacusrc new file mode 100644 index 0000000..9373b51 --- /dev/null +++ b/.abacusrc @@ -0,0 +1,4 @@ +50 +50 +800 +550 diff --git a/AbacusActivity.py b/AbacusActivity.py new file mode 100644 index 0000000..fd5f7e2 --- /dev/null +++ b/AbacusActivity.py @@ -0,0 +1,235 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010, Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import pygtk +pygtk.require('2.0') +import gtk +import gobject + +import sugar +from sugar.activity import activity +try: # 0.86+ toolbar widgets + from sugar.bundle.activitybundle import ActivityBundle + from sugar.activity.widgets import ActivityToolbarButton + from sugar.activity.widgets import StopButton + from sugar.graphics.toolbarbox import ToolbarBox + from sugar.graphics.toolbarbox import ToolbarButton +except ImportError: + pass +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.menuitem import MenuItem +from sugar.graphics.icon import Icon +from sugar.datastore import datastore + +from gettext import gettext as _ +import locale +import os.path + +import logging +_logger = logging.getLogger("abacus-activity") + +from abacus_window import Abacus + +# +# Sugar activity +# +class AbacusActivity(activity.Activity): + + def __init__(self, handle): + super(AbacusActivity,self).__init__(handle) + + try: + # Use 0.86 toolbar design + toolbar_box = ToolbarBox() + + # Buttons added to the Activity toolbar + activity_button = ActivityToolbarButton(self) + toolbar_box.toolbar.insert(activity_button, 0) + activity_button.show() + + # Suanpan (Chinese abacus) 2:5 + self.chinese = ToolButton( "Con" ) + self.chinese.set_tooltip(_('suanpan')) + self.chinese.props.sensitive = True + self.chinese.connect('clicked', self._chinese_cb) + toolbar_box.toolbar.insert(self.chinese, -1) + self.chinese.show() + + # Soroban (Japanese abacus) 1:4 + self.japanese = ToolButton( "Joff" ) + self.japanese.set_tooltip(_('soroban')) + self.japanese.props.sensitive = True + self.japanese.connect('clicked', self._japanese_cb) + toolbar_box.toolbar.insert(self.japanese, -1) + self.japanese.show() + + # Schety (Russian abacus) 0:10 + self.russian = ToolButton( "Roff" ) + self.russian.set_tooltip(_('schety')) + self.russian.props.sensitive = True + self.russian.connect('clicked', self._russian_cb) + toolbar_box.toolbar.insert(self.russian, -1) + self.russian.show() + + separator = gtk.SeparatorToolItem() + separator.props.draw = False + separator.set_expand(True) + separator.show() + toolbar_box.toolbar.insert(separator, -1) + + # The ever-present Stop Button + stop_button = StopButton(self) + stop_button.props.accelerator = '<Ctrl>Q' + toolbar_box.toolbar.insert(stop_button, -1) + stop_button.show() + + self.set_toolbar_box(toolbar_box) + toolbar_box.show() + + except NameError: + # Use pre-0.86 toolbar design + self.toolbox = activity.ActivityToolbox(self) + self.set_toolbox(self.toolbox) + + self.projectToolbar = ProjectToolbar(self) + self.toolbox.add_toolbar( _('Project'), self.projectToolbar ) + + self.toolbox.show() + + # Create a canvas + canvas = gtk.DrawingArea() + canvas.set_size_request(gtk.gdk.screen_width(), \ + gtk.gdk.screen_height()) + self.set_canvas(canvas) + canvas.show() + self.show_all() + + # Initialize the canvas + self.abacus = Abacus(canvas, os.path.join(activity.get_bundle_path(), + 'images/'), self) + + """ + # Read the slider positions from the Journal + try: + self.tw.A.spr.move_relative((int(self.metadata['A']),0)) + self.tw.C.spr.move_relative((int(self.metadata['C']),0)) + self.tw.C_tab_left.spr.move_relative((int(self.metadata['C']),0)) + self.tw.C_tab_right.spr.move_relative((int(self.metadata['C'])+\ + SWIDTH-100,0)) + self.tw.D.spr.move_relative((int(self.metadata['D']),0)) + self.tw.R.spr.move_relative((int(self.metadata['R']),0)) + self.tw.R_tab_top.spr.move_relative((int(self.metadata['R']),0)) + self.tw.R_tab_bot.spr.move_relative((int(self.metadata['R']),0)) + self.tw.slider_on_top = self.metadata['slider'] + if self.tw.slider_on_top == 'A': + self._show_a() + else: + self._show_c() + window._update_results_label(self.tw) + window._update_slider_labels(self.tw) + except: + self._show_c() + """ + + def _chinese_cb(self, button): + self._show_c() + return True + + def _show_c(self): + self.chinese.set_icon("Con") + self.japanese.set_icon("Joff") + self.russian.set_icon("Roff") + self.abacus.chinese.show() + self.abacus.japanese.hide() + self.abacus.russian.hide() + self.abacus.mode = self.abacus.chinese + + def _japanese_cb(self, button): + self._show_j() + return True + + def _show_j(self): + self.chinese.set_icon("Coff") + self.japanese.set_icon("Jon") + self.russian.set_icon("Roff") + self.abacus.chinese.hide() + self.abacus.japanese.show() + self.abacus.russian.hide() + self.abacus.mode = self.abacus.japanese + + def _russian_cb(self, button): + self._show_r() + return True + + def _show_r(self): + self.chinese.set_icon("Coff") + self.japanese.set_icon("Joff") + self.russian.set_icon("Ron") + self.abacus.chinese.hide() + self.abacus.japanese.hide() + self.abacus.russian.show() + self.abacus.mode = self.abacus.russian + + """ + Write the slider positions to the Journal + """ + """ + def write_file(self, file_path): + _logger.debug("Write slider on top: " + self.tw.slider_on_top) + self.metadata['slider'] = self.tw.slider_on_top + x,y = self.tw.A.spr.get_xy() + _logger.debug("Write A offset: " + str(x)) + self.metadata['A'] = str(x) + x,y = self.tw.C.spr.get_xy() + _logger.debug("Write C offset: " + str(x)) + self.metadata['C'] = str(x) + x,y = self.tw.D.spr.get_xy() + _logger.debug("Write D offset: " + str(x)) + self.metadata['D'] = str(x) + x,y = self.tw.R.spr.get_xy() + _logger.debug("Write r offset: " + str(x)) + self.metadata['R'] = str(x) + """ + +# +# Project toolbar for pre-0.86 toolbars +# +class ProjectToolbar(gtk.Toolbar): + + def __init__(self, pc): + gtk.Toolbar.__init__(self) + self.activity = pc + + # Chinese style + self.activity.chinese = ToolButton( "Con" ) + self.activity.chinese.set_tooltip(_('saunpan')) + self.activity.chinese.props.sensitive = True + self.activity.chinese.connect('clicked', self.activity._chinese_cb) + self.insert(self.activity.chinese, -1) + self.activity.chinese.show() + + # Japanese style + self.activity.japanese = ToolButton( "Joff" ) + self.activity.japanese.set_tooltip(_('soroban')) + self.activity.japanese.props.sensitive = True + self.activity.japanese.connect('clicked', self.activity._japanese_cb) + self.insert(self.activity.japanese, -1) + self.activity.japanese.show() + + # Russian style + self.activity.russian = ToolButton( "Roff" ) + self.activity.russian.set_tooltip(_('schety')) + self.activity.russian.props.sensitive = True + self.activity.russian.connect('clicked', self.activity._russian_cb) + self.insert(self.activity.russian, -1) + self.activity.russian.show() @@ -0,0 +1,12 @@ +Copyright (c) 2010, Walter Bender + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 3 of the License, or +(at your option) any later version. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, write to the +Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. + @@ -0,0 +1,6 @@ +1 + +* Abacus activity +* Chinese (suanpan), Japanese (soroban), and Russian (schety) models + + diff --git a/abacus.py b/abacus.py new file mode 100755 index 0000000..098e73b --- /dev/null +++ b/abacus.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python + +#Copyright (c) 2010, Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +import pygtk +pygtk.require('2.0') +import gtk + +from gettext import gettext as _ +import os + +from abacus_window import Abacus + +def makepath(path): + """ Make a path if it doesn't previously exist """ + from os import makedirs + from os.path import normpath, dirname, exists + + dpath = normpath(dirname(path)) + if not exists(dpath): + makedirs(dpath) + +class AbacusMain: + def __init__(self): + self.r = 0 + self.tw = None + + self.win = gtk.Window(gtk.WINDOW_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()) + + menu = gtk.Menu() + menu_items = gtk.MenuItem(_("Saunpan")) + menu.append(menu_items) + menu_items.connect("activate", self._c_cb) + menu_items.show() + menu_items = gtk.MenuItem(_("Soroban")) + menu.append(menu_items) + menu_items.connect("activate", self._j_cb) + menu_items.show() + menu_items = gtk.MenuItem(_("Schety")) + menu.append(menu_items) + menu_items.connect("activate", self._r_cb) + menu_items.show() + menu_items = gtk.MenuItem(_("Quit")) + menu.append(menu_items) + menu_items.connect("activate", self.destroy) + menu_items.show() + root_menu = gtk.MenuItem("Tools") + root_menu.show() + root_menu.set_submenu(menu) + + # A vbox to put a menu and the canvas in: + vbox = gtk.VBox(False, 0) + self.win.add(vbox) + vbox.show() + + menu_bar = gtk.MenuBar() + vbox.pack_start(menu_bar, False, False, 2) + menu_bar.show() + + menu_bar.append(root_menu) + + sw = gtk.ScrolledWindow() + sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + sw.show() + canvas = gtk.DrawingArea() + width = gtk.gdk.screen_width() + height = gtk.gdk.screen_height() + canvas.set_size_request(width, height) + sw.add_with_viewport(canvas) + canvas.show() + vbox.pack_end(sw, True, True) + + self.win.show_all() + + if os.path.exists('/usr/share/abacus/images/'): + self.abacus = Abacus(canvas, '/usr/share/abacus/images/') + elif os.path.exists('/usr/local/share/abacus/images/'): + self.abacus = Abacus(canvas, '/usr/local/share/abacus/images/') + else: + self.abacus = Abacus(canvas, os.path.abspath('.')+'/images/') + self.abacus.win = self.win + + """ + + canvas = gtk.DrawingArea() + vbox.pack_end(canvas, True, True) + canvas.show() + + menu_bar.append(root_menu) + self.win.show_all() + + # Join the activity + self.abacus = Abacus(canvas, os.path.join(os.path.abspath('.'), + 'images/')) + """ + + self.abacus.activity = self + + def set_title(self, title): + self.win.set_title(title) + + def _c_cb(self, widget): + self.abacus.chinese.show() + self.abacus.japanese.hide() + self.abacus.russian.hide() + self.abacus.mode = self.abacus.chinese + return True + + def _j_cb(self, widget): + self.abacus.chinese.hide() + self.abacus.japanese.show() + self.abacus.russian.hide() + self.abacus.mode = self.abacus.japanese + return True + + def _r_cb(self, widget): + self.abacus.chinese.hide() + self.abacus.japanese.hide() + self.abacus.russian.show() + self.abacus.mode = self.abacus.russian + return True + + def destroy(self, event, data=None): + """ Callback for destroy event. """ + gtk.main_quit() + +def main(): + gtk.main() + return 0 + +if __name__ == "__main__": + AbacusMain() + main() diff --git a/abacus_window.py b/abacus_window.py new file mode 100644 index 0000000..32aa053 --- /dev/null +++ b/abacus_window.py @@ -0,0 +1,507 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2010, Walter Bender + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the +# Free Software Foundation, Inc., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +from constants import * + +import pygtk +pygtk.require('2.0') +import gtk +from gettext import gettext as _ +import math +import os + +try: + from sugar.graphics import style + GRID_CELL_SIZE = style.GRID_CELL_SIZE +except: + GRID_CELL_SIZE = 0 + +from sprites import * + +def load_image(path, name, w, h): + """ create a pixbuf from a SVG stored in a file """ + return gtk.gdk.pixbuf_new_from_file_at_size( + os.path.join(path+name+'.svg'), int(w), int(h)) + +class Abacus(): + + def __init__(self, canvas, path, parent=None): + """ Abacus class """ + self.path = path + self.activity = parent + + if parent is None: # Starting from command line + self.sugar = False + self.canvas = canvas + else: # Starting from Sugar + self.sugar = True + self.canvas = canvas + parent.show_all() + + self.canvas.set_flags(gtk.CAN_FOCUS) + self.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) + self.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) + self.canvas.add_events(gtk.gdk.POINTER_MOTION_MASK) + self.canvas.connect("expose-event", self._expose_cb) + self.canvas.connect("button-press-event", self._button_press_cb) + self.canvas.connect("button-release-event", self._button_release_cb) + self.canvas.connect("motion-notify-event", self._mouse_move_cb) + self.width = gtk.gdk.screen_width() + self.height = gtk.gdk.screen_height()-GRID_CELL_SIZE + self.sprites = Sprites(self.canvas) + self.scale = gtk.gdk.screen_height()/900.0 + self.dragpos = 0 + self.press = None + + self.chinese = Suanpan(self) + self.japanese = Soroban(self) + self.russian = Schety(self) + + self.chinese.show() + self.japanese.hide() + self.russian.hide() + self.mode = self.chinese + + def _button_press_cb(self, win, event): + win.grab_focus() + x, y = map(int, event.get_coords()) + self.dragpos = y + self.press = self.sprites.find_sprite((x,y)) + if self.press is not None and self.press.type != 'bead': + self.press = None + return True + + def _mouse_move_cb(self, win, event): + if self.press is None: + self.dragpos = 0 + return True + win.grab_focus() + x, y = map(int, event.get_coords()) + dy = y-self.dragpos + self.mode.move_bead(self.press, dy) + + def _button_release_cb(self, win, event): + if self.press == None: + return True + self.press = None + self.mode.label(self.mode.value()) + return True + + def _expose_cb(self, win, event): + self.sprites.redraw_sprites() + return True + + def _destroy_cb(self, win, event): + gtk.main_quit() + + +class Suanpan(): + + def __init__(self, abacus): + """ create a Chinese abacus: 15 by (5,2) """ + self.abacus = abacus + self.num_rods = 15 + self.bot_beads = 5 + self.top_beads = 2 + # 5 beads + 2 spaces, divider, 2 bead + 2 spaces + h = (self.bot_beads+2+1+self.top_beads+2)*BHEIGHT*self.abacus.scale + w = (self.num_rods+1)*(BWIDTH+BOFFSET)*self.abacus.scale + dy = 4*BHEIGHT*self.abacus.scale + x = (self.abacus.width-w)/2 + y = (self.abacus.height-h)/2 + + # Draw the rods... + self.rods = [] + o = (BWIDTH+BOFFSET-5)*self.abacus.scale/2 + dx = (BWIDTH+BOFFSET)*self.abacus.scale + for i in range(self.num_rods): + self.rods.append(Sprite(self.abacus.sprites, x+i*dx+o, y, + load_image(self.abacus.path, "chinese_rod", + 10*self.abacus.scale, h))) + + for i in self.rods: + i.type = 'rod' + + # and then the beads. + self.beads = [] + o = (BWIDTH-BOFFSET)/2*self.abacus.scale/2 + for i in range(self.num_rods): + for b in range(self.top_beads): + self.beads.append(Sprite(self.abacus.sprites, x+i*dx+o, + y+b*BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, "white", + BWIDTH*self.abacus.scale, + BHEIGHT*self.abacus.scale))) + for b in range(self.bot_beads): + self.beads.append(Sprite(self.abacus.sprites, x+i*dx+o, + y+(7+b)*BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, "white", + BWIDTH*self.abacus.scale, + BHEIGHT*self.abacus.scale))) + + for i in self.beads: + i.type = 'bead' + i.state = 0 + + # Draw the dividing bar on top + self.bar = Sprite(self.abacus.sprites, x, y+dy, + load_image(self.abacus.path, "divider_bar", + w, BHEIGHT*self.abacus.scale)) + + self.bar.type = 'frame' + self.bar.set_label_color('white') + + def value(self): + """ Return a string representing the value of each rod """ + string = '' + v = [] + for r in range(self.num_rods+1): # +1 for overflow + v.append(0) + + # Tally the values on each rod. + for i, b in enumerate(self.beads): + r = i/(self.top_beads+self.bot_beads) + j = i%(self.top_beads+self.bot_beads) + if b.state == 1: + if j < self.top_beads: + v[r+1] += 5 + else: + v[r+1] += 1 + + # Carry to the left if a rod has a value > 9. + for j in range(self.num_rods): + if v[len(v)-j-1] > 9: + v[len(v)-j-1] -= 10 + v[len(v)-j-2] += 1 + + # Convert values to a string. + for j in v: + if string != '' or j > 0: + string += str(j) + return(string) + + def hide(self): + for i in self.rods: + i.hide() + for i in self.beads: + i.hide() + self.bar.hide() + + def show(self): + for i in self.rods: + i.set_layer(100) + for i in self.beads: + i.set_layer(101) + self.bar.set_layer(102) + + def label(self, string): + """ Label the crossbar with the string. (USed with self.value) """ + self.bar.set_label(string) + + def move_bead(self, bead, dy): + """ Move a bead (or beads) up or down a rod. """ + i = self.beads.index(bead) + b = i%(self.top_beads+self.bot_beads) + + if b < self.top_beads: + if dy > 0 and bead.state == 0: + bead.move_relative((0, 2*BHEIGHT*self.abacus.scale)) + bead.state = 1 + # make sure beads below this bead are also moved + if b == 0 and self.beads[i+1].state == 0: + self.beads[i+1].move_relative((0, + 2*BHEIGHT*self.abacus.scale)) + self.beads[i+1].state = 1 + elif dy < 0 and bead.state == 1: + bead.move_relative((0, -2*BHEIGHT*self.abacus.scale)) + # make sure beads above this bead are also moved + if b == 1 and self.beads[i-1].state == 1: + self.beads[i-1].move_relative((0, + -2*BHEIGHT*self.abacus.scale)) + self.beads[i-1].state = 0 + bead.state = 0 + else: + if dy < 0 and bead.state == 0: + bead.move_relative((0, -2*BHEIGHT*self.abacus.scale)) + bead.state = 1 + # make sure beads above this bead are also moved + for ii in range(b-self.top_beads+1): + if self.beads[i-ii].state == 0: + self.beads[i-ii].move_relative((0, + -2*BHEIGHT*self.abacus.scale)) + self.beads[i-ii].state = 1 + elif dy > 0 and bead.state == 1: + bead.move_relative((0, 2*BHEIGHT*self.abacus.scale)) + bead.state = 0 + # make sure beads below this bead are also moved + for ii in range(self.top_beads+self.bot_beads-b): + if self.beads[i+ii].state == 1: + self.beads[i+ii].move_relative((0, + 2*BHEIGHT*self.abacus.scale)) + self.beads[i+ii].state = 0 + + +class Soroban(): + + def __init__(self, abacus): + """ create a Japanese abacus: 15 by (4,1) """ + self.abacus = abacus + self.num_rods = 15 + self.bot_beads = 4 + self.top_beads = 1 + # 4 beads + 2 spaces, divider, 1 bead + 2 spaces + h = (self.bot_beads+2+1+self.top_beads+2)*BHEIGHT*self.abacus.scale + w = (self.num_rods+1)*(BWIDTH+BOFFSET)*self.abacus.scale + dy = 3*BHEIGHT*self.abacus.scale + x = (self.abacus.width-w)/2 + y = (self.abacus.height-h)/2 + + # Draw the rods... + self.rods = [] + o = (BWIDTH+BOFFSET-5)*self.abacus.scale/2 + dx = (BWIDTH+BOFFSET)*self.abacus.scale + for i in range(self.num_rods): + self.rods.append(Sprite(self.abacus.sprites, x+i*dx+o, y, + load_image(self.abacus.path, "japanese_rod", + 10, h))) + + for i in self.rods: + i.type = 'rod' + + # and then the beads. + self.beads = [] + o = (BWIDTH-BOFFSET)/2*self.abacus.scale/2 + for i in range(self.num_rods): + for b in range(self.top_beads): + self.beads.append(Sprite(self.abacus.sprites, x+i*dx+o, + y+b*BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, "white", + BWIDTH*self.abacus.scale, + BHEIGHT*self.abacus.scale))) + for b in range(self.bot_beads): + self.beads.append(Sprite(self.abacus.sprites, x+i*dx+o, + y+(6+b)*BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, "white", + BWIDTH*self.abacus.scale, + BHEIGHT*self.abacus.scale))) + + for i in self.beads: + i.type = 'bead' + i.state = 0 + + # Draw the dividing bar on top + self.bar = Sprite(self.abacus.sprites, x, y+dy, + load_image(self.abacus.path, "divider_bar", + w, BHEIGHT*self.abacus.scale)) + + self.bar.type = 'frame' + self.bar.set_label_color('white') + + def hide(self): + for i in self.rods: + i.hide() + for i in self.beads: + i.hide() + self.bar.hide() + + def show(self): + for i in self.rods: + i.set_layer(100) + for i in self.beads: + i.set_layer(101) + self.bar.set_layer(102) + + def value(self): + """ Return a string with the value of each rod. """ + string = '' + v = 0 + for i, b in enumerate(self.beads): + if b.state == 1: + if i%(self.top_beads+self.bot_beads) < self.top_beads: + v += 5 + else: + v += 1 + if i%(self.top_beads+self.bot_beads) == \ + self.top_beads+self.bot_beads-1: + if string != '' or v > 0: + string += str(v) + v = 0 + return(string) + + def label(self, string): + """ Label the crossbar with the string. (USed with self.value) """ + self.bar.set_label(string) + + def move_bead(self, bead, dy): + """ Move a bead (or beads) up or down a rod. """ + i = self.beads.index(bead) + b = i%(self.top_beads+self.bot_beads) + + if b < self.top_beads: + if dy > 0 and bead.state == 0: + bead.move_relative((0, 2*BHEIGHT*self.abacus.scale)) + bead.state = 1 + elif dy < 0 and bead.state == 1: + bead.move_relative((0, -2*BHEIGHT*self.abacus.scale)) + bead.state = 0 + else: + if dy < 0 and bead.state == 0: + bead.move_relative((0, -2*BHEIGHT*self.abacus.scale)) + bead.state = 1 + # make sure beads above this bead are also moved + for ii in range(b-self.top_beads+1): + if self.beads[i-ii].state == 0: + self.beads[i-ii].move_relative((0, + -2*BHEIGHT*self.abacus.scale)) + self.beads[i-ii].state = 1 + elif dy > 0 and bead.state == 1: + bead.move_relative((0, 2*BHEIGHT*self.abacus.scale)) + bead.state = 0 + # make sure beads below this bead are also moved + for ii in range(self.top_beads+self.bot_beads-b): + if self.beads[i+ii].state == 1: + self.beads[i+ii].move_relative((0, + 2*BHEIGHT*self.abacus.scale)) + self.beads[i+ii].state = 0 + + +class Schety(): + + def __init__(self, abacus): + """ create a Russian abacus: 15 by 10 """ + self.abacus = abacus + self.num_rods = 15 + self.bot_beads = 10 + # 10 beads + 2 spaces + h = (self.bot_beads+2)*BHEIGHT*self.abacus.scale + w = (self.num_rods+1)*(BWIDTH+BOFFSET)*self.abacus.scale + x = (self.abacus.width-w)/2 + y = (self.abacus.height-h)/2 + + # Draw the rods... + self.rods = [] + o = (BWIDTH+BOFFSET-5)*self.abacus.scale/2 + dx = (BWIDTH+BOFFSET)*self.abacus.scale + for i in range(self.num_rods): + self.rods.append(Sprite(self.abacus.sprites, x+i*dx+o, y, + load_image(self.abacus.path, "russian_rod", + 10, h))) + + for i in self.rods: + i.type = 'rod' + + # and then the beads. + self.beads = [] + o = (BWIDTH-BOFFSET)/2*self.abacus.scale/2 + for i in range(self.num_rods): + if i == 10: + for b in range(4): + if b in [1,2]: + color = 'black' + else: + color = 'white' + self.beads.append(Sprite(self.abacus.sprites, x+i*dx+o, + y+(8+b)*BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, color, + BWIDTH*self.abacus.scale, + BHEIGHT*self.abacus.scale))) + else: + for b in range(self.bot_beads): + if b in [4,5]: + color = 'black' + else: + color = 'white' + self.beads.append(Sprite(self.abacus.sprites, x+i*dx+o, + y+(2+b)*BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, color, + BWIDTH*self.abacus.scale, + BHEIGHT*self.abacus.scale))) + + for i in self.beads: + i.type = 'bead' + i.state = 0 + + # Draw a bar for the label on top + self.bar = Sprite(self.abacus.sprites, x, y-BHEIGHT*self.abacus.scale, + load_image(self.abacus.path, "divider_bar", + w, BHEIGHT*self.abacus.scale)) + + self.bar.type = 'frame' + self.bar.set_label_color('white') + + def hide(self): + for i in self.rods: + i.hide() + for i in self.beads: + i.hide() + self.bar.hide() + + def show(self): + for i in self.rods: + i.set_layer(100) + for i in self.beads: + i.set_layer(101) + self.bar.set_layer(102) + + def value(self): + # TODO: cascade and account for short rod + """ Return a string with the value of each rod. """ + string = '' + v = 0 + for i, b in enumerate(self.beads): + if b.state == 1: + v += 1 + if i%self.bot_beads == self.bot_beads-1: + if string != '' or v > 0: + string += str(v) + v = 0 + return(string) + + def label(self, string): + """ Label the crossbar with the string. (USed with self.value) """ + self.bar.set_label(string) + + def move_bead(self, bead, dy): + # TODO: take into account short rod in rod calculations + i = self.beads.index(bead) + r = i/self.bot_beads + if r < 10: + o = 2 + b = i%self.bot_beads + n = self.bot_beads + elif r == 10: + o = 8 + b = i%self.bot_beads + n = 4 + else: + s = 2 + b = (i+6)%self.bot_beads + n = self.bot_beads + if dy < 0 and bead.state == 0: + bead.move_relative((0, -o*BHEIGHT*self.abacus.scale)) + bead.state = 1 + # make sure beads above this bead are also moved + for ii in range(b+1): + if self.beads[i-ii].state == 0: + self.beads[i-ii].move_relative((0, + -o*BHEIGHT*self.abacus.scale)) + self.beads[i-ii].state = 1 + elif dy > 0 and bead.state == 1: + bead.move_relative((0, o*BHEIGHT*self.abacus.scale)) + bead.state = 0 + # make sure beads below this bead are also moved + for ii in range(n-b): + if self.beads[i+ii].state == 1: + self.beads[i+ii].move_relative((0, + o*BHEIGHT*self.abacus.scale)) + self.beads[i+ii].state = 0 diff --git a/activity/activity-abacus.svg b/activity/activity-abacus.svg new file mode 100644 index 0000000..8e4e512 --- /dev/null +++ b/activity/activity-abacus.svg @@ -0,0 +1,187 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" + "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [ + <!ENTITY fill_color "#AAAAAA"> + <!ENTITY stroke_color "#000000"> +]> +<svg xmlns="http://www.w3.org/2000/svg" width="45" height="45"> + <rect + width="37.959229" + height="43" + x="-41.478813" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2" /> + <line + y1="14" + y2="14" + x1="43.966454" + x2="1.0335478" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2" + id="line10-4" /> + <g + transform="translate(82.754238,28.792372)" + id="g3788"> + <g + transform="translate(-14.555086,-5.2669489)" + id="g3690"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10" /> + <g + transform="translate(0,0.94158681)" + id="g3684"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(-4.1313576,-5.2669489)" + id="g3690-5"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-2" /> + <g + transform="translate(0,0.94158681)" + id="g3684-5"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-47" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-4" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-4" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-3" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-0" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(6.2923724,-5.2669489)" + id="g3690-8"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-6" /> + <g + transform="translate(0,0.94158681)" + id="g3684-8"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-8" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-43" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-1" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-4" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-9" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(-24.978814,-5.2669489)" + id="g3690-0"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:&fill_color;;stroke:&stroke_color;;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68" /> + <g + transform="translate(0,0.94158681)" + id="g3684-9"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-2" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-6" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-6" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-49" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-5" + style="fill:&stroke_color;;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> +</svg> diff --git a/activity/activity.info b/activity/activity.info new file mode 100644 index 0000000..335adb9 --- /dev/null +++ b/activity/activity.info @@ -0,0 +1,8 @@ +[Activity] +name = Abacus +activity_version = 1 +license = GPLv3 +bundle_id = org.sugarlabs.AbacusActivity +exec = sugar-activity AbacusActivity.AbacusActivity +icon = activity-abacus +show_launcher = yes diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..ca7f6c2 --- /dev/null +++ b/constants.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +#Copyright (c) 2009, Walter Bender + +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is +#furnished to do so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in +#all copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +BWIDTH = 40 +BHEIGHT = 30 +BOFFSET = 10 +NRODS = 15 + diff --git a/icons/Coff.svg b/icons/Coff.svg new file mode 100644 index 0000000..aa6c56a --- /dev/null +++ b/icons/Coff.svg @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <defs + id="defs41" /> + <rect + width="37.959229" + height="43" + x="-41.479614" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2" /> + <line + y1="16.5" + y2="16.5" + x1="44.18692" + x2="1.2540125" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2" + id="line10-4" /> + <g + transform="translate(0,0.06685352)" + id="g2971"> + <line + id="line10-68" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(10.448677,0.06685352)" + id="g2971-9"> + <line + id="line10-68-3" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-74" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(20.897353,0.06685352)" + id="g2971-3"> + <line + id="line10-68-0" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-78" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-68" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6-1" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(31.346028,0.06685352)" + id="g2971-0"> + <line + id="line10-68-6" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6-26" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-64" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6-0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> +</svg> diff --git a/icons/Con.svg b/icons/Con.svg new file mode 100644 index 0000000..c55f777 --- /dev/null +++ b/icons/Con.svg @@ -0,0 +1,184 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <defs + id="defs41" /> + <rect + width="37.959229" + height="43" + x="-41.479614" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2" /> + <line + y1="16.5" + y2="16.5" + x1="44.18692" + x2="1.2540125" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2" + id="line10-4" /> + <g + transform="translate(0,0.06685352)" + id="g2971"> + <line + id="line10-68" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(10.448677,0.06685352)" + id="g2971-9"> + <line + id="line10-68-3" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-74" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(20.897353,0.06685352)" + id="g2971-3"> + <line + id="line10-68-0" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-78" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-68" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6-1" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(31.346028,0.06685352)" + id="g2971-0"> + <line + id="line10-68-6" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + x2="6.7392497" + x1="6.7392497" + y2="4.2606754" + y1="40.605618" /> + <path + d="m 10.73925,26.747115 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,30.676521 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,34.605927 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-5-6-26" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,38.535333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-64" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,6.1059274 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-2-7-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,10.035333 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-7-6-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.73925,22.816439 a 4,1.9646672 0 0 1 -8,0 4,1.9646672 0 1 1 8,0 z" + id="path3633-3-49-6-0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> +</svg> diff --git a/icons/Joff.svg b/icons/Joff.svg new file mode 100644 index 0000000..828b233 --- /dev/null +++ b/icons/Joff.svg @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <defs + id="defs41" /> + <rect + width="37.959229" + height="43" + x="-41.478813" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2" /> + <line + y1="14" + y2="14" + x1="43.966454" + x2="1.0335478" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2" + id="line10-4" /> + <g + transform="translate(82.754238,28.792372)" + id="g3788"> + <g + transform="translate(-14.555086,-5.2669489)" + id="g3690"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10" /> + <g + transform="translate(0,0.94158681)" + id="g3684"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(-4.1313576,-5.2669489)" + id="g3690-5"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-2" /> + <g + transform="translate(0,0.94158681)" + id="g3684-5"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-47" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(6.2923724,-5.2669489)" + id="g3690-8"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-6" /> + <g + transform="translate(0,0.94158681)" + id="g3684-8"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-43" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-1" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(-24.978814,-5.2669489)" + id="g3690-0"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68" /> + <g + transform="translate(0,0.94158681)" + id="g3684-9"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> +</svg> diff --git a/icons/Jon.svg b/icons/Jon.svg new file mode 100644 index 0000000..d0acfd3 --- /dev/null +++ b/icons/Jon.svg @@ -0,0 +1,192 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <defs + id="defs41" /> + <rect + width="37.959229" + height="43" + x="-41.478813" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2" /> + <line + y1="14" + y2="14" + x1="43.966454" + x2="1.0335478" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2" + id="line10-4" /> + <g + transform="translate(82.754238,28.792372)" + id="g3788"> + <g + transform="translate(-14.555086,-5.2669489)" + id="g3690"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10" /> + <g + transform="translate(0,0.94158681)" + id="g3684"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(-4.1313576,-5.2669489)" + id="g3690-5"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-2" /> + <g + transform="translate(0,0.94158681)" + id="g3684-5"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-47" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(6.2923724,-5.2669489)" + id="g3690-8"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-6" /> + <g + transform="translate(0,0.94158681)" + id="g3684-8"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-43" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-1" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="translate(-24.978814,-5.2669489)" + id="g3690-0"> + <line + y1="15.974576" + y2="-18.025423" + x1="-50.911018" + x2="-50.911018" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68" /> + <g + transform="translate(0,0.94158681)" + id="g3684-9"> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,9.5844131)" + id="path3633-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,15.084513)" + id="path3633-7-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,20.584613)" + id="path3633-5-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,26.084713)" + id="path3633-3-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <path + d="m -62.542371,-12.870763 a 4.0042372,2.7648306 0 1 1 -8.008474,0 4.0042372,2.7648306 0 1 1 8.008474,0 z" + transform="matrix(0.99894183,0,0,0.99463598,15.565173,-3.4736993)" + id="path3633-4-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> +</svg> diff --git a/icons/Roff.svg b/icons/Roff.svg new file mode 100644 index 0000000..8594f97 --- /dev/null +++ b/icons/Roff.svg @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <defs + id="defs41" /> + <rect + width="37.959229" + height="43" + x="-41.479614" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:#aaaaaa;fill-opacity:1;stroke:#000000;stroke-width:2" /> + <line + y1="39.5" + y2="5.5" + x1="22.5" + x2="22.5" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68" /> + <g + transform="translate(0,-2.0365919)" + id="g3825"> + <g + transform="matrix(1,0,0,0.67426444,15.635544,15.573287)" + id="g3781"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="matrix(1,0,0,0.67426444,15.635544,-2.9776469)" + id="g3781-4"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> + <line + y1="39.500004" + y2="5.4999976" + x1="9.724575" + x2="9.724575" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68-3" /> + <g + transform="translate(-12.775424,-2.0365919)" + id="g3825-7"> + <g + transform="matrix(1,0,0,0.67426444,15.635544,15.573287)" + id="g3781-45"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="matrix(1,0,0,0.67426444,15.635544,-2.9776469)" + id="g3781-4-4"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-7-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-6-0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-5-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-6-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-9-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> + <line + y1="39.500004" + y2="5.4999976" + x1="35.084743" + x2="35.084743" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68-3-8" /> + <g + transform="translate(12.584746,-2.0365919)" + id="g3825-7-8"> + <g + transform="matrix(1,0,0,0.67426444,15.635544,15.573287)" + id="g3781-45-4"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-2-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-5-1" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-4-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-7-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-4-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="matrix(1,0,0,0.67426444,15.635544,-2.9776469)" + id="g3781-4-4-0"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-7-3-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-6-0-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-5-7-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-6-8-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-9-6-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> +</svg> diff --git a/icons/Ron.svg b/icons/Ron.svg new file mode 100644 index 0000000..3481473 --- /dev/null +++ b/icons/Ron.svg @@ -0,0 +1,198 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="45" + height="45" + id="svg2"> + <defs + id="defs41" /> + <rect + width="37.959229" + height="43" + x="-41.479614" + y="1" + transform="matrix(0,-1,1,0,0,0)" + id="rect4" + style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:2" /> + <line + y1="39.5" + y2="5.5" + x1="22.5" + x2="22.5" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68" /> + <g + transform="translate(0,-2.0365919)" + id="g3825"> + <g + transform="matrix(1,0,0,0.67426444,15.635544,15.573287)" + id="g3781"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="matrix(1,0,0,0.67426444,15.635544,-2.9776469)" + id="g3781-4"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> + <line + y1="39.500004" + y2="5.4999976" + x1="9.724575" + x2="9.724575" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68-3" /> + <g + transform="translate(-12.775424,-2.0365919)" + id="g3825-7"> + <g + transform="matrix(1,0,0,0.67426444,15.635544,15.573287)" + id="g3781-45"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-5" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="matrix(1,0,0,0.67426444,15.635544,-2.9776469)" + id="g3781-4-4"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-7-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-6-0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-5-7" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-6-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-9-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> + <line + y1="39.500004" + y2="5.4999976" + x1="35.084743" + x2="35.084743" + style="fill:#aaaaaa;stroke:#000000;stroke-width:2;stroke-miterlimit:0;stroke-dasharray:none" + id="line10-68-3-8" /> + <g + transform="translate(12.584746,-2.0365919)" + id="g3825-7-8"> + <g + transform="matrix(1,0,0,0.67426444,15.635544,15.573287)" + id="g3781-45-4"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-2-3" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-5-1" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-4-4" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-7-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-4-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + <g + transform="matrix(1,0,0,0.67426444,15.635544,-2.9776469)" + id="g3781-4-4-0"> + <path + d="m 10.864456,21.54732 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-2-7-3-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,27.049879 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-7-6-6-0-8" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,32.552439 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-5-6-5-7-9" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,38.054999 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-3-49-6-8-2" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + <path + d="m 10.864456,16.04476 a 4,2.75 0 1 1 -7.9999992,0 4,2.75 0 1 1 7.9999992,0 z" + id="path3633-4-5-9-6-6" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none" /> + </g> + </g> +</svg> diff --git a/images/black.svg b/images/black.svg new file mode 100644 index 0000000..1101eb4 --- /dev/null +++ b/images/black.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="40" + height="30" + id="svg2"> + <defs + id="defs4" /> + <g + transform="translate(-3.329523e-6,-1022.3622)" + id="layer1"> + <path + d="m 379.99999,425.21933 a 98.571434,49.999996 0 1 1 -197.14287,0 98.571434,49.999996 0 1 1 197.14287,0 z" + transform="matrix(0.18768115,0,0,0.27000002,-32.818832,922.55297)" + id="path2816" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#ffffff;stroke-width:13.32689667;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/images/chinese_rod.svg b/images/chinese_rod.svg new file mode 100644 index 0000000..a8cb73c --- /dev/null +++ b/images/chinese_rod.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="10" + height="360" + id="svg2"> + <rect + width="10" + height="360" + x="0" + y="0" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.0;stroke-opacity:1" /> +</svg> diff --git a/images/divider_bar.svg b/images/divider_bar.svg new file mode 100644 index 0000000..0c89eec --- /dev/null +++ b/images/divider_bar.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="750" + height="30" + id="svg2"> + <rect + width="750" + height="30" + x="0" + y="0" + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:3;stroke-opacity:1" /> +</svg> diff --git a/images/japanese_rod.svg b/images/japanese_rod.svg new file mode 100644 index 0000000..bc9a5ca --- /dev/null +++ b/images/japanese_rod.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="10" + height="300" + id="svg2"> + <rect + width="10" + height="300" + x="0" + y="0" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.0;stroke-opacity:1" /> +</svg> diff --git a/images/russian_rod.svg b/images/russian_rod.svg new file mode 100644 index 0000000..a8cb73c --- /dev/null +++ b/images/russian_rod.svg @@ -0,0 +1,15 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="10" + height="360" + id="svg2"> + <rect + width="10" + height="360" + x="0" + y="0" + style="fill:#000000;fill-opacity:1;stroke:#000000;stroke-width:3.0;stroke-opacity:1" /> +</svg> diff --git a/images/white.svg b/images/white.svg new file mode 100644 index 0000000..9b66d68 --- /dev/null +++ b/images/white.svg @@ -0,0 +1,22 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<!-- Created with Inkscape (http://www.inkscape.org/) --> + +<svg + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + version="1.1" + width="40" + height="30" + id="svg2"> + <defs + id="defs4" /> + <g + transform="translate(-3.329523e-6,-1022.3622)" + id="layer1"> + <path + d="m 379.99999,425.21933 a 98.571434,49.999996 0 1 1 -197.14287,0 98.571434,49.999996 0 1 1 197.14287,0 z" + transform="matrix(0.18768115,0,0,0.27000002,-32.818832,922.55297)" + id="path2816" + style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:13.32689667;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" /> + </g> +</svg> diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..bd1e319 --- /dev/null +++ b/setup.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python +from sugar.activity import bundlebuilder +if __name__ == "__main__": + bundlebuilder.start() + diff --git a/sprites.py b/sprites.py new file mode 100644 index 0000000..045ab98 --- /dev/null +++ b/sprites.py @@ -0,0 +1,367 @@ +# -*- coding: utf-8 -*- + +#Copyright (c) 2007-8, Playful Invention Company. +#Copyright (c) 2008-10 Walter Bender + +#Permission is hereby granted, free of charge, to any person obtaining a copy +#of this software and associated documentation files (the "Software"), to deal +#in the Software without restriction, including without limitation the rights +#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +#copies of the Software, and to permit persons to whom the Software is +#furnished to do so, subject to the following conditions: + +#The above copyright notice and this permission notice shall be included in +#all copies or substantial portions of the Software. + +#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +#THE SOFTWARE. + +""" + +sprites.py is a simple sprites library for managing graphics objects, +'sprites', on a canvas. It manages multiple sprites with methods such +as move, hide, set_layer, etc. + +There are two classes: + +class Sprites maintains a collection of sprites. +class Sprite manages individual sprites within the collection. + +Example usage: + # Import the classes into your program. + from sprites import Sprites, Sprite + + # Create a new sprite collection for a gtk Drawing Area. + my_drawing_area = gtk.DrawingArea() + self.sprite_list = Sprites(my_drawing_area) + + # Create a "pixbuf" (in this example, from SVG). + my_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>") + + # Create a sprite at position x1, y1. + my_sprite = sprites.Sprite(self.sprite_list, x1, y1, my_pixbuf) + + # Move the sprite to a new position. + my_sprite.move((x1+dx, y1+dy)) + + # Create another "pixbuf". + your_pixbuf = svg_str_to_pixbuf("<svg>...some svg code...</svg>") + + # Create a sprite at position x2, y2. + your_sprite = sprites.Sprite(self.sprite_list, x2, y2, my_pixbuf) + + # Assign the sprites to layers. + # In this example, your_sprite will be on top of my_sprite. + my_sprite.set_layer(100) + your_sprite.set_layer(200) + + # Now put my_sprite on top of your_sprite. + my_sprite.set_layer(300) + +# method for converting SVG to a gtk pixbuf +def svg_str_to_pixbuf(svg_string): + pl = gtk.gdk.PixbufLoader('svg') + pl.write(svg_string) + pl.close() + pixbuf = pl.get_pixbuf() + return pixbuf +""" + +import pygtk +pygtk.require('2.0') +import gtk +import gobject +import pango + +# +# A class for the list of sprites and everything they share in common +# + +class Sprites: + def __init__(self, canvas, area=None, gc=None): + self.canvas = canvas + if area == None: + self.area = self.canvas.window + self.gc = self.area.new_gc() + else: + self.area = area + self.gc = gc + self.cm = self.gc.get_colormap() + self.list = [] + + def get_sprite(self, i): + if i < 0 or i > len(self.list)-1: + return(None) + else: + return(self.list[i]) + + def length_of_list(self): + return(len(self.list)) + + def append_to_list(self, spr): + self.list.append(spr) + + def insert_in_list(self, spr, i): + if i < 0: + self.list.insert(0, spr) + elif i > len(self.list)-1: + self.list.append(spr) + else: + self.list.insert(i, spr) + + def remove_from_list(self, spr): + if spr in self.list: + self.list.remove(spr) + + def find_sprite(self, pos): + list = self.list[:] + list.reverse() + for spr in list: + if spr.hit(pos): return spr + return None + + def redraw_sprites(self): + for spr in self.list: + spr.draw() + +# +# A class for the individual sprites +# +class Sprite: + def __init__(self, sprites, x, y, image): + self._sprites = sprites + self._x = int(x) + self._y = int(y) + self._scale = [12] + self._rescale = [True] + self._horiz_align = ["center"] + self._vert_align = ["middle"] + self._fd = None + self._bold = False + self._italic = False + self._color = None + self._width = 0 + self._height = 0 + self._margins = [0,0,0,0] + self.layer = 100 + self.labels = [] + self.images = [] + self._dx = [] # image offsets + self._dy = [] + self.set_image(image) + self._sprites.append_to_list(self) + + def set_image(self, image, i=0, dx=0, dy=0): + while len(self.images) < i+1: + self.images.append(None) + self._dx.append(0) + self._dy.append(0) + self.images[i] = image + self._dx[i] = dx + self._dy[i] = dy + if isinstance(image, gtk.gdk.Pixbuf): + _w = image.get_width() + _h = image.get_height() + else: + _w, _h = image.get_size() + if i == 0: # Always reset width and height when base image changes. + self._width = _w + dx + self._height = _h + dy + else: + if _w + dx > self._width: + self._width = _w + dx + if _h + dy > self._height: + self._height = _h + dy + + def move(self, pos): + self.inval() + self._x,self._y = int(pos[0]),int(pos[1]) + self.inval() + + def move_relative(self, pos): + self.inval() + self._x += int(pos[0]) + self._y += int(pos[1]) + self.inval() + + def get_xy(self): + return (self._x, self._y) + + def get_dimensions(self): + return (self._width, self._height) + + def get_layer(self): + return self.layer + + def set_shape(self, image, i=0): + self.inval() + self.set_image(image, i) + self.inval() + + def set_layer(self, layer): + self._sprites.remove_from_list(self) + self.layer = layer + for i in range(self._sprites.length_of_list()): + if layer < self._sprites.get_sprite(i).layer: + self._sprites.insert_in_list(self, i) + self.inval() + return + self._sprites.append_to_list(self) + self.inval() + + def set_label(self, new_label, i=0): + self._extend_labels_array(i) + if type(new_label) is str or type(new_label) is unicode: + # pango doesn't like nulls + self.labels[i] = new_label.replace("\0"," ") + else: + self.labels[i] = str(new_label) + self.inval() + + def set_margins(self, l=0, t=0, r=0, b=0): + self._margins = [l,t,r,b] + + def _extend_labels_array(self, i): + if self._fd is None: + self.set_font('Sans') + if self._color is None: + self._color = self._sprites.cm.alloc_color('black') + while len(self.labels) < i+1: + self.labels.append(" ") + self._scale.append(self._scale[0]) + self._rescale.append(self._rescale[0]) + self._horiz_align.append(self._horiz_align[0]) + self._vert_align.append(self._vert_align[0]) + + def set_font(self, font): + self._fd = pango.FontDescription(font) + + def set_label_color(self, rgb): + self._color = self._sprites.cm.alloc_color(rgb) + + def set_label_attributes(self, scale, rescale=True, horiz_align="center", + vert_align="middle", i=0): + self._extend_labels_array(i) + self._scale[i] = scale + self._rescale[i] = rescale + self._horiz_align[i] = horiz_align + self._vert_align[i] = vert_align + + def hide(self): + self.inval() + self._sprites.remove_from_list(self) + + def inval(self): + self._sprites.area.invalidate_rect( + gtk.gdk.Rectangle(self._x,self._y,self._width,self._height), False) + + def draw(self): + for i,img in enumerate(self.images): + if isinstance(img, gtk.gdk.Pixbuf): + self._sprites.area.draw_pixbuf( + self._sprites.gc, img, 0, 0, self._x+self._dx[i], + self._y+self._dy[i]) + elif img is not None: + self._sprites.area.draw_drawable( + self._sprites.gc, img, 0, 0, self._x+self._dx[i], + self._y+self._dy[i], -1, -1) + if len(self.labels) > 0: + self.draw_label() + + def hit(self, pos): + x, y = pos + if x < self._x: + return False + if x > self._x+self._width: + return False + if y < self._y: + return False + if y > self._y+self._height: + return False + return True + + def draw_label(self): + my_width = self._width-self._margins[0]-self._margins[2] + if my_width < 0: + my_width = 0 + my_height = self._height-self._margins[1]-self._margins[3] + for i in range(len(self.labels)): + pl = self._sprites.canvas.create_pango_layout(str(self.labels[i])) + self._fd.set_size(int(self._scale[i]*pango.SCALE)) + pl.set_font_description(self._fd) + w = pl.get_size()[0]/pango.SCALE + if w > my_width: + if self._rescale[i] is True: + self._fd.set_size( + int(self._scale[i]*pango.SCALE*my_width/w)) + pl.set_font_description(self._fd) + w = pl.get_size()[0]/pango.SCALE + else: + j = len(self.labels[i])-1 + while(w > my_width and j > 0): + pl = self._sprites.canvas.create_pango_layout( + "…"+self.labels[i][len(self.labels[i])-j:]) + self._fd.set_size(int(self._scale[i]*pango.SCALE)) + pl.set_font_description(self._fd) + w = pl.get_size()[0]/pango.SCALE + j -= 1 + if self._horiz_align[i] == "center": + x = int(self._x+self._margins[0]+(my_width-w)/2) + elif self._horiz_align[i] == 'left': + x = int(self._x+self._margins[0]) + else: # right + x = int(self._x+self._width-w-self._margins[2]) + h = pl.get_size()[1]/pango.SCALE + if self._vert_align[i] == "middle": + y = int(self._y+self._margins[1]+(my_height-h)/2) + elif self._vert_align[i] == "top": + y = int(self._y+self._margins[1]) + else: # bottom + y = int(self._y+self._height-h-self._margins[3]) + self._sprites.gc.set_foreground(self._color) + self._sprites.area.draw_layout(self._sprites.gc, x, y, pl) + + def label_width(self): + max = 0 + for i in range(len(self.labels)): + pl = self._sprites.canvas.create_pango_layout(self.labels[i]) + self._fd.set_size(int(self._scale[i]*pango.SCALE)) + pl.set_font_description(self._fd) + w = pl.get_size()[0]/pango.SCALE + if w > max: + max = w + return max + + def label_safe_width(self): + return self._width-self._margins[0]-self._margins[2] + + def label_safe_height(self): + return self._height-self._margins[1]-self._margins[3] + + def label_left_top(self): + return (self._margins[0], self._margins[1]) + + def get_pixel(self, pos, i=0): + x, y = pos + x = x-self._x + y = y-self._y + if y > self.images[i].get_height()-1: + return (-1,-1,-1,-1) + try: + array = self.images[i].get_pixels() + if array is not None: + offset = (y*self.images[i].get_width()+x)*4 + r,g,b,a = ord(array[offset]), ord(array[offset+1]),\ + ord(array[offset+2]), ord(array[offset+3]) + return (r,g,b,a) + else: + return (-1,-1,-1,-1) + except IndexError: + print "Index Error: %d %d" % (len(array), offset) + return (-1,-1,-1,-1) + |