Remove the promise of ducks
[tabakrolletjie.git] / tabakrolletjie / widgets.py
index 2678e72c46cce18b390686ee079dda184ee1e56b..5d58d29bd0f3e151e9d28f7f8b2863fb3583fcd2 100644 (file)
@@ -3,19 +3,55 @@
 # There is no implied container / window system (yet)
 
 import pygame.locals as pgl
+import pygame.mouse
+import pygame.surface
 
 from .loader import loader
-from .constants import FONTS
-from .transforms import NullTransform
+from .constants import FONTS, COLOURS
+from .transforms import NullTransform, Multiply
 
 
+class Tooltip(object):
+    def __init__(self, textparts, font='sans', size=12, padding=5, distance=10):
+        self._font = loader.load_font(FONTS[font], size=size)
+        self._text = [self._font.render(text, True, COLOURS["white"]) for text in textparts]
+        self._padding = padding
+        self._distance =  distance
+
+    def render(self, surface, tool_pos, tool_width):
+        width = max(t.get_size()[0] for t in self._text) + 2 * self._padding
+        height = sum(t.get_size()[1] for t in self._text) + 2 * self._padding
+
+        tooltip = pygame.surface.Surface(
+            (width, height), pgl.SWSURFACE).convert_alpha()
+        tooltip.fill((0, 0, 0, 172))
+
+        ty = 0
+        for t in self._text:
+            tooltip.blit(t, (self._padding, self._padding + ty), None)
+            ty += self._font.get_height()
+
+        x = tool_pos[0] - width/2 + tool_width/2
+        y = tool_pos[1] - height - self._distance
+
+        surface.blit(tooltip, (x, y), None)
+        
+
 class Button(object):
 
-    def __init__(self, size, name=None, pos=None, padding=10):
+    def __init__(self, size, name=None, pos=None, padding=10, tooltip=None):
         self._size = size
         self._padding = padding
         self.position = pos
         self.name = name
+        self.enabled = True
+        self.tooltip = tooltip
+
+    def enable(self):
+        self.enabled = True
+
+    def disable(self):
+        self.enabled = False
 
     @property
     def position(self):
@@ -40,6 +76,8 @@ class Button(object):
         pass
 
     def pressed(self, ev):
+        if not self.enabled:
+            return False
         if self._pos is None:
             # Unplaced buttons can't be pressed
             return False
@@ -49,17 +87,51 @@ class Button(object):
                     return True
         return False
 
+    def mouseover(self):
+        if not self.enabled:
+            return False
+        if self._pos is None:
+            # Unplaced buttons can't be moused over
+            return False
+
+        mpos = pygame.mouse.get_pos()
+        
+        if self._min_x < mpos[0] < self._max_x:
+            if self._min_y < mpos[1] < self._max_y:
+                return True
+        return False
+
+
+class SpacerButton(Button):
+    """ Add a nothing object which can be used to space other things,
+        but is never pressed """
+
+    def pressed(self, ev):
+        return False
+
 
 class TextButton(Button):
 
-    def __init__(self, text, colour, name=None, pos=None, padding=10):
-        font = loader.load_font(FONTS['sans'], size=24)
+    def __init__(
+            self, text, colour, name=None, pos=None, padding=10, size=24,
+            font='sans', centre=False, tooltip=None):
+        font = loader.load_font(FONTS[font], size=size)
         self._text = font.render(text, True, colour)
+        if centre:
+            w, h = self._text.get_size()
+            pos = pos[0] - (w / 2), pos[1] - (h / 2)
+        self._disabled_text = self._text.copy()
+        Multiply(colour=(80, 80, 80)).apply(self._disabled_text)
         super(TextButton, self).__init__(self._text.get_size(), name,
-                                         pos, padding)
+                                         pos, padding, tooltip)
 
     def render(self, surface):
-        surface.blit(self._text, self._pos, None)
+        if self.enabled:
+            surface.blit(self._text, self._pos, None)
+            if self.mouseover() and self.tooltip:
+                self.tooltip.render(surface, self._pos, self.get_width())
+        else:
+            surface.blit(self._disabled_text, self._pos, None)
 
 
 class ImageButton(Button):
@@ -69,15 +141,24 @@ class ImageButton(Button):
         self._img = kwargs.pop("image", None)
         if self._img is None:
             self._img = loader.load_image(*imgparts, transform=transform)
+        self._disabled_img = self._img.copy()
+        disabled_colour = kwargs.pop("disabled_colour", (80, 80, 80))
+        Multiply(colour=disabled_colour).apply(self._disabled_img)
         name = kwargs.get('name')
         pos = kwargs.get('pos')
         padding = kwargs.get('padding', 0)
+        tooltip = kwargs.get('tooltip')
         super(ImageButton, self).__init__(self._img.get_size(), name,
-                                          pos, padding)
+                                          pos, padding, tooltip)
 
     def update_image(self, *imgparts, **kwargs):
         transform = kwargs.pop("transform", NullTransform())
         self._img = loader.load_image(*imgparts, transform=transform)
 
     def render(self, surface):
-        surface.blit(self._img, self._pos, None)
+        if self.enabled:
+            surface.blit(self._img, self._pos, None)
+            if self.mouseover() and self.tooltip:
+                self.tooltip.render(surface, self._pos, self.get_width())
+        else:
+            surface.blit(self._disabled_img, self._pos, None)