changeset 38:7bea2ae0c4fb

Tarot game: center_panel layout + chien can now be showed + fixed click event inheritance + card selection first draft
author Goffi <goffi@goffi.org>
date Thu, 19 May 2011 02:00:59 +0200
parents b306aa090438
children 305e81c7a32c
files browser_side/card_game.py browser_side/panels.py libervia.py libervia.tac
diffstat 4 files changed, 120 insertions(+), 20 deletions(-) [+]
line wrap: on
line diff
--- a/browser_side/card_game.py	Wed May 18 01:45:28 2011 +0200
+++ b/browser_side/card_game.py	Thu May 19 02:00:59 2011 +0200
@@ -24,12 +24,17 @@
 from pyjamas.ui.VerticalPanel import VerticalPanel
 from pyjamas.ui.HorizontalPanel import HorizontalPanel
 from pyjamas.ui.DockPanel import DockPanel
+from pyjamas.ui.SimplePanel import SimplePanel
 from pyjamas.ui.DialogBox import DialogBox
 from pyjamas.ui.ListBox import ListBox
 from pyjamas.ui.Image import Image
 from pyjamas.ui.Label import Label
 from pyjamas.ui.Button import Button
+from pyjamas.ui.ClickListener import ClickHandler
+from pyjamas.ui.MouseListener import MouseHandler
 from pyjamas.ui import HasAlignment
+from pyjamas import Window
+from pyjamas import DOM
 
 from pyjamas.dnd import makeDraggable
 from pyjamas.ui.DragWidget import DragWidget, DragContainer
@@ -43,6 +48,7 @@
 
 CARD_WIDTH = 74
 CARD_HEIGHT = 136
+CARD_DELTA_Y = 10
 MIN_WIDTH = 950 #Minimum size of the panel
 MIN_HEIGHT = 500
 
@@ -76,28 +82,31 @@
         self.hide()
         self._parent.contratSelected(self.contrats_list.getSelectedItemText()[0])
 
-class CardWidget(TarotCard, Image):
+class CardWidget(TarotCard, Image, MouseHandler):
     """This class is used to represent a card, graphically and logically"""
 
-    def __init__(self, file):
+    def __init__(self, parent, file):
         """@param file: path of the PNG file"""
+        self._parent = parent
         Image.__init__(self,file)
         root_name = file[file.rfind("/")+1:-4]
         suit,value = root_name.split('_')
         TarotCard.__init__(self, (suit, value))
-        print "Carte:",suit, value #, self.bout
+        MouseHandler.__init__(self)
+        self.addMouseListener(self)
 
-    def draw(self, dc, x, y):
-        """Draw the card on the device context
-        @param dc: device context
-        @param x: abscissa 
-        @param y: ordinate"""
-        pass
-        #dc.DrawBitmap(self.bitmap, x, y, True)
+    def onMouseEnter(self, sender):
+        if self._parent.state == "ecart":
+            DOM.setStyleAttribute(self.getElement(), "top", "0px")
 
-class CardPanel(DockPanel):
+    def onMouseLeave(self, sender):
+        DOM.setStyleAttribute(self.getElement(), "top", "%dpx" % CARD_DELTA_Y)
+
+class CardPanel(DockPanel, ClickHandler):
 
     def __init__(self, parent, referee, players, player_nick):
+        DockPanel.__init__(self)
+        ClickHandler.__init__(self)
         self._parent = parent
         self._autoplay = None #XXX: use 0 to activate fake play, None else
         self.referee = referee
@@ -120,16 +129,17 @@
         self.hand = []
         self.to_show = []
         self.state = None
-        DockPanel.__init__(self)
-        self.setSize("%spx" % MIN_WIDTH, "%spx" % MIN_HEIGHT)
+        self.setSize("%dpx" % MIN_WIDTH, "%dpx" % MIN_HEIGHT)
         self.setStyleName("cardPanel")
         
+        # Now we set up the layout
         _label = Label(self.top_nick)
         _label.setStyleName('cardGamePlayerNick')
         self.add(_label, DockPanel.NORTH)
         self.setCellWidth(_label, '100%')
         self.setCellHorizontalAlignment(_label, HasAlignment.ALIGN_CENTER) 
         
+        
         self.hand_panel = AbsolutePanel()
         self.add(self.hand_panel, DockPanel.SOUTH)
         self.setCellWidth(self.hand_panel, '100%')
@@ -142,6 +152,7 @@
         self.setCellHeight(_label, '100%')
         self.setCellVerticalAlignment(_label, HasAlignment.ALIGN_MIDDLE) 
 
+
         _label = Label(self.right_nick)
         _label.setStyleName('cardGamePlayerNick')
         self.add(_label, DockPanel.EAST)
@@ -149,9 +160,41 @@
         self.setCellHorizontalAlignment(_label, HasAlignment.ALIGN_RIGHT) 
         self.setCellVerticalAlignment(_label, HasAlignment.ALIGN_MIDDLE) 
         
+
         self.center_panel = DockPanel()
+        self.inner_left = SimplePanel()
+        self.center_panel.add(self.inner_left, DockPanel.WEST)
+        self.center_panel.setCellHeight(self.inner_left, '100%')
+        self.center_panel.setCellHorizontalAlignment(self.inner_left, HasAlignment.ALIGN_RIGHT)
+        self.center_panel.setCellVerticalAlignment(self.inner_left, HasAlignment.ALIGN_MIDDLE)
+
+        self.inner_right = SimplePanel()
+        self.center_panel.add(self.inner_right, DockPanel.EAST)
+        self.center_panel.setCellHeight(self.inner_right, '100%')
+        self.center_panel.setCellVerticalAlignment(self.inner_right, HasAlignment.ALIGN_MIDDLE)
+        
+        self.inner_top = SimplePanel()
+        self.center_panel.add(self.inner_top, DockPanel.NORTH)
+        self.center_panel.setCellWidth(self.inner_top, '100%')
+        self.center_panel.setCellHorizontalAlignment(self.inner_top, HasAlignment.ALIGN_CENTER)
+        self.center_panel.setCellVerticalAlignment(self.inner_top, HasAlignment.ALIGN_BOTTOM)
+        
+        self.inner_bottom = SimplePanel()
+        self.center_panel.add(self.inner_bottom, DockPanel.SOUTH)
+        self.center_panel.setCellWidth(self.inner_bottom, '100%')
+        self.center_panel.setCellHorizontalAlignment(self.inner_bottom, HasAlignment.ALIGN_CENTER)
+        self.center_panel.setCellVerticalAlignment(self.inner_bottom, HasAlignment.ALIGN_TOP)
+        
+        self.inner_center = SimplePanel()
+        self.center_panel.add(self.inner_center, DockPanel.CENTER)
+        self.center_panel.setCellHorizontalAlignment(self.inner_center, HasAlignment.ALIGN_CENTER)
+        self.center_panel.setCellVerticalAlignment(self.inner_center, HasAlignment.ALIGN_MIDDLE)
+
         self.add(self.center_panel, DockPanel.CENTER)
         self.setCellWidth(self.center_panel, '100%')
+        self.setCellHeight(self.center_panel, '100%')
+        self.setCellVerticalAlignment(self.center_panel, HasAlignment.ALIGN_MIDDLE)
+        self.setCellHorizontalAlignment(self.center_panel, HasAlignment.ALIGN_CENTER)
 
 
         """for side in zip(['left', 'top', 'right'],
@@ -163,6 +206,7 @@
         self.loadCards()
         self.mouse_over_card = None #contain the card to highlight
         self.visible_size = CARD_WIDTH/2 #number of pixels visible for cards
+        self.addClickListener(self)
 
 
     def loadCards(self, dir):
@@ -170,7 +214,7 @@
         @param dir: directory where the PNG files are"""
         def _getTarotCardsPathsCb(paths):
             for file in paths:
-                card = CardWidget(file)
+                card = CardWidget(self, file)
                 self.cards[(card.suit, card.value)]=card
                 self.deck.append(card)
             self._parent.host.bridge.call('tarotGameReady', None, self.player_nick, self.referee)
@@ -183,6 +227,19 @@
         self.cards["trefle"]={} #club
         self._parent.host.bridge.call('getTarotCardsPaths', _getTarotCardsPathsCb)
 
+    def onClick(self, sender):
+        if self.state == "chien":
+            self.to_show = []
+            self.state = "wait"
+            self.updateToShow()
+        elif self.state == "wait_for_ecart":
+            self.state = "ecart"
+            self.hand.extend(self.to_show)
+            self.hand.sort()
+            self.to_show = []
+            self.updateToShow()
+            self.updateHand()
+
     def tarotGameNew(self, hand):
         """Start a new game, with given hand"""
         for suit, value in hand:
@@ -194,13 +251,30 @@
     def updateHand(self):
         """Show the cards in the hand in the hand_panel (SOUTH panel)"""
         self.hand_panel.clear()
-        self.hand_panel.setSize("%spx" % (self.visible_size * (len(self.hand)+1)), "%spx" % (CARD_HEIGHT + 10))
+        self.hand_panel.setSize("%dpx" % (self.visible_size * (len(self.hand)+1)), "%dpx" % (CARD_HEIGHT + CARD_DELTA_Y + 10))
         x_pos = 0
-        y_pos = 0
+        y_pos = CARD_DELTA_Y
         for card in self.hand:
             self.hand_panel.add(card, x_pos, y_pos)
             x_pos+=self.visible_size
-    
+   
+    def updateToShow(self):
+        """Show cards in the center panel"""
+        if not self.to_show:
+            _widget = self.inner_center.getWidget()
+            if _widget: 
+                self.inner_center.remove(_widget)
+            return
+        panel = AbsolutePanel()
+        panel.setSize("%dpx" % ((CARD_WIDTH + 5) * len(self.to_show) - 5), "%dpx" % (CARD_HEIGHT))
+        x_pos = 0
+        y_pos = 0
+        for card in self.to_show:
+            panel.add(card, x_pos, y_pos)
+            x_pos+=CARD_WIDTH + 5
+        self.inner_center.setWidget(panel)
+
+
     def tarotGameChooseContrat(self, xml_data):
         """Called when the player as to select his contrat
         @param xml_data: SàT xml representation of the form"""
@@ -213,5 +287,18 @@
         """Must be called when the contrat is selected
         @param contrat: one of the valid contrat value"""
         print "Contrat choosed:", contrat
-        self._parent.host.bridge.call('tarotGameContratChoosed', None, self.player_nick, self.referee, contrat or 'Passe') #FIXME: must use roomID ! cf quick_card_game for same issue
+        self._parent.host.bridge.call('tarotGameContratChoosed', None, self.player_nick, self.referee, contrat or 'Passe')
+
+
 
+    def tarotGameShowCards(self, game_stage, cards, data):
+        """Display cards in the middle of the game (to show for e.g. chien ou poignée)"""
+        self.to_show = []
+        for suit, value in cards:
+            self.to_show.append(self.cards[(suit, value)])
+        self.updateToShow()
+        if game_stage == "chien" and data['attaquant'] == self.player_nick:
+            self.state = "wait_for_ecart"
+        else:
+            self.state = "chien"
+
--- a/browser_side/panels.py	Wed May 18 01:45:28 2011 +0200
+++ b/browser_side/panels.py	Thu May 19 02:00:59 2011 +0200
@@ -495,6 +495,16 @@
         self.setStyleName('chatPanel')
         self.addClickListener(self)
 
+    def doDetachChildren(self):
+        #We need to force the use of a panel subclass method here,
+        #for the same reason as doAttachChildren
+        ScrollPanelWrapper.doDetachChildren(self)
+
+    def doAttachChildren(self):
+        #We need to force the use of a panel subclass method here, else
+        #the event will not propagate to children
+        ScrollPanelWrapper.doAttachChildren(self)
+
     def onClick(self, sender, event):
         self.host.select(self)
     
--- a/libervia.py	Wed May 18 01:45:28 2011 +0200
+++ b/libervia.py	Thu May 19 02:00:59 2011 +0200
@@ -109,6 +109,8 @@
     def select(self, widget):
         """Define the selected widget"""
         if self.selected:
+            if self.selected == widget:
+                return
             self.selected.removeStyleName('selected_widget')
         self.selected = widget
         if widget:
@@ -170,7 +172,8 @@
         elif name == 'tarotGameStarted':
             self._tarotGameStartedCb(*args)
         elif name == 'tarotGameNew' or \
-             name == 'tarotGameChooseContrat':
+             name == 'tarotGameChooseContrat' or \
+             name == 'tarotGameShowCards':
             self._tarotGameGenericCb(name, args[0], args[1:])
 
     def _getProfileJidCB(self, jid):
--- a/libervia.tac	Wed May 18 01:45:28 2011 +0200
+++ b/libervia.tac	Thu May 19 02:00:59 2011 +0200
@@ -362,7 +362,7 @@
         self.bridge.register("connected", self.signal_handler.connected)
         self.bridge.register("connectionError", self.signal_handler.connectionError)
         for signal_name in ['presenceUpdate', 'personalEvent', 'newMessage', 'roomJoined', 'roomUserJoined', 'roomUserLeft', 'tarotGameStarted', 'tarotGameNew',
-                            'tarotGameChooseContrat']:
+                            'tarotGameChooseContrat', 'tarotGameShowCards']:
             self.bridge.register(signal_name, self.signal_handler.getGenericCb(signal_name))
         root.putChild('json_signal_api', self.signal_handler)
         root.putChild('json_api', MethodHandler(self))