Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWalter Bender <walter@walter-laptop.(none)>2009-11-05 20:50:10 (GMT)
committer Walter Bender <walter@walter-laptop.(none)>2009-11-05 20:50:10 (GMT)
commita42a2a732c0f0b183259689d3e87dff06a8ca42f (patch)
tree5fde7aeff708c9ae2b9dcbccdd3a42e79593ec30
new project
-rw-r--r--COPYING20
-rw-r--r--VisualMatchActivity.py211
-rw-r--r--activity/activity-visualmatch.svg62
-rw-r--r--activity/activity-visualmatch.svg~83
-rw-r--r--activity/activity.info8
-rw-r--r--card.py49
-rw-r--r--grid.py63
-rw-r--r--icons/button1off.svg22
-rw-r--r--icons/button1off.svg~30
-rw-r--r--icons/button1on.svg20
-rw-r--r--icons/button1on.svg~77
-rw-r--r--icons/button2off.svg22
-rw-r--r--icons/button2off.svg~22
-rw-r--r--icons/button2on.svg20
-rw-r--r--icons/button2on.svg~20
-rw-r--r--images/card.svg16
-rwxr-xr-xsetup.py5
-rw-r--r--sprites.py161
-rw-r--r--window.py141
19 files changed, 1052 insertions, 0 deletions
diff --git a/COPYING b/COPYING
new file mode 100644
index 0000000..a817f22
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,20 @@
+Copyright (c) 2007-9, Playful Invention Company, Sugar Labs
+
+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.
+
diff --git a/VisualMatchActivity.py b/VisualMatchActivity.py
new file mode 100644
index 0000000..51f7824
--- /dev/null
+++ b/VisualMatchActivity.py
@@ -0,0 +1,211 @@
+#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.
+
+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
+
+from sprites import *
+import window
+
+SERVICE = 'org.sugarlabs.VisualMatchActivity'
+IFACE = SERVICE
+PATH = '/org/augarlabs/VisualMatchActivity'
+
+#
+# Sugar activity
+#
+class VisualMatchActivity(activity.Activity):
+
+ def __init__(self, handle):
+ super(VisualMatchActivity,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()
+
+ # Button 1
+ self.button1 = ToolButton( "button1off" )
+ self.button1.set_tooltip(_('Button 1'))
+ self.button1.props.sensitive = True
+ self.button1.connect('clicked', self._button1_cb)
+ toolbar_box.toolbar.insert(self.button1, -1)
+ self.button1.show()
+
+ # 3x3 Button
+ self.button2 = ToolButton( "button2on" )
+ self.button2.set_tooltip(_('Button 2'))
+ self.button2.props.sensitive = True
+ self.button2.connect('clicked', self._button2_cb)
+ toolbar_box.toolbar.insert(self.button2, -1)
+ self.button2.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.show()
+ toolbar_box.toolbar.insert(separator, -1)
+
+ # Label for showing status
+ self.results_label = gtk.Label(_("say something here"))
+ self.results_label.show()
+ results_toolitem = gtk.ToolItem()
+ results_toolitem.add(self.results_label)
+ toolbar_box.toolbar.insert(results_toolitem,-1)
+
+ 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.tw = window.new_window(canvas, \
+ os.path.join(activity.get_bundle_path(), \
+ 'images/card'), \
+ self)
+
+ # Read the mode from the Journal
+ try:
+ if self.metadata['status'] == 'one':
+ self.show_button1()
+ elif self.metadata['status'] == 'two':
+ self.show_button2()
+ except:
+ self.metadata['status'] = "two"
+
+
+ #
+ # Button callbacks
+ #
+ def _button1_cb(self, button):
+ self.show_button1()
+ return True
+
+ def show_button1(self):
+ self.button1.set_icon("button1on")
+ self.button2.set_icon("button2off")
+ self.metadata['status'] = "one"
+ # do something here
+
+ def _button2_cb(self, button):
+ self.show_button2()
+ return True
+
+ def show_button2(self):
+ self.button1.set_icon("button1off")
+ self.button2.set_icon("button2on")
+ self.metadata['status'] = "two"
+ # do something here
+
+ """
+ Write the additional status to the Journal
+ """
+ def write_file(self, file_path):
+ pass
+
+#
+# Project toolbar for pre-0.86 toolbars
+#
+class ProjectToolbar(gtk.Toolbar):
+
+ def __init__(self, pc):
+ gtk.Toolbar.__init__(self)
+ self.activity = pc
+
+ # Button 1
+ self.activity.button1 = ToolButton( "button1off" )
+ self.activity.button1.set_tooltip(_('Button 1'))
+ self.activity.button1.props.sensitive = True
+ self.activity.button1.connect('clicked', self.activity._button1_cb)
+ self.insert(self.activity.button1, -1)
+ self.activity.button1.show()
+
+ # Button 2
+ self.activity.button2 = ToolButton( "button2on" )
+ self.activity.button2.set_tooltip(_('Button 2'))
+ self.activity.button2.props.sensitive = True
+ self.activity.button2.connect('clicked', self.activity._button2_cb)
+ self.insert(self.activity.button2, -1)
+ self.activity.button2.show()
+
+ separator = gtk.SeparatorToolItem()
+ separator.set_draw(True)
+ self.insert(separator, -1)
+ separator.show()
+
+ # Label for showing status
+ self.activity.results_label = gtk.Label(\
+ _("say something here"))
+ self.activity.results_label.show()
+ self.activity.results_toolitem = gtk.ToolItem()
+ self.activity.results_toolitem.add(self.activity.results_label)
+ self.insert(self.activity.results_toolitem, -1)
+ self.activity.results_toolitem.show()
diff --git a/activity/activity-visualmatch.svg b/activity/activity-visualmatch.svg
new file mode 100644
index 0000000..a4128bc
--- /dev/null
+++ b/activity/activity-visualmatch.svg
@@ -0,0 +1,62 @@
+<?xml version="1.0" ?>
+<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#000">
+ <!ENTITY fill_color "#eee">
+]>
+<svg height="55px" viewBox="0 0 55 55" width="55px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" stroke="&stroke_color;" fill="&fill_color;">
+ <path
+ d="M 1,54 L 1,1 L 54,1 L 54,54 L 1,54 z"
+ stroke="&stroke_color;"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ transform="translate(0,-0.4)">
+ <rect
+ ry="8.9"
+ rx="11.0"
+ y="21.1"
+ x="18.2"
+ height="13.6"
+ width="18.6"
+ style="fill:&fill_color;;fill-opacity:1;stroke:&stroke_color;;stroke-width:1.4;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <rect
+ ry="8.9"
+ rx="11.0"
+ y="4.9"
+ x="18.2"
+ height="13.6"
+ width="18.6"
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.4;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <g
+ transform="translate(65.8,18.5)">
+ <rect
+ style="fill:&fill_color;;fill-opacity:1;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.4;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ width="18.6"
+ height="13.6"
+ x="-47.6"
+ y="18.9"
+ rx="11.0"
+ ry="8.9" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -44.976185,30.770204 c 4.589517,-11.530164 4.616819,-11.635243 4.616819,-11.635243" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -43.127191,31.961097 c 4.904753,-12.826136 5.177239,-12.826136 5.177239,-12.826136 l 0,0" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -40.717775,31.961097 c 4.904752,-12.826136 5.177239,-12.826136 5.177239,-12.826136 l 0,0" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -38.308364,31.961097 c 4.904753,-12.826136 4.862003,-12.230689 4.862003,-12.230689" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -35.898948,31.961097 c 4.414384,-11.109849 4.301582,-10.759586 4.301582,-10.759586" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -33.384459,31.575808 c 3.538728,-9.008273 3.460952,-8.973246 3.460952,-8.973246" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.2px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -46.650044,29.264074 c 3.853964,-9.848903 3.811214,-9.813877 3.811214,-9.813877" />
+ </g>
+ </g>
+</svg>
diff --git a/activity/activity-visualmatch.svg~ b/activity/activity-visualmatch.svg~
new file mode 100644
index 0000000..df68bf3
--- /dev/null
+++ b/activity/activity-visualmatch.svg~
@@ -0,0 +1,83 @@
+<?xml version="1.0" ?>
+<!DOCTYPE svg PUBLIC '-//W3C//DTD SVG 1.1//EN' 'http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd' [
+ <!ENTITY stroke_color "#000">
+ <!ENTITY fill_color "#eee">
+]>
+<svg height="55px" viewBox="0 0 55 55" width="55px" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.5" stroke="&stroke_color;" fill="&fill_color;">
+ <path
+ d="M 1,54 L 1,1 L 54,1 L 54,54 L 1,54 z"
+ id="path2395"
+ stroke="&stroke_color;"
+ style="fill:none;fill-opacity:1;fill-rule:evenodd;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+ <g
+ id="g5200"
+ transform="translate(0,-0.40254307)">
+ <rect
+ ry="8.8859863"
+ rx="11.00049"
+ y="21.123711"
+ x="18.221169"
+ height="13.557661"
+ width="18.557661"
+ id="rect2827"
+ style="fill:&fill_color;;fill-opacity:1;stroke:#000000;stroke-width:1.4423393;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <rect
+ ry="8.8859863"
+ rx="11.00049"
+ y="4.8906612"
+ x="18.221169"
+ height="13.557661"
+ width="18.557661"
+ id="rect2827-4"
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.4423393;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
+ <g
+ transform="translate(65.786775,18.5)"
+ id="g5190">
+ <rect
+ style="fill:&fill_color;;fill-opacity:1;fill-rule:evenodd;stroke:&stroke_color;;stroke-width:1.4423393;stroke-linecap:square;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect2827-6"
+ width="18.557661"
+ height="13.557661"
+ x="-47.565605"
+ y="18.856764"
+ rx="11.00049"
+ ry="8.8859863" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -44.976185,30.770204 c 4.589517,-11.530164 4.616819,-11.635243 4.616819,-11.635243"
+ id="path5074"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -43.127191,31.961097 c 4.904753,-12.826136 5.177239,-12.826136 5.177239,-12.826136 l 0,0"
+ id="path5074-6"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -40.717775,31.961097 c 4.904752,-12.826136 5.177239,-12.826136 5.177239,-12.826136 l 0,0"
+ id="path5074-3"
+ sodipodi:nodetypes="ccc" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -38.308364,31.961097 c 4.904753,-12.826136 4.862003,-12.230689 4.862003,-12.230689"
+ id="path5074-4"
+ sodipodi:nodetypes="cc"
+ inkscape:transform-center-x="2.206655" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -35.898948,31.961097 c 4.414384,-11.109849 4.301582,-10.759586 4.301582,-10.759586"
+ id="path5074-2"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -33.384459,31.575808 c 3.538728,-9.008273 3.460952,-8.973246 3.460952,-8.973246"
+ id="path5074-7"
+ sodipodi:nodetypes="cc" />
+ <path
+ style="fill:none;stroke:&stroke_color;;stroke-width:1.23778403px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+ d="m -46.650044,29.264074 c 3.853964,-9.848903 3.811214,-9.813877 3.811214,-9.813877"
+ id="path5074-78"
+ sodipodi:nodetypes="cc" />
+ </g>
+ </g>
+</svg>
diff --git a/activity/activity.info b/activity/activity.info
new file mode 100644
index 0000000..7298b29
--- /dev/null
+++ b/activity/activity.info
@@ -0,0 +1,8 @@
+[Activity]
+name = Visual Match
+activity_version = 4
+license = GPLv3
+bundle_id = org.sugarlabs.VisualMatchActivity
+exec = sugar-activity VisualMatchActivity.VisualMatchActivity
+icon = activity-visualmatch
+show_launcher = yes
diff --git a/card.py b/card.py
new file mode 100644
index 0000000..4a8aaac
--- /dev/null
+++ b/card.py
@@ -0,0 +1,49 @@
+#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.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+import os.path
+
+from sprites import *
+
+#
+# class for defining individual cards
+#
+class Card:
+ def __init__(self,tw,pattern):
+ # what do we need to know about each card?
+ # self.??? = ???
+ # create sprite from svg file
+ self.spr = sprNew(tw, 0, 0,\
+ self.load_image(tw.path,tw.card_dim*tw.scale))
+ self.spr.label = ""
+
+ def draw_card(self):
+ setlayer(self.spr,2000)
+ draw(self.spr)
+
+ def load_image(self, file, wh):
+ return gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(file + \
+ '.svg'), \
+ int(wh), int(wh))
+
diff --git a/grid.py b/grid.py
new file mode 100644
index 0000000..b04e5a1
--- /dev/null
+++ b/grid.py
@@ -0,0 +1,63 @@
+#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.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+
+from sprites import *
+from card import *
+
+#
+# class for defining 4x3 matrix of cards
+#
+class Grid:
+ def __init__(self, tw):
+ # the playing surface is a 3x4 grid
+ self.grid = []
+ # create the deck of cards
+ self.deck = {}
+ # stuff to keep around for the graphics
+ self.w = tw.width
+ self.h = tw.height
+ self.d = tw.card_dim
+ self.s = tw.scale
+ # Initialize the deck of cards
+ # some loop through all the patterns
+ # self.deck[i] = Card(tw,pattern)
+
+ # shuffle the deck
+ def shuffle(self,tw):
+ return
+
+ # initial layout of 12 cards on the table
+ def start(self, tw):
+ return
+
+ # draw a card from the deck
+ def draw_a_card(self, tw):
+ return
+
+ # find a set
+ def find_a_set(self, tw):
+ return
+
+
diff --git a/icons/button1off.svg b/icons/button1off.svg
new file mode 100644
index 0000000..bbc5058
--- /dev/null
+++ b/icons/button1off.svg
@@ -0,0 +1,22 @@
+<?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.0"
+ width="55"
+ height="55">
+ <rect
+ style="fill:#808080;fill-opacity:1;stroke:#808080;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;"
+ width="51"
+ height="51"
+ x="2"
+ y="2"
+ ry="7.0"
+ rx="8.1" />
+ <text
+ x="13.5"
+ y="42.0"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.5"
+ y="42.0">1</tspan></text>
+</svg>
diff --git a/icons/button1off.svg~ b/icons/button1off.svg~
new file mode 100644
index 0000000..b3e9844
--- /dev/null
+++ b/icons/button1off.svg~
@@ -0,0 +1,30 @@
+<?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.0"
+ width="55"
+ height="55"
+ id="svg2">
+ <defs
+ id="defs4" />
+ <rect
+ style="fill:#808080;fill-opacity:1;stroke:#808080;stroke-width:4.05900620999999973;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect2817"
+ width="50.94099"
+ height="50.940994"
+ x="2.0295048"
+ y="2.0295029"
+ ry="7.0263433"
+ rx="8.1506357" />
+ <text
+ x="13.496094"
+ y="42.060547"
+ id="text2394"
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.496094"
+ y="42.060547"
+ id="tspan2396">1</tspan></text>
+</svg>
diff --git a/icons/button1on.svg b/icons/button1on.svg
new file mode 100644
index 0000000..ebe7c37
--- /dev/null
+++ b/icons/button1on.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55">
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:#808080;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ width="51"
+ height="51"
+ x="2"
+ y="2"
+ ry="7.0"
+ rx="8.1" />
+ <text
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.5"
+ y="42.0"
+ id="tspan2396">1</tspan></text>
+</svg>
diff --git a/icons/button1on.svg~ b/icons/button1on.svg~
new file mode 100644
index 0000000..a434afb
--- /dev/null
+++ b/icons/button1on.svg~
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<!-- Created with Inkscape (http://www.inkscape.org/) -->
+
+<svg
+ xmlns:dc="http://purl.org/dc/elements/1.1/"
+ xmlns:cc="http://creativecommons.org/ns#"
+ xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+ xmlns:svg="http://www.w3.org/2000/svg"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+ xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+ version="1.0"
+ width="55"
+ height="55"
+ id="svg2"
+ inkscape:version="0.47pre4 r22446"
+ sodipodi:docname="Aon.svg">
+ <metadata
+ id="metadata9">
+ <rdf:RDF>
+ <cc:Work
+ rdf:about="">
+ <dc:format>image/svg+xml</dc:format>
+ <dc:type
+ rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+ </cc:Work>
+ </rdf:RDF>
+ </metadata>
+ <sodipodi:namedview
+ pagecolor="#ffffff"
+ bordercolor="#666666"
+ borderopacity="1"
+ objecttolerance="10"
+ gridtolerance="10"
+ guidetolerance="10"
+ inkscape:pageopacity="0"
+ inkscape:pageshadow="2"
+ inkscape:window-width="1680"
+ inkscape:window-height="972"
+ id="namedview7"
+ showgrid="false"
+ inkscape:zoom="13.181818"
+ inkscape:cx="14.110345"
+ inkscape:cy="27.5"
+ inkscape:window-x="0"
+ inkscape:window-y="27"
+ inkscape:window-maximized="1"
+ inkscape:current-layer="svg2" />
+ <defs
+ id="defs4">
+ <inkscape:perspective
+ sodipodi:type="inkscape:persp3d"
+ inkscape:vp_x="0 : 27.5 : 1"
+ inkscape:vp_y="0 : 1000 : 0"
+ inkscape:vp_z="55 : 27.5 : 1"
+ inkscape:persp3d-origin="27.5 : 18.333333 : 1"
+ id="perspective11" />
+ </defs>
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:#808080;stroke-width:4.05900620999999973;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ id="rect2817"
+ width="50.94099"
+ height="50.940994"
+ x="2.0295048"
+ y="2.0295029"
+ ry="7.0263433"
+ rx="8.1506357" />
+ <text
+ x="13.496094"
+ y="42.060547"
+ id="text2394"
+ xml:space="preserve"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.496094"
+ y="42.060547"
+ id="tspan2396">A</tspan></text>
+</svg>
diff --git a/icons/button2off.svg b/icons/button2off.svg
new file mode 100644
index 0000000..d184b94
--- /dev/null
+++ b/icons/button2off.svg
@@ -0,0 +1,22 @@
+<?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.0"
+ width="55"
+ height="55">
+ <rect
+ style="fill:#808080;fill-opacity:1;stroke:#808080;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;"
+ width="51"
+ height="51"
+ x="2"
+ y="2"
+ ry="7.0"
+ rx="8.1" />
+ <text
+ x="13.5"
+ y="42.0"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.5"
+ y="42.0">2</tspan></text>
+</svg>
diff --git a/icons/button2off.svg~ b/icons/button2off.svg~
new file mode 100644
index 0000000..bbc5058
--- /dev/null
+++ b/icons/button2off.svg~
@@ -0,0 +1,22 @@
+<?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.0"
+ width="55"
+ height="55">
+ <rect
+ style="fill:#808080;fill-opacity:1;stroke:#808080;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;"
+ width="51"
+ height="51"
+ x="2"
+ y="2"
+ ry="7.0"
+ rx="8.1" />
+ <text
+ x="13.5"
+ y="42.0"
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.5"
+ y="42.0">1</tspan></text>
+</svg>
diff --git a/icons/button2on.svg b/icons/button2on.svg
new file mode 100644
index 0000000..39a0f80
--- /dev/null
+++ b/icons/button2on.svg
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55">
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:#808080;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ width="51"
+ height="51"
+ x="2"
+ y="2"
+ ry="7.0"
+ rx="8.1" />
+ <text
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.5"
+ y="42.0"
+ id="tspan2396">2</tspan></text>
+</svg>
diff --git a/icons/button2on.svg~ b/icons/button2on.svg~
new file mode 100644
index 0000000..ebe7c37
--- /dev/null
+++ b/icons/button2on.svg~
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ xmlns="http://www.w3.org/2000/svg"
+ version="1.0"
+ width="55"
+ height="55">
+ <rect
+ style="fill:#000000;fill-opacity:1;stroke:#808080;stroke-width:4;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+ width="51"
+ height="51"
+ x="2"
+ y="2"
+ ry="7.0"
+ rx="8.1" />
+ <text
+ style="font-size:40px;font-style:normal;font-weight:normal;fill:#ffffff;fill-opacity:1;font-family:Bitstream Vera Sans"><tspan
+ x="13.5"
+ y="42.0"
+ id="tspan2396">1</tspan></text>
+</svg>
diff --git a/images/card.svg b/images/card.svg
new file mode 100644
index 0000000..e9ad27d
--- /dev/null
+++ b/images/card.svg
@@ -0,0 +1,16 @@
+<?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.0"
+ width="135"
+ height="135.00002"
+ id="svg3193">
+ <defs
+ id="defs3195" />
+ <path
+ d="M 1.1368684e-13,135 L 1.1368684e-13,-2.8421709e-14 L 135,-2.8421709e-14 L 135,135 L 1.1368684e-13,135 z"
+ id="path2395"
+ style="fill:#ff0000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.34653473px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+</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..e1b037e
--- /dev/null
+++ b/sprites.py
@@ -0,0 +1,161 @@
+# -*- coding: utf-8 -*-
+
+#Copyright (c) 2007-8, Playful Invention Company.
+#Copyright (c) 2008-9, 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.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+import gobject
+import pango
+class taSprite: pass
+
+def findsprite(tw,pos):
+ list = tw.sprites[:]
+ list.reverse()
+ for s in list:
+ if hit(s,pos): return s
+ return None
+
+def redrawsprites(tw):
+ for s in tw.sprites: draw(s)
+
+def sprNew(tw,x,y,image,altlabel=False):
+ spr = taSprite()
+ spr.tw, spr.x, spr.y = tw,x,y
+ setimage(spr,image)
+ spr.label = None
+ spr.ds_id = None
+ if altlabel:
+ spr.draw_label = draw_label2
+ else: spr.draw_label = draw_label1
+ return spr
+
+def setimage(spr,image):
+ spr.image = image
+ if isinstance(image,gtk.gdk.Pixbuf):
+ spr.width = image.get_width()
+ spr.height = image.get_height()
+ else: spr.width,spr.height=image.get_size()
+
+def move(spr,pos):
+ inval(spr)
+ spr.x,spr.y = pos
+ inval(spr)
+
+def setshape(spr,image):
+ inval(spr)
+ setimage(spr,image)
+ inval(spr)
+
+def setshapex(spr):
+ inval(spr)
+
+def setlayer(spr, layer):
+ sprites = spr.tw.sprites
+ if spr in sprites: sprites.remove(spr)
+ spr.layer = layer
+ for i in range(len(sprites)):
+ if layer < sprites[i].layer:
+ sprites.insert(i, spr)
+ inval(spr)
+ return
+ sprites.append(spr)
+ inval(spr)
+
+def hide(spr):
+ if spr not in spr.tw.sprites: return
+ inval(spr)
+ spr.tw.sprites.remove(spr)
+
+def setlabel(spr,label):
+ spr.label = label
+ inval(spr)
+
+def inval(spr):
+ spr.tw.area.invalidate_rect(gtk.gdk.Rectangle(spr.x,spr.y,spr.width, \
+ spr.height), False)
+
+def draw(spr):
+ if isinstance(spr.image,gtk.gdk.Pixbuf):
+ spr.tw.area.draw_pixbuf(spr.tw.gc, spr.image, 0, 0, spr.x, spr.y)
+ else:
+ spr.tw.area.draw_drawable(spr.tw.gc,spr.image,0,0,spr.x,spr.y,-1,-1)
+ if spr.label!=None:
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name'):
+ name = spr.proto.name
+ else:
+ name = ""
+ spr.draw_label(spr,str(spr.label))
+
+def hit(spr,pos):
+ x,y = pos
+ if x<spr.x: return False
+ if x>spr.x+spr.width: return False
+ if y<spr.y: return False
+ if y>spr.y+spr.height: return False
+ if isinstance(spr.image,gtk.gdk.Pixmap): return True
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name') and \
+ spr.proto.name == 'journal':
+ return True
+ dx,dy = x-spr.x, y-spr.y
+ try:
+ return ord(spr.image.get_pixels()[(dy*spr.width+dx)*4+3]) == 255
+ except IndexError:
+ if hasattr(spr, 'proto') and hasattr(spr.proto, 'name'):
+ print spr.proto.name
+ print "IndexError: string index out of range" + str(dx) + " " \
+ + str(dy) + " " + str(spr.width) + " " + str(spr.height)
+ return True
+
+def draw_label(spr, label, myscale, center_flag, truncate_flag):
+ fd = pango.FontDescription('Sans')
+ fd.set_size(int(myscale*spr.tw.scale*pango.SCALE))
+ if type(label) == str or type(label) == unicode:
+ mylabel = label.replace("\0"," ")
+ l = len(mylabel)
+ if truncate_flag and l > 8:
+ pl = spr.tw.canvas.create_pango_layout("..."+mylabel[l-8:])
+ else:
+ pl = spr.tw.canvas.create_pango_layout(mylabel)
+ pl.set_font_description(fd)
+ if center_flag:
+ swidth = pl.get_size()[0]/pango.SCALE
+ centerx = spr.x+spr.width/2
+ x = int(centerx-swidth/2)
+ else:
+ x = spr.x+70
+ sheight = pl.get_size()[1]/pango.SCALE
+ centery = spr.y+spr.height/2
+ y = int(centery-sheight/2)
+ spr.tw.gc.set_foreground(spr.tw.msgcolor)
+ spr.tw.area.draw_layout(spr.tw.gc, x, y, pl)
+ else:
+ print type(label)
+
+# used for most things
+def draw_label1(spr, label):
+ draw_label(spr, label, 12, True, True)
+
+# used for status blocks
+def draw_label2(spr, label):
+ draw_label(spr, str(label), 14, False, False)
+
diff --git a/window.py b/window.py
new file mode 100644
index 0000000..8ee6559
--- /dev/null
+++ b/window.py
@@ -0,0 +1,141 @@
+#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.
+
+import pygtk
+pygtk.require('2.0')
+import gtk
+from gettext import gettext as _
+
+try:
+ from sugar.graphics import style
+ GRID_CELL_SIZE = style.GRID_CELL_SIZE
+except:
+ GRID_CELL_SIZE = 0
+
+from grid import *
+from card import *
+
+from math import sqrt
+
+CARD_DIM = 135
+
+class taWindow: pass
+
+#
+# handle launch from both within and without of Sugar environment
+#
+def new_window(canvas, path, parent=None):
+ tw = taWindow()
+ tw.path = path
+ tw.activity = parent
+
+ # starting from command line
+ # we have to do all the work that was done in CardSortActivity.py
+ if parent is None:
+ tw.sugar = False
+ tw.canvas = canvas
+
+ # starting from Sugar
+ else:
+ tw.sugar = True
+ tw.canvas = canvas
+ parent.show_all()
+
+ tw.canvas.set_flags(gtk.CAN_FOCUS)
+ tw.canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK)
+ tw.canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK)
+ tw.canvas.connect("expose-event", _expose_cb, tw)
+ tw.canvas.connect("button-press-event", _button_press_cb, tw)
+ tw.canvas.connect("button-release-event", _button_release_cb, tw)
+ tw.canvas.connect("key_press_event", _keypress_cb, tw)
+ tw.width = gtk.gdk.screen_width()
+ tw.height = gtk.gdk.screen_height()-GRID_CELL_SIZE
+ tw.card_dim = CARD_DIM
+ tw.scale = 0.8 * tw.height/(tw.card_dim*3)
+ tw.area = tw.canvas.window
+ tw.gc = tw.area.new_gc()
+ tw.cm = tw.gc.get_colormap()
+ tw.msgcolor = tw.cm.alloc_color('black')
+ tw.sprites = []
+
+ # make the cards, the deck and start playing...
+ tw.deck = Grid(tw)
+ tw.deck.shuffle(tw)
+ tw.deck.start(tw)
+
+ # Start doing something
+ tw.keypress = ""
+ tw.press = -1
+ tw.release = -1
+ tw.start_drag = [0,0]
+
+ return tw
+
+#
+# Button press
+#
+def _button_press_cb(win, event, tw):
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ tw.start_drag = [x,y]
+ spr = findsprite(tw,(x,y))
+ if spr is None:
+ tw.press = None
+ tw.release = None
+ return True
+ # take note of card under button press
+ tw.press = spr
+ return True
+
+#
+# Button release
+#
+def _button_release_cb(win, event, tw):
+ win.grab_focus()
+ x, y = map(int, event.get_coords())
+ spr = findsprite(tw,(x,y))
+ if spr is None:
+ tw.press = None
+ tw.release = None
+ return True
+ # take note of card under button release
+ tw.release = spr
+ return True
+
+#
+# Keypress
+#
+def _keypress_cb(area, event, tw):
+ tw.keypress = gtk.gdk.keyval_name(event.keyval)
+ return True
+
+#
+# Repaint
+#
+def _expose_cb(win, event, tw):
+ redrawsprites(tw)
+ return True
+
+#
+# callbacks
+#
+def _destroy_cb(win, event, tw):
+ gtk.main_quit()
+