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)>2010-02-24 14:41:48 (GMT)
committer Walter Bender <walter@walter-laptop.(none)>2010-02-24 14:41:48 (GMT)
commitd0f2e2eb2995c01789f8604f80b7e4d202388192 (patch)
treebebc2551c8b6df9f7af1c3e29c165e5961be2fc1
parentbba203b7b8333dca6e27ff7f365f2eaa620efd2f (diff)
majore refactoring
-rw-r--r--CardSortActivity.py11
-rw-r--r--NEWS8
-rw-r--r--activity/activity.info2
-rw-r--r--card.py31
-rwxr-xr-xcardsort.py63
-rw-r--r--grid.py172
-rw-r--r--sprites.py463
-rw-r--r--window.py24
8 files changed, 513 insertions, 261 deletions
diff --git a/CardSortActivity.py b/CardSortActivity.py
index 1f10c38..848454e 100644
--- a/CardSortActivity.py
+++ b/CardSortActivity.py
@@ -67,7 +67,7 @@ class CardSortActivity(activity.Activity):
activity_button.show()
# 2x2 Button
- self.grid2x2 = ToolButton( "2x2off" )
+ self.grid2x2 = ToolButton( "2x2on" )
self.grid2x2.set_tooltip(_('2x2'))
self.grid2x2.props.sensitive = True
self.grid2x2.connect('clicked', self._grid2x2_cb)
@@ -91,7 +91,7 @@ class CardSortActivity(activity.Activity):
self.grid2x3.show()
# 3x3 Button
- self.grid3x3 = ToolButton( "3x3on" )
+ self.grid3x3 = ToolButton( "3x3off" )
self.grid3x3.set_tooltip(_('3x3'))
self.grid3x3.props.sensitive = True
self.grid3x3.connect('clicked', self._grid3x3_cb)
@@ -159,7 +159,8 @@ class CardSortActivity(activity.Activity):
elif self.metadata['grid'] == '3x3':
self.show_grid3x3()
except:
- self.metadata['grid'] = "3x3"
+ self.metadata['grid'] = "2x2"
+ self.show_grid2x2()
#
@@ -233,7 +234,7 @@ class ProjectToolbar(gtk.Toolbar):
self.activity = pc
# 2x2 Button
- self.activity.grid2x2 = ToolButton( "2x2off" )
+ self.activity.grid2x2 = ToolButton( "2x2on" )
self.activity.grid2x2.set_tooltip(_('2x2'))
self.activity.grid2x2.props.sensitive = True
self.activity.grid2x2.connect('clicked', self.activity._grid2x2_cb)
@@ -257,7 +258,7 @@ class ProjectToolbar(gtk.Toolbar):
self.activity.grid2x3.show()
# 3x3 Button
- self.activity.grid3x3 = ToolButton( "3x3on" )
+ self.activity.grid3x3 = ToolButton( "3x3off" )
self.activity.grid3x3.set_tooltip(_('3x3'))
self.activity.grid3x3.props.sensitive = True
self.activity.grid3x3.connect('clicked', self.activity._grid3x3_cb)
diff --git a/NEWS b/NEWS
index 331a02c..c14c555 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,11 @@
+5
+
+* default grid is 2x2
+* randomize initial orientation
+* more game options
+* new sprite library
+* license text
+
4
* 2x2, 3x2, 2x3 and 3x3 grids
diff --git a/activity/activity.info b/activity/activity.info
index 4209fd6..5b06687 100644
--- a/activity/activity.info
+++ b/activity/activity.info
@@ -1,6 +1,6 @@
[Activity]
name = Card Sort
-activity_version = 4
+activity_version = 5
license = GPLv3
bundle_id = org.sugarlabs.CardSortActivity
exec = sugar-activity CardSortActivity.CardSortActivity
diff --git a/card.py b/card.py
index 5991084..fdca7a0 100644
--- a/card.py
+++ b/card.py
@@ -1,4 +1,4 @@
-#Copyright (c) 2009, Walter Bender
+#Copyright (c) 2009,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
@@ -24,7 +24,7 @@ import gtk
import gobject
import os.path
-from sprites import *
+from sprites import Sprite
#
# class for defining individual cards
@@ -40,14 +40,14 @@ class Card:
self.south = c[2]
self.west = c[3]
self.orientation = 0
+ self.images = []
+ self.images.append(self.load_image(tw.path,i,tw.card_dim*tw.scale))
+ for j in range(3):
+ self.images.append(self.images[j].rotate_simple(90))
# create sprite from svg file
- self.spr = sprNew(tw, x, y,\
- self.load_image(tw.path,i,tw.card_dim*tw.scale))
- self.spr.label = i
-
- def draw_card(self):
- setlayer(self.spr,2000)
- draw(self.spr)
+ self.spr = Sprite(tw.sprites, x, y,self.images[0])
+ self.spr.set_label(i)
+ self.spr.draw()
def load_image(self, file, i, wh):
return gtk.gdk.pixbuf_new_from_file_at_size(os.path.join(file + \
@@ -55,8 +55,9 @@ class Card:
'.svg'), \
int(wh), int(wh))
- def reload_image(self, tw, i):
- self.spr.image = self.load_image(tw.path,i,tw.card_dim*tw.scale)
+ def reset_image(self, tw, i):
+ while self.orientation != 0:
+ self.rotate_ccw()
def set_orientation(self,r,rotate_spr=True):
while r != self.orientation:
@@ -70,11 +71,11 @@ class Card:
self.south = self.west
self.west = tmp
self.orientation += 90
- if self.orientation > 359:
- self.orientation -= 360
+ if self.orientation == 360:
+ self.orientation = 0
if rotate_spr is True:
- tmp = self.spr.image.rotate_simple(90)
- self.spr.image = tmp
+ self.spr.images[0] = self.images[int(self.orientation/90)]
+ self.spr.draw()
def print_card(self):
print "(" + str(self.north) + "," + str(self.east) + \
diff --git a/cardsort.py b/cardsort.py
index fa8e7e6..623fc8b 100755
--- a/cardsort.py
+++ b/cardsort.py
@@ -45,10 +45,31 @@ class CardSortMain:
self.win.connect("delete_event", lambda w,e: gtk.main_quit())
menu = gtk.Menu()
+
+ menu_items = gtk.MenuItem(_("2x2"))
+ menu.append(menu_items)
+ menu_items.connect("activate", self._grid2x2_cb)
+ menu_items.show()
+ menu_items = gtk.MenuItem(_("2x3"))
+ menu.append(menu_items)
+ menu_items.connect("activate", self._grid2x3_cb)
+ menu_items.show()
+ menu_items = gtk.MenuItem(_("3x2"))
+ menu.append(menu_items)
+ menu_items.connect("activate", self._grid3x2_cb)
+ menu_items.show()
+ menu_items = gtk.MenuItem(_("3x3"))
+ menu.append(menu_items)
+ menu_items.connect("activate", self._grid3x3_cb)
+ menu_items.show()
+
+ """
menu_items = gtk.MenuItem(_("Solve it"))
menu.append(menu_items)
menu_items.connect("activate", self._solve_cb)
menu_items.show()
+ """
+
root_menu = gtk.MenuItem("Tools")
root_menu.show()
root_menu.set_submenu(menu)
@@ -69,16 +90,40 @@ class CardSortMain:
menu_bar.append(root_menu)
self.win.show_all()
- # Join the activity
+ # Start the activity
self.tw = window.new_window(canvas, \
os.path.join(os.path.abspath('.'), \
'images/card'))
self.tw.win = self.win
+ self.tw.test = self.tw.grid.test2x2
+ self.tw.grid.reset2x2(self.tw)
def set_title(self, title):
self.win.set_title(title)
+ #
+ # Grid resize callbacks
+ #
+ def _grid2x2_cb(self, button):
+ self.tw.test = self.tw.grid.test2x2
+ self.tw.grid.reset2x2(self.tw)
+
+ def _grid3x2_cb(self, button):
+ self.tw.test = self.tw.grid.test3x2
+ self.tw.grid.reset3x2(self.tw)
+
+ def _grid2x3_cb(self, button):
+ self.tw.test = self.tw.grid.test2x3
+ self.tw.grid.reset2x3(self.tw)
+
+ def _grid3x3_cb(self, button):
+ self.tw.test = self.tw.grid.test3x3
+ self.tw.grid.reset3x3(self.tw)
+
def _solve_cb(self, widget):
+ self.show_all()
+ self.set_grid([0,1,2,3,4,5,6,7,8])
+ self.set_orientations([0,0,0,0,0,0,0,0,0])
self.rotation_sets = get_rotation_sets()
counter = 0
a = [0,1,2,3,4,5,6,7,8]
@@ -110,22 +155,9 @@ class CardSortMain:
.set_orientation(self.rotation_sets[o][r],True)
self.tw.grid.print_grid()
self.tw.grid.print_orientations()
- sprites.redrawsprites(self.tw)
+ self.tw.sprites.redraw_sprites()
return True
return False
-"""
-def permute(inputData, outputSoFar):
- for elem in inputData:
- if elem not in outputSoFar:
- outputSoFar.append(elem)
- if len(outputSoFar) == len(inputData):
- print outputSoFar
- else:
- permute(inputData, outputSoFar) # --- Recursion
- outputSoFar.pop()
-
-permute([0,1,2,3,4,5,6,7,8], [])
-"""
class Permutation:
def __init__(self, justalist):
@@ -144,7 +176,6 @@ class Permutation:
yield v
self._sofar.pop()
-
def main():
gtk.main()
return 0
diff --git a/grid.py b/grid.py
index db3ccb2..67646a5 100644
--- a/grid.py
+++ b/grid.py
@@ -23,7 +23,7 @@ pygtk.require('2.0')
import gtk
import gobject
-from sprites import *
+from random import uniform
from card import *
CARD_DEFS = ((1,3,-2,-3),(2,3,-3,-2),(2,3,-4,-4),
@@ -32,96 +32,110 @@ CARD_DEFS = ((1,3,-2,-3),(2,3,-3,-2),(2,3,-4,-4),
#
-# class for defining 3x3 matrix of cards
+# Class for defining 3x3 matrix of cards
#
class Grid:
- # 012
- # 345
- # 678
+ """
+ Grid positions correspond to one of:
+ 012 01x 012 01x
+ 345 34x 345 34x
+ 678 xxx xxx 67x
+ """
def __init__(self, tw):
- self.grid = [0,1,2,3,4,5,6,7,8,9]
+ self.grid = [0,1,2,3,4,5,6,7,8]
self.card_table = {}
- # stuff to keep around for the graphics
- self.w = tw.width
- self.h = tw.height
- self.d = tw.card_dim
- self.s = tw.scale
+ # Stuff to keep around for the graphics
+ self.w = int(tw.width)
+ self.h = int(tw.height)
+ self.d = int(tw.card_dim*tw.scale)
# Initialize the cards
i = 0 # i is used as a label on the sprite
- x = int((self.w-(self.d*3*self.s))/2)
- y = int((self.h-(self.d*3*self.s))/2)
for c in CARD_DEFS:
+ x, y = self.i_to_xy(i)
self.card_table[i] = Card(tw,c,i,x,y)
- self.card_table[i].draw_card()
- x += int(self.d*self.s)
- if x > (self.w+(self.d*2*self.s))/2:
- x = int((self.w-(self.d*3*self.s))/2)
- y += int(self.d*self.s)
i += 1
- # reset everything to initial layout
+ # Utility functions
+ def i_to_xy(self, i):
+ return int((self.w-(self.d*3))/2) + (i%3)*self.d,\
+ int((self.h-(self.d*3))/2) + int(i/3)*self.d
+
+ def xy_to_i(self, x, y):
+ return (x-int((self.w-(self.d*3))/2))/self.d +\
+ ((y-int((self.h-(self.d*3))/2))/self.d)*3
+
+ def set_orientation(self, neworientation, draw_card=True):
+ for c in range(9):
+ self.card_table[c].set_orientation(neworientation[c], draw_card)
+
+ def randomize_orientation(self, draw_card=True):
+ olist = [0,90,180,270]
+ for c in range(9):
+ o = int(uniform(0,4))
+ self.card_table[c].set_orientation(olist[o], draw_card)
+
+ def set_grid(self, newgrid):
+ for i, c in enumerate(newgrid):
+ x, y = self.i_to_xy(i)
+ self.card_table[c].spr.move((x,y))
+ self.grid[i] = c
+
+ def show_all(self):
+ for i in range(9):
+ self.card_table[i].spr.set_layer(100)
+
+ def hide_list(self, list):
+ for i in list:
+ self.card_table[i].spr.hide()
+
+ # Reset everything to initial layout
def reset3x3(self, tw):
+ self.show_all()
self.set_grid([0,1,2,3,4,5,6,7,8])
- self.set_orientation([0,0,0,0,0,0,0,0,0])
- for i in range(9):
- self.card_table[i].reload_image(tw, i)
- self.print_grid()
+ self.randomize_orientation()
- # TWO_BY_TWO = ((7,5,0,3),(7,4,5,2),(1,3,5,8),(4,5,6,1))
- # reset everything to initial layout
+ # Two by two = ((7,5,0,3),(7,4,5,2),(1,3,5,8),(4,5,6,1))
def reset2x2(self, tw):
- self.set_grid([4,5,0,6,1,2,3,7,8])
- self.set_orientation([0,0,0,0,0,0,0,0,0])
- for i in range(9):
- self.card_table[i].reload_image(tw, i)
- for i in (0,2,3,7,8):
- hide(self.card_table[i].spr)
- self.print_grid()
-
- # THREE_BY_TWO = ((7,5,0,2,4,3),(5,6,1,4,3,8))
- # reset everything to initial layout
+ self.show_all()
+ self.randomize_orientation()
+ r = int(uniform(0,4))
+ if r == 0:
+ self.set_grid([7,5,1,0,3,2,4,6,8])
+ self.hide_list([1,2,4,6,8])
+ elif r == 1:
+ self.set_grid([7,4,1,5,2,3,0,6,8])
+ self.hide_list([0,1,3,6,8])
+ elif r == 2:
+ self.set_grid([1,3,2,5,8,4,6,7,0])
+ self.hide_list([2,4,6,7,0])
+ else:
+ self.set_grid([4,5,0,6,1,2,3,7,8])
+ self.hide_list([0,2,3,7,8])
+
+ # Three by two = ((7,5,0,2,4,3),(5,6,1,4,3,8))
def reset3x2(self, tw):
- self.set_grid([7,5,0,2,4,3,1,6,8])
- self.set_orientation([0,0,0,0,0,0,0,0,0])
- for i in range(9):
- self.card_table[i].reload_image(tw, i)
- for i in (1,6,8):
- hide(self.card_table[i].spr)
- self.print_grid()
-
- # TWO_BY_THREE = ((5,2,4,6,1,7),(7,1,2,5,8,0))
+ self.show_all()
+ self.randomize_orientation()
+ r = int(uniform(0,2))
+ if r == 0:
+ self.set_grid([7,5,0,2,4,3,1,6,8])
+ self.hide_list([1,6,8])
+ else:
+ self.set_grid([5,6,1,4,3,8,0,2,7])
+ self.hide_list([0,2,7])
+
+ # Two by three = ((5,2,4,6,1,7),(7,1,2,5,8,0))
# reset everything to initial layout
def reset2x3(self, tw):
- self.set_grid([5,2,0,4,6,3,1,7,8])
- self.set_orientation([0,0,0,0,0,0,0,0,0])
- for i in range(9):
- self.card_table[i].reload_image(tw, i)
- for i in (0,3,8):
- hide(self.card_table[i].spr)
- self.print_grid()
-
- # force a specific layout
- def set_grid(self, newgrid):
- x = int((self.w-(self.d*3*self.s))/2)
- y = int((self.h-(self.d*3*self.s))/2)
- j = 0
- for c in newgrid:
- for i in range(9):
- if self.card_table[i].spr.label == c:
- self.card_table[i].spr.x = x
- self.card_table[i].spr.y = y
- self.card_table[i].draw_card()
- x += int(self.d*self.s)
- if x > (self.w+(self.d*2*self.s))/2:
- x = int((self.w-(self.d*3*self.s))/2)
- y += int(self.d*self.s)
- self.grid[j] = c
- j+=1
-
- def set_orientation(self, neworientation):
- for c in range(9):
- self.card_table[c].set_orientation(neworientation[c],True)
- self.card_table[c].draw_card()
+ self.show_all()
+ self.randomize_orientation()
+ r = int(uniform(0,2))
+ if r == 0:
+ self.set_grid([5,2,0,4,6,3,1,7,8])
+ self.hide_list([0,3,8])
+ else:
+ self.set_grid([7,1,3,2,5,4,8,0,6])
+ self.hide_list([3,4,6])
# swap card a and card b
# swap their entries in the grid and the position of their sprites
@@ -132,12 +146,10 @@ class Grid:
bi = self.grid.index(b)
self.grid[bi] = a
self.grid[ai] = b
- x = self.card_table[a].spr.x
- y = self.card_table[a].spr.y
- self.card_table[a].spr.x = self.card_table[b].spr.x
- self.card_table[a].spr.y = self.card_table[b].spr.y
- self.card_table[b].spr.x = x
- self.card_table[b].spr.y = y
+ ax,ay = self.card_table[a].spr.get_xy()
+ bx,by = self.card_table[b].spr.get_xy()
+ self.card_table[a].spr.move((bx,by))
+ self.card_table[b].spr.move((ax,ay))
# print the grid
def print_grid(self):
diff --git a/sprites.py b/sprites.py
index e1b037e..a361ba0 100644
--- a/sprites.py
+++ b/sprites.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#Copyright (c) 2007-8, Playful Invention Company.
-#Copyright (c) 2008-9, Walter Bender
+#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
@@ -21,141 +21,346 @@
#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
-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
+
+#
+# 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:
- 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
+ self.area = area
+ self.gc = gc
+ self.cm = self.gc.get_colormap()
+ self.list = []
-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:])
+ def get_sprite(self, i):
+ if i < 0 or i > len(self.list)-1:
+ return(None)
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)
+ 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:
- 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)
+ 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(self.images[i], gtk.gdk.Pixbuf):
+ _w = self.images[i].get_width()
+ _h = self.images[i].get_height()
+ else:
+ _w, _h = self.images[i].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)
diff --git a/window.py b/window.py
index e4d4160..bc3082b 100644
--- a/window.py
+++ b/window.py
@@ -31,7 +31,7 @@ except:
from grid import *
from card import *
-
+from sprites import Sprites
from math import sqrt
CARD_DIM = 135
@@ -68,15 +68,12 @@ def new_window(canvas, path, parent=None):
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 = []
+
+ # Initialize the sprite repository
+ tw.sprites = Sprites(tw.canvas)
# Initialize the grid
tw.grid = Grid(tw)
- tw.test = tw.grid.test3x3
# Start solving the puzzle
tw.press = -1
@@ -92,13 +89,13 @@ 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))
+ spr = tw.sprites.find_sprite((x,y))
if spr is None:
tw.press = -1
tw.release = -1
return True
# take note of card under button press
- tw.press = spr.label
+ tw.press = int(spr.labels[0])
return True
#
@@ -107,13 +104,13 @@ def _button_press_cb(win, event, tw):
def _button_release_cb(win, event, tw):
win.grab_focus()
x, y = map(int, event.get_coords())
- spr = findsprite(tw,(x,y))
+ spr = tw.sprites.find_sprite((x,y))
if spr is None:
tw.press = -1
tw.release = -1
return True
# take note of card under button release
- tw.release = spr.label
+ tw.release = int(spr.labels[0])
# if the same card (click) then rotate
if tw.press == tw.release:
# check to see if it was an aborted move
@@ -124,9 +121,6 @@ def _button_release_cb(win, event, tw):
else:
tw.grid.swap(tw.press,tw.release)
# tw.grid.print_grid()
- inval(tw.grid.card_table[tw.press].spr)
- inval(tw.grid.card_table[tw.release].spr)
- redrawsprites(tw)
tw.press = -1
tw.release = -1
if tw.test() == True:
@@ -157,7 +151,7 @@ def distance(start,stop):
# Repaint
#
def _expose_cb(win, event, tw):
- redrawsprites(tw)
+ tw.sprites.redraw_sprites()
return True
#