diff options
author | Walter Bender <walter@walter-laptop.(none)> | 2009-10-03 00:24:36 (GMT) |
---|---|---|
committer | Walter Bender <walter@walter-laptop.(none)> | 2009-10-03 00:24:36 (GMT) |
commit | b0e22b3b1ab7a16471f6ddd1e91e1f0c6a8b529d (patch) | |
tree | 7b6b9076bc91feb36468e74f1df6465f071e4741 /CardSortActivity.py |
new project
Diffstat (limited to 'CardSortActivity.py')
-rw-r--r-- | CardSortActivity.py | 318 |
1 files changed, 318 insertions, 0 deletions
diff --git a/CardSortActivity.py b/CardSortActivity.py new file mode 100644 index 0000000..0522e82 --- /dev/null +++ b/CardSortActivity.py @@ -0,0 +1,318 @@ +#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 +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 +from sugar.graphics.toolbutton import ToolButton +from sugar.graphics.menuitem import MenuItem +from sugar.graphics.icon import Icon +from sugar.graphics import style +from sugar.datastore import datastore + +from sugar import profile +from gettext import gettext as _ +import locale +import os.path +from sprites import * +from math import sqrt + +class taWindow: pass + +SERVICE = 'org.sugarlabs.CardSortActivity' +IFACE = SERVICE +PATH = '/org/augarlabs/CardSortActivity' + +CARD_DIM = 135 +CARD_DEFS = ((1,3,-2,-3),(2,3,-3,-2),(2,3,-4,-4),\ + (2,1,-1,-4),(3,4,-4,-3),(4,2,-1,-2),\ + (1,1,-2,-4),(4,2,-3,-4),(1,3,-1,-2)) + + +# +# class for defining 3x3 matrix of cards +# +class Grid: + # 123 + # 456 + # 789 + def __init__(self,tw): + self.grid = [1,2,3,4,5,6,7,8,9] + self.card_table = {} + # Initialize the cards + i = 0 + x = (tw.width-(CARD_DIM*3))/2 + y = (tw.height-(CARD_DIM*3))/2 + for c in CARD_DEFS: + self.card_table[i] = Card(tw,c,i,x,y) + self.card_table[i].draw_card() + x += CARD_DIM + if x > (tw.width+(CARD_DIM*2))/2: + x = (tw.width-(CARD_DIM*3))/2 + y += CARD_DIM + i += 1 + + def swap(self,a,b): + # swap grid elements and x,y positions of sprites + print "swapping cards " + str(a) + " and " + str(b) + tmp = self.grid[a] + x = self.card_table[a].spr.x + y = self.card_table[a].spr.y + self.grid[a] = self.grid[b] + 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.grid[b] = tmp + self.card_table[b].spr.x = x + self.card_table[b].spr.y = y + + def print_grid(self): + print self.grid + return + + def test(self): + for i in (0,1,3,4,6,7): + if self.card_table[self.grid[i]].east + \ + self.card_table[self.grid[i+1]].west != 0: + return False + for i in (0,1,2,3,4,5): + if self.card_table[self.grid[i]].south + \ + self.card_table[self.grid[i+3]].north != 0: + return False + return True + + +# +# class for defining individual cards +# +class Card: + # Spade = 1,-1 + # Heart = 2,-2 + # Club = 3,-3 + # Diamond = 4,-4 + def __init__(self,tw,c,i,x,y): + self.north = c[0] + self.east = c[1] + self.south = c[2] + self.west = c[3] + self.rotate = 0 + # create sprite from svg file + self.spr = sprNew(tw,x,y,self.load_image(tw.path,i)) + self.spr.label = i + + def draw_card(self): + setlayer(self.spr,2000) + draw(self.spr) + + def load_image(self, file, i): + print "loading " + os.path.join(file + str(i) + '.svg') + return gtk.gdk.pixbuf_new_from_file(os.path.join(file + \ + str(i) + "x" + \ + '.svg')) + + def rotate_ccw(self): + # print "rotating card " + str(self.spr.label) + tmp = self.north + self.north = self.east + self.east = self.south + self.south = self.west + self.west = tmp + self.rotate += 90 + if self.rotate > 359: + self.rotate -= 360 + tmp = self.spr.image.rotate_simple(90) + self.spr.image = tmp + + def print_card(self): + print "(" + str(self.north) + "," + str(self.east) + \ + "," + str(self.south) + "," + str(self.west) + \ + ") " + str(self.rotate) + "ccw" + \ + " x:" + str(self.spr.x) + " y:" + str(self.spr.y) + +# +# Sugar activity +# +class CardSortActivity(activity.Activity): + + def __init__(self, handle): + super(CardSortActivity,self).__init__(handle) + + # 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() + + # Solver button + self.solve_puzzle = ToolButton( "solve-off" ) + self.solve_puzzle.set_tooltip(_('Solve it')) + self.solve_puzzle.props.sensitive = True + self.solve_puzzle.connect('clicked', self._solver_cb) + toolbar_box.toolbar.insert(self.solve_puzzle, -1) + self.solve_puzzle.show() + + separator = gtk.SeparatorToolItem() + separator.show() + toolbar_box.toolbar.insert(separator, -1) + + # Label for showing status + self.results_label = gtk.Label(_("click to rotate; drag to swap")) + 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() + + # Create a canvas + canvas = gtk.DrawingArea() + canvas.set_size_request(gtk.gdk.screen_width(), \ + gtk.gdk.screen_height()) + self.set_canvas(canvas) + self.show_all() + + # Initialize the canvas + self.tw = taWindow() + self.tw.window = canvas + canvas.set_flags(gtk.CAN_FOCUS) + canvas.add_events(gtk.gdk.BUTTON_PRESS_MASK) + canvas.add_events(gtk.gdk.BUTTON_RELEASE_MASK) + canvas.connect("expose-event", self._expose_cb, self.tw) + canvas.connect("button-press-event", self._button_press_cb, self.tw) + canvas.connect("button-release-event", self._button_release_cb, self.tw) + self.tw.width = gtk.gdk.screen_width() + self.tw.height = gtk.gdk.screen_height()-style.GRID_CELL_SIZE + self.tw.area = canvas.window + self.tw.gc = self.tw.area.new_gc() + self.tw.scale = 3 + self.tw.cm = self.tw.gc.get_colormap() + self.tw.msgcolor = self.tw.cm.alloc_color('black') + self.tw.sprites = [] + + # Initialize the grid + self.tw.path = os.path.join(activity.get_bundle_path(),'images/card') + self.tw.grid = Grid(self.tw) + + # Start solving the puzzle + self.tw.press = -1 + self.tw.release = -1 + self.tw.start_drag = [0,0] + + # + # Solver + # + def _solver_cb(self, button): + self.solve_puzzle.set_icon("solve-on") + """ + We need to write this code + """ + self.results_label.set_text(_("I don't know how to solve it.")) + self.results_label.show() + self.solve_puzzle.set_icon("solve-off") + return True + + + # + # Repaint + # + def _expose_cb(self, win, event, tw): + redrawsprites(tw) + return True + + # + # Button press + # + def _button_press_cb(self, 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 = -1 + tw.release = -1 + return True + # take note of card under button press + tw.press = spr.label + return True + + # + # Button release + # + def _button_release_cb(self, win, event, tw): + win.grab_focus() + x, y = map(int, event.get_coords()) + spr = findsprite(tw,(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 + # if the same card (click) then rotate + if tw.press == tw.release: + # check to see if it was an aborted move + if self.distance(tw.start_drag,[x,y]) < 20: + tw.grid.card_table[tw.press].rotate_ccw() + # tw.grid.card_table[tw.press].print_card() + # if different card (drag) then swap + 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.grid.test() == True: + self.results_label.set_text(_("You solved the puzzle.")) + self.results_label.show() + else: + self.results_label.set_text(_("Keep trying.")) + self.results_label.show() + + return True + + def distance(self,start,stop): + dx = start[0]-stop[0] + dy = start[1]-stop[1] + return sqrt(dx*dx+dy*dy) |