diff options
author | Walter 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) |
commit | d0f2e2eb2995c01789f8604f80b7e4d202388192 (patch) | |
tree | bebc2551c8b6df9f7af1c3e29c165e5961be2fc1 | |
parent | bba203b7b8333dca6e27ff7f365f2eaa620efd2f (diff) |
majore refactoring
-rw-r--r-- | CardSortActivity.py | 11 | ||||
-rw-r--r-- | NEWS | 8 | ||||
-rw-r--r-- | activity/activity.info | 2 | ||||
-rw-r--r-- | card.py | 31 | ||||
-rwxr-xr-x | cardsort.py | 63 | ||||
-rw-r--r-- | grid.py | 172 | ||||
-rw-r--r-- | sprites.py | 463 | ||||
-rw-r--r-- | window.py | 24 |
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) @@ -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 @@ -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 @@ -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): @@ -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) @@ -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 # |