Refaktoring (Fabrik et. al)
authorJoachim Breitner <mail@joachim-breitner.de>
Sat, 7 Jul 2007 07:20:48 +0000 (07:20 +0000)
committerJoachim Breitner <mail@joachim-breitner.de>
Sat, 7 Jul 2007 07:20:48 +0000 (07:20 +0000)
cairoboard.py
engine.py
ozeanien.py

index 3d9a13e..4f6ade3 100644 (file)
@@ -9,6 +9,8 @@ import cairo
 import math
 import random
 
+import engine
+
 # Constants
 
 GRIDWIDTH = 70
@@ -22,13 +24,12 @@ BH_X = 2 * GRIDPAD + 10*GRIDWIDTH
 BH_Y = 5 * GRIDWIDTH
 
 class CairoBoard(gtk.DrawingArea):
-    def __init__(self,board):
+    def __init__(self,fabric, board):
         assert board
         self.board = board
+        self.fabric = fabric
 
         self.base_surface = None
-        self.hand_x = 0
-        self.hand_y = 0
         
         self.highlighted_slot = None
 
@@ -48,6 +49,14 @@ class CairoBoard(gtk.DrawingArea):
         
         self.reset()
 
+        # Creatings Drawing Things
+        for col in self.board.slots:
+            for slot in col:
+                self.fabric.setup(slot)
+        self.fabric.setup(self.board.bh)
+        self.fabric.setup(self.board.pile)
+        self.fabric.setup(self.board.hand)
+
     def reset(self):
         self.queue_draw()
 
@@ -59,11 +68,10 @@ class CairoBoard(gtk.DrawingArea):
         cr.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
         cr.clip()
 
-        self.draw_board(self.board, self.window)
+        self.draw(self.window)
 
     def hover(self, widget, event):
-        self.hand_x = event.x
-        self.hand_y = event.y
+        self.board.hand.guiinfo.move_to(event.x, event.y)
         if not self.board.hand.is_empty():
             self.queue_draw()
 
@@ -77,7 +85,6 @@ class CairoBoard(gtk.DrawingArea):
             self.highlighted_slot = slot
             self.queue_draw()
 
-
     def pileclick(self, event):
         return (2*abs(event.x - PILE_X) < GRIDWIDTH and
                 2*abs(event.y - PILE_Y + 3*SCALE) < GRIDWIDTH)
@@ -92,7 +99,6 @@ class CairoBoard(gtk.DrawingArea):
         else:
             return 0
 
-
     def event2slot(self, event):
         x = int((event.x - GRIDPAD) // GRIDWIDTH)
         y = int((event.y - GRIDPAD) // GRIDWIDTH)
@@ -107,18 +113,201 @@ class CairoBoard(gtk.DrawingArea):
         else:
             return None
 
-    def draw_board(self, board, window):
+    def draw(self, window):
         self.draw_cached_base(window)
 
-        for col in board.slots:
+        self.draw_points(self.board.points, window)
+
+        for col in self.board.slots:
             for slot in col:
-                self.draw_boardslot(slot,window)
+                slot.guiinfo.draw(window)
+        self.board.bh.guiinfo.draw(window)
+        self.board.pile.guiinfo.draw(window)
+        self.board.hand.guiinfo.draw(window)
+        #self.draw_hand(self.board.hand, window, self.hand_x, self.hand_y)
+    
+    def draw_points(self, points, window):
+        cr = window.cairo_create()
+        cr.translate(2 * GRIDPAD + 10*GRIDWIDTH, 6 * GRIDWIDTH)
+        cr.scale(SCALE, SCALE)
+
+        txt = "%ip" % points
+
+        cr.set_font_size(1)
+        cr.set_source_rgb(0,0,0)
+        (_,_,w,h,_,_) = cr.text_extents(txt)
+
+        cr.move_to(-w/2, h/2)
+        cr.show_text(txt)
+        cr.fill()
+
+
+    def draw_cached_base(self,window):
+        ocr = window.cairo_create()
+        if not self.base_surface:
+            self.base_surface = ocr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
+                    2*GRIDPAD + 9*GRIDWIDTH, 2*GRIDPAD + 6*GRIDWIDTH)
+
+            cr = cairo.Context(self.base_surface)
+            self.draw_base(cr)
 
-        self.draw_bh(board.bh, window)
-        self.draw_points(board.points, window)
-        self.draw_pile(board.pile, window)
-        self.draw_hand(board.hand, window, self.hand_x, self.hand_y)
+        ocr.set_source_surface(self.base_surface,0,0)
+        ocr.rectangle(0,0,
+                2*GRIDPAD + 9*GRIDWIDTH, 2*GRIDPAD + 6*GRIDWIDTH)
+        ocr.fill()
+
+class CairoSlot:
+    pass
+
+class SeaBoard(CairoBoard):
+    def draw_base(self, cr):
+        cr.translate(GRIDPAD, GRIDPAD)
+        cr.scale(GRIDWIDTH, GRIDWIDTH)
 
+        # Sea Background
+        # Unten
+        pat = cairo.LinearGradient (0, 5, 0, 5.5)
+        pat.add_color_stop_rgba(0, 0, 0, 1,1)
+        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        cr.rectangle(1, 5, 7, 0.5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Oben
+        pat = cairo.LinearGradient (0, 0, 0, -0.5)
+        pat.add_color_stop_rgba(0, 0, 0, 1,1)
+        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        cr.rectangle(1, -0.5, 7, 0.5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Links
+        pat = cairo.LinearGradient (1, 0, 0.5, 0)
+        pat.add_color_stop_rgba(0, 0, 0, 1,1)
+        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        cr.rectangle(0.5, 0, 0.5, 5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Rechts
+        pat = cairo.LinearGradient (8, 0, 8.5, 0)
+        pat.add_color_stop_rgba(0, 0, 0, 1,1)
+        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        cr.rectangle(8, 0, 0.5, 5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Oben Links
+        pat = cairo.RadialGradient(1,0,0, 1,0, 0.5)
+        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
+        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        cr.rectangle(0.5, -0.5, 0.5, 0.5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Oben Rechts
+        pat = cairo.RadialGradient(8,0,0, 8,0, 0.5)
+        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
+        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        cr.rectangle(8, -0.5, 8.5, 0.5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Unten Rechts
+        pat = cairo.RadialGradient(8,5,0, 8,5, 0.5)
+        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
+        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        cr.rectangle(8, 5, 8.5, 5.5)
+        cr.set_source(pat)
+        cr.fill()
+
+        # Unten Links
+        pat = cairo.RadialGradient(1,5,0, 1,5, 0.5)
+        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
+        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        cr.rectangle(0.5, 5, 1, 5.5)
+        cr.set_source(pat)
+        cr.fill()
+
+
+        # Frame
+        cr.set_source_rgb(1,1,1)
+        cr.set_line_width(0.05)
+        cr.set_line_cap(cairo.LINE_CAP_ROUND)
+        for x in range(0,8):
+            cr.move_to(1+x, 0)
+            cr.line_to(1+x, 5.5)
+            cr.stroke()
+        for y in range(0,6):
+            cr.move_to(0.5, y)
+            cr.line_to(8.5, y)
+            cr.stroke()
+
+class SeaSlot(CairoSlot):
+    def __init__(self, fabric, slot):
+        self.fabric = fabric
+        self.slot = slot
+
+    def translate(self, cr):
+        raise "Abstract Method of Object" + str(self)
+
+    def draw(self, window):
+        if self.slot.card or self.slot.ship:
+            cr = window.cairo_create()
+            self.translate(cr)
+            cr.scale(SCALE, SCALE)
+
+            #cr.rectangle(-1, -1, 2, 2)
+            #cr.clip()
+
+            matrix = cr.get_matrix()
+            if self.slot.card:
+                self.fabric.setup(self.slot.card)
+                self.slot.card.guiinfo.draw(cr)
+                cr.set_matrix(matrix)
+            if self.slot.ship:
+                self.fabric.setup(self.slot.ship)
+                self.slot.ship.guiinfo.draw(cr)
+                cr.set_matrix(matrix)
+
+            if self.slot.highlighted:
+                cr.set_source_rgba(1, 1, 1, 0.5)
+                cr.rectangle(-1, -1, 2, 2)
+                cr.fill()
+
+class SeaHandSlot(SeaSlot):
+    def __init__(self, fabric, slot):
+        SeaSlot.__init__(self, fabric, slot)
+        self.x = 0
+        self.y = 0
+
+    def move_to(self, x,y):
+        self.x = x
+        self.y = y
+
+    def translate(self, cr):
+        cr.translate(self.x, self.y)
+
+class SeaBoardSlot(SeaSlot):
+    def __init__(self, fabric, slot):
+        SeaSlot.__init__(self, fabric, slot)
+
+    def translate(self, cr):
+        cr.translate(
+                 GRIDPAD + (self.slot.x+0.5)*GRIDWIDTH,
+                 GRIDPAD + (self.slot.y+0.5)*GRIDWIDTH
+        )
+
+class SeaPile(SeaSlot):
+    def __init__(self, fabric, slot):
+        SeaSlot.__init__(self, fabric, slot)
+        self.pile = self.slot
+
+    def translate(self, cr):
+        cr.translate(
+                PILE_X,
+                PILE_Y,
+        )
     
     def draw_arrow(self, cr):
         cr.arc(1, 1, 0.5, 0, math.pi/2)
@@ -133,7 +322,7 @@ class CairoBoard(gtk.DrawingArea):
         cr.line_to(1   , 1.25)
         cr.stroke()
 
-    def draw_pile(self, pile, window):
+    def draw(self, window):
         cr = window.cairo_create()
         cr.translate(PILE_X, PILE_Y)
         cr.scale(SCALE, SCALE)
@@ -150,7 +339,7 @@ class CairoBoard(gtk.DrawingArea):
 
         cr.set_line_cap(cairo.LINE_CAP_SQUARE)
         cr.translate(0,-3)
-        if pile.cards:
+        if self.pile.cards:
             cr.set_source_rgb(0, 0, 0.5)
             cr.rectangle(-1, -1, 2, 2)
             cr.fill()
@@ -162,30 +351,20 @@ class CairoBoard(gtk.DrawingArea):
 
         cr.set_font_size(1)
         cr.set_source_rgb(1,1,1)
-        (_,_,w,h,_,_) = cr.text_extents(str(len(pile.cards)))
+        (_,_,w,h,_,_) = cr.text_extents(str(len(self.pile.cards)))
 
         cr.move_to(-w/2, h/2)
-        cr.show_text(str(len(pile.cards)))
+        cr.show_text(str(len(self.pile.cards)))
         cr.fill()
 
-        self.draw_slot(pile, window, PILE_X, PILE_Y)
+        SeaSlot.draw(self, window)
 
-    def draw_points(self, points, window):
-        cr = window.cairo_create()
-        cr.translate(2 * GRIDPAD + 10*GRIDWIDTH, 6 * GRIDWIDTH)
-        cr.scale(SCALE, SCALE)
+class SeaBlackHole:
+    def __init__(self, fabric, bh):
+        self.fabric = fabric
+        self.bh = bh
 
-        txt = "%ip" % points
-
-        cr.set_font_size(1)
-        cr.set_source_rgb(0,0,0)
-        (_,_,w,h,_,_) = cr.text_extents(txt)
-
-        cr.move_to(-w/2, h/2)
-        cr.show_text(txt)
-        cr.fill()
-
-    def draw_bh(self, bh, window):
+    def draw(self, window):
         cr = window.cairo_create()
         cr.translate(BH_X, BH_Y)
         cr.scale(SCALE, SCALE)
@@ -199,52 +378,35 @@ class CairoBoard(gtk.DrawingArea):
         
         cr.set_font_size(1)
         cr.set_source_rgb(1,1,1)
-        (_,_,w,h,_,_) = cr.text_extents(str(bh.count))
+        (_,_,w,h,_,_) = cr.text_extents(str(self.bh.count))
 
         cr.move_to(-w/2, h/2)
-        cr.show_text(str(bh.count))
+        cr.show_text(str(self.bh.count))
         cr.fill()
 
-    def draw_boardslot(self, slot, window):
-        self.draw_slot(slot, window,
-            GRIDPAD + (slot.x+0.5) * GRIDWIDTH,
-            GRIDPAD + (slot.y+0.5) * GRIDWIDTH)
-
-    def draw_slot(self, slot, window, x, y):
-        if slot.card or slot.ship:
-            cr = window.cairo_create()
-            cr.translate(x, y)
-            cr.scale(SCALE, SCALE)
+class SeaCard:
+    def __init__(self, fabric, card):
+        self.fabric = fabric
+        self.card = card
+        self.cache = None
 
-            #cr.rectangle(-1, -1, 2, 2)
-            #cr.clip()
-
-            matrix = cr.get_matrix()
-            if slot.card:
-                self.draw_cached_card(slot.card, cr)
-                cr.set_matrix(matrix)
-            if slot.ship:
-                self.draw_cached_ship(slot.ship, cr)
-                cr.set_matrix(matrix)
-
-            if slot.highlighted:
-                cr.set_source_rgba(1, 1, 1, 0.5)
-                cr.rectangle(-1, -1, 2, 2)
-                cr.fill()
+    def draw(self, cr):
+        cr.rotate(-(self.card.rotation * math.pi / 2))
 
-    def draw_ship(self, ship, cr):
-        cr.move_to(0.9, 0)
-        cr.arc(0, 0, 0.3, math.pi, 0) 
-        cr.line_to(-0.9,0)
-        cr.line_to(-0.6, 0.6)
-        cr.line_to( 0.6, 0.6)
+        if not self.cache:
+            self.cache = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
+                    GRIDWIDTH + GRIDPAD, GRIDWIDTH + GRIDPAD)
+            scr = cairo.Context(self.cache)
+            scr.translate((GRIDWIDTH + GRIDPAD)/2, (GRIDWIDTH+GRIDPAD)/2)
+            scr.scale(SCALE, SCALE)
 
-        cr.set_source_rgb(1, 0, 0)
-        cr.fill()
+            self.draw_cache(scr)
 
-    draw_hand = draw_slot
+        cr.scale(1.0/SCALE, 1.0/SCALE)
+        cr.set_source_surface(self.cache,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
+        cr.paint()
 
-    def draw_card(self, card, cr):
+    def draw_cache(self, cr):
         # Meer
         cr.set_source_rgb(0, 0, 1)
         cr.rectangle(-1, -1, 2, 2)
@@ -258,7 +420,7 @@ class CairoBoard(gtk.DrawingArea):
         p2c = [ (1,0), (0,-1), (-1,0), (0,1) ]
 
         # Land
-        for island in card.islands:
+        for island in self.card.islands:
             point = island[0]
             cr.move_to( *p2c[point] )
             for point in island[1:]:
@@ -273,72 +435,134 @@ class CairoBoard(gtk.DrawingArea):
         cr.rectangle(-1, -1, 2, 2)
         cr.stroke()
 
-    def draw_base(self, cr):
+class SeaShip:
+    def __init__(self, fabric, ship):
+        self.fabric = fabric
+        self.ship = ship
+        self.cache = None
+    
+    def draw_cache(self, cr):
+        cr.move_to(0.9, 0)
+        cr.arc(0, 0, 0.3, math.pi, 0) 
+        cr.line_to(-0.9,0)
+        cr.line_to(-0.6, 0.6)
+        cr.line_to( 0.6, 0.6)
+
+        cr.set_source_rgb(1, 0, 0)
+        cr.fill()
+
+    def draw(self, cr):
+        cr.rotate(-(self.ship.rotation * math.pi / 2))
+        cr.rotate(math.pi / 2) # Koordinaten unten passen sonst nicht
+
+        if not self.cache:
+            self.cache = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
+                    GRIDWIDTH + GRIDPAD, GRIDWIDTH + GRIDPAD)
+            scr = cairo.Context(self.cache)
+            scr.translate((GRIDWIDTH + GRIDPAD)/2, (GRIDWIDTH+GRIDPAD)/2)
+            scr.scale(SCALE, SCALE)
+
+            self.draw_cache(scr)
+
+        cr.scale(1.0/SCALE, 1.0/SCALE)
+        cr.set_source_surface(self.cache,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
+        cr.paint()
+
+class CairoFabric:
+    def get_widget(self, board):
+        board_draw = self.get_drawer(board)
+        board.guiinfo = board_draw
+        return board_draw
+
+    def get_drawer(self, object):
+        for c, drawer in self.classes:
+            if isinstance(object, c):
+                return drawer(self, object)
+        raise "No Drawing Class for "+str(object)
+
+    def setup(self, object):
+        if not object.guiinfo:
+            object.guiinfo = self.get_drawer(object)
+
+class SeaFabric(CairoFabric):
+    classes = [ 
+            (engine.Board,      SeaBoard),
+            (engine.BoardSlot,  SeaBoardSlot),
+            (engine.HandSlot,   SeaHandSlot),
+            (engine.Pile,       SeaPile),
+            (engine.Slot,       SeaSlot),
+            (engine.Ship,       SeaShip),
+            (engine.Card,       SeaCard),
+    ]
+
+class GrassBoard(CairoBoard):
+    def draw_base(self,cr):
         cr.translate(GRIDPAD, GRIDPAD)
         cr.scale(GRIDWIDTH, GRIDWIDTH)
 
         # Sea Background
+
         # Unten
         pat = cairo.LinearGradient (0, 5, 0, 5.5)
-        pat.add_color_stop_rgba(0, 0, 0, 1,1)
-        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
         cr.rectangle(1, 5, 7, 0.5)
         cr.set_source(pat)
         cr.fill()
 
         # Oben
         pat = cairo.LinearGradient (0, 0, 0, -0.5)
-        pat.add_color_stop_rgba(0, 0, 0, 1,1)
-        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
         cr.rectangle(1, -0.5, 7, 0.5)
         cr.set_source(pat)
         cr.fill()
 
         # Links
         pat = cairo.LinearGradient (1, 0, 0.5, 0)
-        pat.add_color_stop_rgba(0, 0, 0, 1,1)
-        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
         cr.rectangle(0.5, 0, 0.5, 5)
         cr.set_source(pat)
         cr.fill()
 
         # Rechts
         pat = cairo.LinearGradient (8, 0, 8.5, 0)
-        pat.add_color_stop_rgba(0, 0, 0, 1,1)
-        pat.add_color_stop_rgba(1, 0, 0, 1,0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
         cr.rectangle(8, 0, 0.5, 5)
         cr.set_source(pat)
         cr.fill()
 
         # Oben Links
         pat = cairo.RadialGradient(1,0,0, 1,0, 0.5)
-        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
-        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
         cr.rectangle(0.5, -0.5, 0.5, 0.5)
         cr.set_source(pat)
         cr.fill()
 
         # Oben Rechts
         pat = cairo.RadialGradient(8,0,0, 8,0, 0.5)
-        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
-        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
         cr.rectangle(8, -0.5, 8.5, 0.5)
         cr.set_source(pat)
         cr.fill()
 
         # Unten Rechts
         pat = cairo.RadialGradient(8,5,0, 8,5, 0.5)
-        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
-        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
         cr.rectangle(8, 5, 8.5, 5.5)
         cr.set_source(pat)
         cr.fill()
 
         # Unten Links
         pat = cairo.RadialGradient(1,5,0, 1,5, 0.5)
-        pat.add_color_stop_rgba(0, 0, 0, 1, 1)
-        pat.add_color_stop_rgba(1, 0, 0, 1, 0)
-        cr.rectangle(0.5, 5, 1, 5.5)
+        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
+        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
+        cr.rectangle(0.5, 5, 0.5, 5.5)
         cr.set_source(pat)
         cr.fill()
 
@@ -356,56 +580,209 @@ class CairoBoard(gtk.DrawingArea):
             cr.line_to(8.5, y)
             cr.stroke()
 
-    def draw_cached_ship(self,ship,cr):
-        cr.rotate(-(ship.rotation * math.pi / 2))
+class GrassSlot(CairoSlot):
+    def __init__(self, fabric, slot):
+        self.fabric = fabric
+        self.slot = slot
+
+    def translate(self, cr):
+        raise "Abstract Method of Object" + str(self)
+
+    def draw(self, window):
+        if self.slot.card or self.slot.ship:
+            cr = window.cairo_create()
+            self.translate(cr)
+            cr.scale(SCALE, SCALE)
+
+            #cr.rectangle(-1, -1, 2, 2)
+            #cr.clip()
+
+            matrix = cr.get_matrix()
+            if self.slot.card:
+                self.fabric.setup(self.slot.card)
+                self.slot.card.guiinfo.draw(cr)
+                cr.set_matrix(matrix)
+            if self.slot.ship:
+                self.fabric.setup(self.slot.ship)
+                self.slot.ship.guiinfo.draw(cr)
+                cr.set_matrix(matrix)
+
+            if self.slot.highlighted:
+                cr.set_source_rgba(1, 1, 1, 0.5)
+                cr.rectangle(-1, -1, 2, 2)
+                cr.fill()
+
+class GrassBoardSlot(GrassSlot):
+    def __init__(self, fabric, slot):
+        GrassSlot.__init__(self, fabric, slot)
+
+    def translate(self, cr):
+        cr.translate(
+                 GRIDPAD + (self.slot.x+0.5)*GRIDWIDTH,
+                 GRIDPAD + (self.slot.y+0.5)*GRIDWIDTH
+        )
+
+class GrassShip:
+    def __init__(self, fabric, ship):
+        self.fabric = fabric
+        self.ship = ship
+        self.cache = None
+    
+    def draw_cache(self, cr):
+        # Grundkörper (noch abzurunden)
+        cr.move_to(-0.5, -0.75)
+        cr.line_to(0.5, -0.75)
+        cr.line_to(0.5, 0.5)
+        cr.line_to(-0.5, 0.5)
+        cr.close_path()
+        cr.set_source_rgb(1, 0.2, 0.2)
+        cr.fill_preserve()
+        cr.set_source_rgb(0, 0, 0)
+        cr.set_line_width(0.05)
+        cr.stroke()
+
+        # Griff
+        cr.move_to(-0.25, 0.25)
+        cr.line_to(-0.55,  0.75)
+        cr.line_to( 0.55,  0.75)
+        cr.line_to( 0.25, 0.25)
+        cr.set_line_width(0.1)
+        cr.set_line_join(cairo.LINE_JOIN_ROUND)
+        cr.stroke()
+        
+        # Motor
+        cr.arc(0, -0.1 , 0.3, 0, 2*math.pi)
+        cr.set_source_rgb(0, 0, 0)
+        cr.fill()
+
+        # Augen
+        for _ in range(2):
+            cr.scale(-1,1)
+            cr.arc(0.3, -0.55 , 0.15, 0, 2*math.pi)
+            cr.set_source_rgb(1, 1, 1)
+            cr.fill_preserve()
+            cr.set_source_rgb(0, 0, 0)
+            cr.set_line_width(0.05)
+            cr.stroke()
+            cr.arc(0.25, -0.6 , 0.05, 0, 2*math.pi)
+            cr.set_source_rgb(0, 0, 0)
+            cr.fill()
+
+    def draw(self, cr):
+        cr.rotate(-(self.ship.rotation * math.pi / 2))
         cr.rotate(math.pi / 2) # Koordinaten unten passen sonst nicht
 
-        if not ship.guiinfo:
-            ship.guiinfo = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
+        if not self.cache:
+            self.cache = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
                     GRIDWIDTH + GRIDPAD, GRIDWIDTH + GRIDPAD)
-            scr = cairo.Context(ship.guiinfo)
+            scr = cairo.Context(self.cache)
             scr.translate((GRIDWIDTH + GRIDPAD)/2, (GRIDWIDTH+GRIDPAD)/2)
             scr.scale(SCALE, SCALE)
 
-            self.draw_ship(ship, scr)
+            self.draw_cache(scr)
 
         cr.scale(1.0/SCALE, 1.0/SCALE)
-        cr.set_source_surface(ship.guiinfo,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
+        cr.set_source_surface(self.cache,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
         cr.paint()
 
-    def draw_cached_card(self,card,cr):
-        cr.rotate(-(card.rotation * math.pi / 2))
+class GrassHandSlot(GrassSlot):
+    def __init__(self, fabric, slot):
+        GrassSlot.__init__(self, fabric, slot)
+        self.x = 0
+        self.y = 0
 
-        if not card.guiinfo:
-            card.guiinfo = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
+    def move_to(self, x,y):
+        self.x = x
+        self.y = y
+
+    def translate(self, cr):
+        cr.translate(self.x, self.y)
+
+class GrassPile(GrassSlot):
+    def __init__(self, fabric, slot):
+        GrassSlot.__init__(self, fabric, slot)
+        self.pile = self.slot
+
+    def translate(self, cr):
+        cr.translate(
+                PILE_X,
+                PILE_Y,
+        )
+    
+    def draw_arrow(self, cr):
+        cr.arc(1, 1, 0.5, 0, math.pi/2)
+        cr.set_source_rgb(0, 0, 0)
+        cr.set_line_width(0.1)
+        cr.set_line_cap(cairo.LINE_CAP_ROUND)
+        cr.move_to(1,    1.5)
+        cr.line_to(0.75, 1.5)
+        cr.move_to(0.75, 1.5)
+        cr.line_to(1   , 1.75)
+        cr.move_to(0.75, 1.5)
+        cr.line_to(1   , 1.25)
+        cr.stroke()
+
+    def draw(self, window):
+        cr = window.cairo_create()
+        cr.translate(PILE_X, PILE_Y)
+        cr.scale(SCALE, SCALE)
+
+        cr.set_source_rgb(0.8, 0.8, 0.8)
+        cr.rectangle(-1, -1, 2, 2)
+        cr.fill()
+
+        matrix = cr.get_matrix()
+        self.draw_arrow(cr)
+        cr.scale(-1,1)
+        self.draw_arrow(cr)
+        cr.set_matrix(matrix)
+
+        cr.set_line_cap(cairo.LINE_CAP_SQUARE)
+        cr.translate(0,-3)
+        if self.pile.cards:
+            cr.set_source_rgb(0, 0, 0.5)
+            cr.rectangle(-1, -1, 2, 2)
+            cr.fill()
+        else:
+            cr.set_source_rgb(0, 0, 0)
+            cr.set_line_width(0.05)
+            cr.rectangle(-1, -1, 2, 2)
+            cr.stroke()
+
+        cr.set_font_size(1)
+        cr.set_source_rgb(1,1,1)
+        (_,_,w,h,_,_) = cr.text_extents(str(len(self.pile.cards)))
+
+        cr.move_to(-w/2, h/2)
+        cr.show_text(str(len(self.pile.cards)))
+        cr.fill()
+
+        GrassSlot.draw(self, window)
+
+class GrassCard:
+    def __init__(self, fabric, card):
+        self.fabric = fabric
+        self.card = card
+        self.cache = None
+
+    def draw(self, cr):
+        cr.rotate(-(self.card.rotation * math.pi / 2))
+
+        if not self.cache:
+            self.cache = cr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
                     GRIDWIDTH + GRIDPAD, GRIDWIDTH + GRIDPAD)
-            scr = cairo.Context(card.guiinfo)
+            scr = cairo.Context(self.cache)
             scr.translate((GRIDWIDTH + GRIDPAD)/2, (GRIDWIDTH+GRIDPAD)/2)
             scr.scale(SCALE, SCALE)
 
-            self.draw_card(card, scr)
+            self.draw_cache(scr)
 
         cr.scale(1.0/SCALE, 1.0/SCALE)
-        cr.set_source_surface(card.guiinfo,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
+        cr.set_source_surface(self.cache,-(GRIDWIDTH + GRIDPAD)/2,-(GRIDWIDTH + GRIDPAD)/2)
         cr.paint()
 
-    def draw_cached_base(self,window):
-        ocr = window.cairo_create()
-        if not self.base_surface:
-            self.base_surface = ocr.get_target().create_similar(cairo.CONTENT_COLOR_ALPHA, 
-                    2*GRIDPAD + 9*GRIDWIDTH, 2*GRIDPAD + 6*GRIDWIDTH)
-
-            cr = cairo.Context(self.base_surface)
-            self.draw_base(cr)
-
-        ocr.set_source_surface(self.base_surface,0,0)
-        ocr.rectangle(0,0,
-                2*GRIDPAD + 9*GRIDWIDTH, 2*GRIDPAD + 6*GRIDWIDTH)
-        ocr.fill()
-
-class GrassBoard(CairoBoard):
     #Karte füllen
-    def draw_card(self, card, cr):
+    def draw_cache(self, cr):
         orientation=0;
         cr.set_source_rgb(0.6, 0.4, 0.3)
         cr.rectangle(-1, -1, 2, 2)
@@ -454,24 +831,22 @@ class GrassBoard(CairoBoard):
                     
                 ]:
             cr.translate(*c)
-            self.draw_gras(card, cr, 0)
-            self.draw_gras(card, cr, 1)
+            self.draw_gras(cr, 0)
+            self.draw_gras(cr, 1)
             cr.set_matrix(matrix)
 
-        for island in card.islands:
+        for island in self.card.islands:
             for dir in island:
                 cr.translate(*p2c[dir])
-                self.draw_flower(card, cr)
+                self.draw_flower(cr)
                 cr.set_matrix(matrix)
             for dir in island[:-1]:
                 cr.translate(*between_p2c[dir])
-                self.draw_flower(card, cr)
+                self.draw_flower(cr)
                 cr.set_matrix(matrix)
-        #self.draw_gras(card, cr, orientation)
-        #self.draw_flower(card, cr)
 
     #Einen Grashalm malen
-    def draw_gras(self, card, cr, orientation):
+    def draw_gras(self, cr, orientation):
         x=random.uniform(0.1,0.2)
         y=random.uniform(0.2,0.3)
         matrix=cr.get_matrix()
@@ -497,7 +872,7 @@ class GrassBoard(CairoBoard):
 
 
     #Eine Blume malen
-    def draw_flower(self, card,cr):
+    def draw_flower(self, cr):
         cr.rotate(random.uniform(0,2*math.pi))
         matrix=cr.get_matrix()
         cr.scale(0.25, 0.25)
@@ -514,130 +889,16 @@ class GrassBoard(CairoBoard):
             cr.rotate(2* math.pi / 5)
         cr.set_matrix(matrix)
     
-    def draw_ship(self, ship, cr):
-        
-        # Grundkörper (noch abzurunden)
-        cr.move_to(-0.5, -0.75)
-        cr.line_to(0.5, -0.75)
-        cr.line_to(0.5, 0.5)
-        cr.line_to(-0.5, 0.5)
-        cr.close_path()
-        cr.set_source_rgb(1, 0.2, 0.2)
-        cr.fill_preserve()
-        cr.set_source_rgb(0, 0, 0)
-        cr.set_line_width(0.05)
-        cr.stroke()
-
-        # Griff
-        cr.move_to(-0.25, 0.25)
-        cr.line_to(-0.55,  0.75)
-        cr.line_to( 0.55,  0.75)
-        cr.line_to( 0.25, 0.25)
-        cr.set_line_width(0.1)
-        cr.set_line_join(cairo.LINE_JOIN_ROUND)
-        cr.stroke()
-        
-        # Motor
-        cr.arc(0, -0.1 , 0.3, 0, 2*math.pi)
-        cr.set_source_rgb(0, 0, 0)
-        cr.fill()
-
-        # Augen
-        for _ in range(2):
-            cr.scale(-1,1)
-            cr.arc(0.3, -0.55 , 0.15, 0, 2*math.pi)
-            cr.set_source_rgb(1, 1, 1)
-            cr.fill_preserve()
-            cr.set_source_rgb(0, 0, 0)
-            cr.set_line_width(0.05)
-            cr.stroke()
-            cr.arc(0.25, -0.6 , 0.05, 0, 2*math.pi)
-            cr.set_source_rgb(0, 0, 0)
-            cr.fill()
-
-    def draw_base(self,cr):
-        cr.translate(GRIDPAD, GRIDPAD)
-        cr.scale(GRIDWIDTH, GRIDWIDTH)
-
-        # Sea Background
-
-        # Unten
-        pat = cairo.LinearGradient (0, 5, 0, 5.5)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
-        cr.rectangle(1, 5, 7, 0.5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Oben
-        pat = cairo.LinearGradient (0, 0, 0, -0.5)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
-        cr.rectangle(1, -0.5, 7, 0.5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Links
-        pat = cairo.LinearGradient (1, 0, 0.5, 0)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
-        cr.rectangle(0.5, 0, 0.5, 5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Rechts
-        pat = cairo.LinearGradient (8, 0, 8.5, 0)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4,1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4,0)
-        cr.rectangle(8, 0, 0.5, 5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Oben Links
-        pat = cairo.RadialGradient(1,0,0, 1,0, 0.5)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
-        cr.rectangle(0.5, -0.5, 0.5, 0.5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Oben Rechts
-        pat = cairo.RadialGradient(8,0,0, 8,0, 0.5)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
-        cr.rectangle(8, -0.5, 8.5, 0.5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Unten Rechts
-        pat = cairo.RadialGradient(8,5,0, 8,5, 0.5)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
-        cr.rectangle(8, 5, 8.5, 5.5)
-        cr.set_source(pat)
-        cr.fill()
-
-        # Unten Links
-        pat = cairo.RadialGradient(1,5,0, 1,5, 0.5)
-        pat.add_color_stop_rgba(0.3, 0.6, 0.4, 0.4, 1)
-        pat.add_color_stop_rgba(1, 0.6, 0.4, 0.4, 0)
-        cr.rectangle(0.5, 5, 0.5, 5.5)
-        cr.set_source(pat)
-        cr.fill()
-
-
-        # Frame
-        cr.set_source_rgb(1,1,1)
-        cr.set_line_width(0.05)
-        cr.set_line_cap(cairo.LINE_CAP_ROUND)
-        for x in range(0,8):
-            cr.move_to(1+x, 0)
-            cr.line_to(1+x, 5.5)
-            cr.stroke()
-        for y in range(0,6):
-            cr.move_to(0.5, y)
-            cr.line_to(8.5, y)
-            cr.stroke()
 
+class GrassFabric(CairoFabric):
+    classes = [ 
+            (engine.Board,      GrassBoard),
+            (engine.BoardSlot,  GrassBoardSlot),
+            (engine.HandSlot,   GrassHandSlot),
+            (engine.Pile,       GrassPile),
+            (engine.Slot,       GrassSlot),
+            (engine.Ship,       GrassShip),
+            (engine.Card,       GrassCard),
+    ]
 
 # vim:ts=4:sw=4:sts=4:et
index 7c7f7ac..2e87807 100644 (file)
--- a/engine.py
+++ b/engine.py
@@ -19,6 +19,7 @@ class Ship:
 
 class Slot:
     def __init__(self):
+        self.guiinfo = None
         self.x = None
         self.y = None
         self.rotateable = None
@@ -329,6 +330,8 @@ class Card:
 
 class Board:
     def __init__(self):
+        self.guiinfo = None
+
         self.slots = []
 
         for x in range(9):
index 05e4675..6c07e21 100644 (file)
@@ -8,7 +8,7 @@ import gtk
 import sys
 
 from engine import * 
-from cairoboard import CairoBoard, GrassBoard
+from cairoboard import SeaFabric, GrassFabric
 
 
 DEBUG = 1
@@ -27,9 +27,9 @@ class Game:
         self.drag_from = None
 
         if len(sys.argv) > 1 and sys.argv[1] == "sea": 
-            self.boarddraw = CairoBoard(self.board)
+            self.boarddraw = SeaFabric().get_widget(self.board)
         else:
-            self.boarddraw = GrassBoard(self.board)
+            self.boarddraw = GrassFabric().get_widget(self.board)
 
         self.boarddraw.connect("button-press-event",   self.press)
         self.boarddraw.connect("button-release-event", self.release)