From: <umg...@us...> - 2006-10-06 16:26:04
|
Revision: 346 http://svn.sourceforge.net/pybridge/?rev=346&view=rev Author: umgangee Date: 2006-10-06 09:25:53 -0700 (Fri, 06 Oct 2006) Log Message: ----------- xy positioning of items in cardarea now uses (0..1, 0..1) values scaled by cardarea's width/height; replaces lambda positioning. Addition of set_player_name(). Modified Paths: -------------- trunk/pybridge/pybridge/ui/canvas.py trunk/pybridge/pybridge/ui/cardarea.py trunk/pybridge/pybridge/ui/window_bridgetable.py Modified: trunk/pybridge/pybridge/ui/canvas.py =================================================================== --- trunk/pybridge/pybridge/ui/canvas.py 2006-09-20 15:59:34 UTC (rev 345) +++ trunk/pybridge/pybridge/ui/canvas.py 2006-10-06 16:25:53 UTC (rev 346) @@ -54,7 +54,8 @@ context.rectangle(0, 0, width, height) context.set_source(self.pattern) context.paint() - self.window.invalidate_rect((0, 0, width, height), False) # Expose. + # Trigger a call to self.expose(). + self.window.invalidate_rect((0, 0, width, height), False) def add_item(self, id, source, xy, z_index): @@ -62,13 +63,13 @@ @param id: unique identifier for source. @param source: ImageSurface. - @param xy: function providing (x, y) coords for source in backing. + @param xy: tuple providing (x, y) coords for source in backing. @param z_index: integer. """ - pos_x, pos_y = xy(*self.window.get_size()) - area = (pos_x, pos_y, source.get_width(), source.get_height()) - self.items[id] = {'source': source, 'area': area, - 'xy' : xy, 'z-index': z_index, } + # Calculate and cache the on-screen area of the item. + area = self.get_area(source, xy) + self.items[id] = {'source': source, 'area': area, 'xy': xy, + 'z-index': z_index, } self.redraw(*area) @@ -87,29 +88,35 @@ """ """ - # If optional parameters are not specified, use previous values. - source = source or self.items[id]['source'] - xy = xy or self.items[id]['xy'] + # If optional parameters are not specified, use stored values. z_index = z_index or self.items[id]['z-index'] + if source or xy: + # If source or xy coords changed, recalculate on-screen area. + source = source or self.items[id]['source'] + xy = xy or self.items[id]['xy'] + area = self.get_area(source, xy) + # If area of item has changed, clear item from previous area. + oldarea = self.items[id]['area'] + if area != oldarea: + del self.items[id] + self.redraw(*oldarea) + else: + source = self.items[id]['source'] + xy = self.items[id]['xy'] + area = self.items[id]['area'] - oldarea = self.items[id]['area'] # Current position of item. - pos_x, pos_y = xy(*self.window.get_size()) - area = (pos_x, pos_y, source.get_width(), source.get_height()) - if area != oldarea: # If position has changed, clear previous area. - del self.items[id] - self.redraw(*oldarea) - self.items[id] = {'source': source, 'area': area, - 'xy' : xy, 'z-index': z_index, } + self.items[id] = {'source': source, 'area': area, 'xy' : xy, + 'z-index': z_index, } self.redraw(*area) def redraw(self, x, y, width, height): """Redraws sources in area (x, y, width, height) to backing canvas. - @param x: - @param y: - @param width: - @param height: + @param x: start x-coordinate of area to be redrawn. + @param y: start y-coordinate of area to be redrawn. + @param width: the width of area to be redrawn. + @param height: the height of area to be redrawn. """ context = cairo.Context(self.backing) context.rectangle(x, y, width, height) @@ -134,16 +141,55 @@ self.window.invalidate_rect((x, y, width, height), False) # Expose. + def get_area(self, source, xy): + """Calculates the on-screen area of the specified source centred at xy. + + @param source: + @param xy: + @return: a tuple (x, y, width, height) + """ + win_w, win_h = self.window.get_size() # Window width and height. + width, height = source.get_width(), source.get_height() + x = int((xy[0] * win_w) - width/2) # Round to integer. + y = int((xy[1] * win_h) - height/2) + # Ensure that source coordinates fit inside dimensions of backing. + if x < self.border_x: + x = self.border_x + elif x + width > win_w - self.border_x: + x = win_w - self.border_x - width + if y < self.border_y: + y = self.border_y + elif y + height > win_h - self.border_y: + y = win_h - self.border_y - height + return x, y, width, height + + def new_surface(self, width, height): + """Creates a new ImageSurface of dimensions (width, height) + and ensures that the ImageSurface is cleared. + + @param width: the expected width of the ImageSurface. + @param height: the expected height of the ImageSurface. + @return: tuple (surface, context) + """ + # Create new ImageSurface for hand. + surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) + context = cairo.Context(surface) + # Clear ImageSurface - in Cairo 1.2+, this is done automatically. + if cairo.version_info < (1, 2): + context.set_operator(cairo.OPERATOR_CLEAR) + context.paint() + context.set_operator(cairo.OPERATOR_OVER) # Restore. + return surface, context + + def configure(self, widget, event): width, height = self.window.get_size() self.backing = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) # Recalculate position of all items. - for id, item in self.items.items(): - pos_x, pos_y = item['xy'](width, height) - area = (pos_x, pos_y, item['area'][2], item['area'][3]) - self.items[id]['area'] = area + for id, item in self.items.iteritems(): + self.items[id]['area'] = self.get_area(item['source'], item['xy']) self.redraw(0, 0, width, height) # Full redraw required. return True # Expected to return True. Modified: trunk/pybridge/pybridge/ui/cardarea.py =================================================================== --- trunk/pybridge/pybridge/ui/cardarea.py 2006-09-20 15:59:34 UTC (rev 345) +++ trunk/pybridge/pybridge/ui/cardarea.py 2006-10-06 16:25:53 UTC (rev 346) @@ -18,6 +18,8 @@ import gtk import cairo +import pango +import pangocairo from pybridge.environment import environment from canvas import CairoCanvas @@ -45,6 +47,8 @@ card_mask_path = environment.find_pixmap('bonded.png') card_mask = cairo.ImageSurface.create_from_png(card_mask_path) + font_description = pango.FontDescription('Sans Bold 10') + border_x = border_y = 10 card_width = card_mask.get_width() / 13 card_height = card_mask.get_height() / 5 @@ -110,10 +114,10 @@ pos_x = index * self.spacing_x coords.append((card, pos_x, pos_y)) else: # Insert a space between each suit. - spaces = sum([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 + spaces = len([1 for suitcards in suits.values() if len(suitcards) > 0]) - 1 for index, card in enumerate(hand): # Insert a space for each suit in hand which appears before this card's suit. - insert = sum([1 for suit, suitcards in suits.items() if len(suitcards) > 0 + insert = len([1 for suit, suitcards in suits.items() if len(suitcards) > 0 and RED_BLACK.index(card.suit) > RED_BLACK.index(suit)]) pos_x = (index + insert) * self.spacing_x coords.append((card, pos_x, pos_y)) @@ -156,14 +160,7 @@ # Determine dimensions of hand. width = max([x for card, x, y in coords]) + self.card_width height = max([y for card, x, y in coords]) + self.card_height - # Create new ImageSurface for hand. - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - # Clear ImageSurface - in Cairo 1.2+, this is done automatically. - if cairo.version_info < (1, 2): - context.set_operator(cairo.OPERATOR_CLEAR) - context.paint() - context.set_operator(cairo.OPERATOR_OVER) # Restore. + surface, context = self.new_surface(width, height) # Draw cards to surface. visible = [(i, card) for i, card in enumerate(hand) if card not in omit] @@ -175,23 +172,53 @@ self.hands[seat] = {'hand' : hand, 'visible' : visible, 'surface' : surface, 'coords' : coords, } - # - if seat is self.TOP: - xy = lambda w, h: ((w - width)/2, self.border_y) - elif seat is self.RIGHT: - xy = lambda w, h: ((w - width - self.border_x), (h - height)/2) - elif seat is self.BOTTOM: - xy = lambda w, h: ((w - width)/2, (h - height - self.border_y)) - elif seat is self.LEFT: - xy = lambda w, h: (self.border_x, (h - height)/2) - id = 'hand-%s' % seat # Identifier for this item. if id in self.items: - self.update_item(id, source=surface, xy=xy) - else: - self.add_item(id, surface, xy, 0) + self.update_item(id, source=surface) + else: + xy = {self.TOP : (0.5, 0.15), self.BOTTOM : (0.5, 0.85), + self.LEFT : (0.15, 0.5), self.RIGHT : (0.85, 0.5), } + self.add_item(id, surface, xy[seat], 0) + def set_player_name(self, seat, name=None): + """ + + @param name: the name of the player, or None. + """ + id = 'player-%s' % seat + if name is None or id in self.items: + self.remove_item(id) + return + + layout = pango.Layout(self.create_pango_context()) + layout.set_font_description(self.font_description) + layout.set_text(name) + # Create an ImageSurface respective to dimensions of text. + width, height = layout.get_pixel_size() + surface, context = self.new_surface(width, height) + context = pangocairo.CairoContext(context) + +# context.set_line_width(4) +# context.rectangle(0, 0, width, height) +# context.set_source_rgb(0, 0.5, 0) +# context.fill_preserve() +# context.set_source_rgb(0, 0.25, 0) +# context.stroke() +# context.move_to(4, 2) + context.set_source_rgb(1, 1, 1) + context.show_layout(layout) + + if id in self.items: + self.update_item(id, source=surface) + else: + xy = {self.TOP : (0.5, 0.05), self.BOTTOM : (0.5, 0.95), + self.LEFT : (0.15, 0.7), self.RIGHT : (0.85, 0.7), } +# xy = {self.TOP : (0.5, 0.3), self.BOTTOM : (0.5, 0.7), +# self.LEFT : (0.15, 0.7), self.RIGHT : (0.85, 0.7), } + self.add_item(id, surface, xy[seat], 2) + + def set_seat_mapping(self, focus=Seat.South): """Sets the mapping between seats at table and positions of hands. @@ -223,14 +250,7 @@ Seat.South : ((width - self.card_width)/2, (height - self.card_height) ), Seat.West : (0, (height - self.card_height)/2 ), } - # Create new ImageSurface for trick. - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) - # Clear ImageSurface - in Cairo 1.2+, this is done automatically. - if cairo.version_info < (1, 2): - context.set_operator(cairo.OPERATOR_CLEAR) - context.paint() - context.set_operator(cairo.OPERATOR_OVER) # Restore. + surface, context = self.new_surface(width, height) if trick: leader, cards_played = trick @@ -244,11 +264,10 @@ if id in self.items: self.update_item(id, source=surface) else: - xy = lambda w, h: ((w - width)/2, (h - height)/2) + xy = (0.5, 0.5) self.add_item(id, surface, xy, 0) - def set_turn(self, turn): """Sets the turn indicator. @@ -262,19 +281,16 @@ self.remove_item(id) return - def xy(w, h): - x, y = self.items['hand-%s' % turn]['xy'](w, h) - return x-10, y-10 - # TODO: select colours that don't clash with the background. - # TODO: one colour if user can click card, another if not. + # TODO: one colour if user can play card from hand, another if not. width = self.hands[turn]['surface'].get_width() + 20 height = self.hands[turn]['surface'].get_height() + 20 - surface = cairo.ImageSurface(cairo.FORMAT_ARGB32, width, height) - context = cairo.Context(surface) + surface, context = self.new_surface(width, height) context.set_source_rgb(0.3, 0.6, 0) # Green. context.paint_with_alpha(0.5) + xy = self.items['hand-%s' % turn]['xy'] # Use same xy as hand. + if id in self.items: self.update_item(id, source=surface, xy=xy) else: Modified: trunk/pybridge/pybridge/ui/window_bridgetable.py =================================================================== --- trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-09-20 15:59:34 UTC (rev 345) +++ trunk/pybridge/pybridge/ui/window_bridgetable.py 2006-10-06 16:25:53 UTC (rev 346) @@ -353,6 +353,7 @@ def event_playerAdded(self, table, player, position): if table == self.table: + self.cardarea.set_player_name(position, player) # Disable menu item corresponding to position. widget = self.takeseat_items[position] widget.set_property('sensitive', False) @@ -367,6 +368,7 @@ def event_playerRemoved(self, table, player, position): if table == self.table: + self.cardarea.set_player_name(position, None) # Enable menu item corresponding to position. widget = self.takeseat_items[position] widget.set_property('sensitive', True) @@ -384,13 +386,14 @@ self.children.close('dialog_gameresult') self.resetGame() + self.redrawTrick() # Clear trick. + for position in table.game.deal: + self.redrawHand(position) + self.setTurnIndicator() self.setDealer(table.dealer) self.setVuln(table.game.vulnNS, table.game.vulnEW) - self.redrawTrick() # Clear trick. - for position in table.game.deal: - self.redrawHand(position) if table.seated: self.children.open('window_bidbox', parent=self) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |