diff options
Diffstat (limited to 'cardtable.py')
-rw-r--r-- | cardtable.py | 288 |
1 files changed, 288 insertions, 0 deletions
diff --git a/cardtable.py b/cardtable.py new file mode 100644 index 0000000..4eca7eb --- /dev/null +++ b/cardtable.py @@ -0,0 +1,288 @@ +# Copyright (C) 2006, 2007, 2008 One Laptop Per Child +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +# + +import gtk +import pango +import svgcard +import os +import math +import gc +from gobject import SIGNAL_RUN_FIRST, TYPE_PYOBJECT + +import logging +_logger = logging.getLogger('memorize-activity') + +import theme + +class CardTable(gtk.EventBox): + + __gsignals__ = { + 'card-flipped': (SIGNAL_RUN_FIRST, None, [int, TYPE_PYOBJECT]), + 'card-overflipped': (SIGNAL_RUN_FIRST, None, [int]), + 'card-highlighted': (SIGNAL_RUN_FIRST, None, [int, TYPE_PYOBJECT]), + } + + def __init__(self): + gtk.EventBox.__init__(self) + self.data = None + self.cards_data = None + self._workspace_size = 0 + self.lastcard = None + + # set request size to 100x100 to skip first time sizing in _allocate_cb + self.set_size_request(100, 100) + self.connect('size-allocate', self._allocate_cb) + + # Set table settings + self.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('#000000')) + self.table = gtk.Table() + self.table.grab_focus() + self.table.set_flags(gtk.CAN_FOCUS) + self.table.set_flags(gtk.CAN_DEFAULT) + self.table.set_row_spacings(theme.CARD_PAD) + self.table.set_col_spacings(theme.CARD_PAD) + self.table.set_border_width(theme.CARD_PAD) + self.table.set_resize_mode(gtk.RESIZE_IMMEDIATE) + self.set_property('child', self.table) + self.load_message = gtk.Label('Loading Game') + self.load_message.modify_fg(gtk.STATE_NORMAL, + gtk.gdk.color_parse('#ffffff')) + self.load_message.modify_font(pango.FontDescription("10")) + self.load_message.show() + self.first_load = True + self.load_mode = False + self.dict = None + self.show_all() + + def _allocate_cb(self, widget, allocation): + size = allocation.height + + if size == 100: + # skip first time sizing + return + + # do it once + if self._workspace_size: + return + + _logger.debug('Use %s allocation' % str(self.allocation)) + + self.set_size_request(size, size) + self._workspace_size = size + if self.data: + self.load_game(None, self.data, self.cards_data) + + def load_game(self, widget, data, grid): + self.data = data + self.cards_data = grid + + if self._workspace_size == 0: + # widow is not allocated, thus postpone loading + return + + self.size = int(math.ceil(math.sqrt(len(grid)))) + if self.size < 4: + self.size = 4 + self.table.resize(self.size, self.size) + self.card_size = self.get_card_size(self.size) + self.cards = {} + self.cd2id = {} + self.id2cd = {} + self.dict = {} + self.selected_card = [0, 0] + self.flipped_card = -1 + self.table_positions = {} + + # Build the table + if data['divided'] == '1': + text1 = str(self.data.get('face1', '')) + text2 = str(self.data.get('face2', '')) + else: + text1 = str(self.data.get('face', '')) + text2 = str(self.data.get('face', '')) + + x = 0 + y = 0 + identifier = 0 + + for card in self.cards_data: + if card.get('img', None): + jpg = os.path.join(self.data['pathimg'], card['img']) + else: + jpg = None + props = {} + props['front_text'] = {'card_text':card.get('char', ''), + 'speak': card.get('speak')} + + if card['ab'] == 'a': + props['back_text'] = {'card_text':text1} + elif card['ab'] == 'b': + props['back_text'] = {'card_text':text2} + + align = self.data.get('align', '1') + try: + sensor = card.get('sensor') + except: + sensor = None + card = svgcard.SvgCard(identifier, props, jpg, + self.card_size, align, sensor) + card.connect('enter-notify-event', self.mouse_event, [x, y]) + card.connect("button-press-event", self.flip_card_mouse, identifier) + self.table_positions[(x, y)] = 1 + self.cd2id[card] = identifier + self.id2cd[identifier] = card + self.cards[(x, y)] = card + self.dict[identifier] = (x, y) + self.table.attach(card, x, x+1, y, y+1, gtk.SHRINK, gtk.SHRINK) + + x += 1 + if x == self.size: + x = 0 + y += 1 + identifier += 1 + self.first_load = False + if self.load_mode: + self._set_load_mode(False) + self.show_all() + #gc.collect() + + def change_game(self, widget, data, grid): + if not self.first_load: + for card in self.cards.values(): + self.table.remove(card) + del card + #gc.collect() + self.load_game(None, data, grid) + + def get_card_size(self, size_table): + x = (self._workspace_size + theme.CARD_PAD * (size_table-1)) / \ + size_table - theme.CARD_PAD * 2 + return x + + def mouse_event(self, widget, event, coord): + #self.table.grab_focus() + card = self.cards[coord[0], coord[1]] + identifier = self.cd2id.get(card) + self.emit('card-highlighted', identifier, True) + self.selected_card = (coord[0], coord[1]) + + def key_press_event(self, widget, event): + #self.table.grab_focus() + x = self.selected_card[0] + y = self.selected_card[1] + + if event.keyval in (gtk.keysyms.Left, gtk.keysyms.KP_Left): + if self.table_positions.has_key((x-1, y)): + card = self.cards[x-1, y] + identifier = self.cd2id.get(card) + self.emit('card-highlighted', identifier, False) + + elif event.keyval in (gtk.keysyms.Right, gtk.keysyms.KP_Right): + if self.table_positions.has_key((x+1, y)): + card = self.cards[x+1, y] + identifier = self.cd2id.get(card) + self.emit('card-highlighted', identifier, False) + + elif event.keyval in (gtk.keysyms.Up, gtk.keysyms.KP_Up): + if self.table_positions.has_key((x, y-1)): + card = self.cards[x, y-1] + identifier = self.cd2id.get(card) + self.emit('card-highlighted', identifier, False) + + elif event.keyval in (gtk.keysyms.Down, gtk.keysyms.KP_Down): + if self.table_positions.has_key((x, y+1)): + card = self.cards[x, y+1] + identifier = self.cd2id.get(card) + self.emit('card-highlighted', identifier, False) + + elif event.keyval in (gtk.keysyms.space, gtk.keysyms.KP_Page_Down): + card = self.cards[x, y] + self.card_flipped(card) + + def flip_card_mouse(self, widget, event, identifier): + position = self.dict[identifier] + card = self.cards[position] + self.card_flipped(card) + + def trysensor(self, avg): + for card in self.cards.values(): + #card = self.cards[xy[0],xy[1]] + #if(card.get_sensor() is not None): + cardcode = card.get_text() + if((cardcode.find('s~')!=-1) and (not card.flipped)): + if (abs(int(cardcode[cardcode.find('s~')+2:len(cardcode)]) - avg)<2000): + if(self.lastcard == card): + #self.lastcard = self.cd2id[card] + #card.flip(True) + #card.flip(False) + self.card_flipped(card) + card.flip(True) + #card.animate(True) + #self.card_flipped(card) + #card.flip(True) + #card.flip(True) + #card.flip(False) + #card.flip(False) + break + else: + self.lastcard = card + + def card_flipped(self, card): + identifer = self.cd2id[card] + if card.is_flipped(): + self.emit('card-overflipped', identifer) + else: + self.emit('card-flipped', identifer, False) + + def set_border(self, widget, identifer, stroke_color, fill_color): + self.id2cd[identifer].set_border(stroke_color, fill_color) + + def flop_card(self, widget, identifer): + self.id2cd.get(identifer).flop() + + def flip_card(self, widget, identifer, full_animation): + self.id2cd.get(identifer).flip(full_animation) + + def cement_card(self, widget, identifer): + self.id2cd.get(identifer).cement() + + def highlight_card(self, widget, identifer, status): + if self.dict != None: + self.selected_card = self.dict.get(identifer) + self.id2cd.get(identifer).set_highlight(status) + + def reset(self, widget): + for identifer in self.id2cd.keys(): + self.id2cd[identifer].reset() + + def _set_load_mode(self, mode): + if mode: + self.remove(self.table) + self.set_property('child', self.load_message) + else: + self.remove(self.load_message) + self.set_property('child', self.table) + self.load_mode = mode + self.queue_draw() + while gtk.events_pending(): + gtk.main_iteration() + + def load_msg(self, widget, msg): + if not self.load_mode: + self._set_load_mode(True) + self.load_message.set_text(msg) + self.queue_draw() |