Logo Search packages:      
Sourcecode: castle-combat version File versions  Download package

widget.py

import pygame
from pygame.locals import *
from Numeric import *
import common
from state import State

class WidgetState(State):

      def __init__(self):
            State.__init__(self)
            self.widgets = []

      def handle(self):
            for w in self.widgets:
                  w.draw()                
            common.update()

      def pass_to_widgets(self, event):
            if event.type == KEYDOWN and event.key == K_ESCAPE:
                  self.quit()
            for w in self.widgets:
                  w.handle_event(event)
      
      events = {
            MOUSEMOTION: pass_to_widgets,
            MOUSEBUTTONDOWN: pass_to_widgets,
            KEYDOWN: pass_to_widgets,
      }

class Widget(object):
      
      freeze_highlight = None

      def __init__(self, pos, text=None, surfaces=None, on_click=None):
            State.stack[-1].widgets.append(self)
            self.on_click = on_click
            self.highlighted = False
            self.inactive = False
            if text != None:
                  self.surfaces_from_text(text)
            elif surfaces != None:
                  (self.normal_surface, self.highlight_surface) = surfaces
            else:
                  raise Exception, "text or surfaces argument required"
            self.inactive_surface = None
            # negative positions are distance from screen edge
            pos = list(pos)
            for i in (0,1):
                  if pos[i] == None:
                        pos[i] = (common.screen.get_size()[i] - self.normal_surface.get_size()[i]) / 2
                  elif pos[i] < 0:
                        pos[i] = common.screen.get_size()[i] + pos[i] - self.normal_surface.get_size()[i]
            self.pos = pos
            
      def draw(self):
            # Widget is inactive
            if self.inactive:
                  if not self.inactive_surface:
                        # Create 50% transparent surface
                        self.inactive_surface = self.normal_surface.convert_alpha()
                        alpha = pygame.surfarray.pixels_alpha(self.inactive_surface)
                        divide(alpha, array(2).astype(UInt8), alpha)
                        del alpha
                  common.blit(self.inactive_surface, self.pos)
                  self.highlighted = False
                  return
            
            # This widget can't be highlighted
            if not self.on_click:
                  common.blit(self.normal_surface, self.pos)
                  return
            
            # Is the mouse pointer above the widget?
            if not Widget.freeze_highlight:
                  self.highlighted = True
                  mouse_pos = pygame.mouse.get_pos()
                  for i in (0,1):
                        if mouse_pos[i] not in range(self.pos[i], self.pos[i] + self.normal_surface.get_size()[i]):
                              self.highlighted = False
            else:
                  self.highlighted = Widget.freeze_highlight == self
                        
            if self.highlighted:
                  surf = self.highlight_surface
            else:
                  surf = self.normal_surface
            common.blit(surf, self.pos)

      def surfaces_from_text(self, text):
            self.normal_surface = common.font.render(str(text), True, (0,0,0))
            self.highlight_surface = common.font.render(str(text), True, (150,0,0))
            
      def handle_event(self, event):
            if not self.highlighted:
                  return
            if (event.type == MOUSEBUTTONDOWN):
                  self.on_click()
            

class Button(Widget):

      def __init__(self, text, pos, on_click):
            Widget.__init__(self, pos, text=text, on_click=on_click)


class Label(Widget):

      def __init__(self, text, pos):
            Widget.__init__(self, pos, text=text)


class SpinBox(Widget):

      up = map(lambda col: common.colorize(common.load_image("arrow.png", alpha=True), col), ( (0,0,0), (150,0,0) ))
      down = map(lambda surf: pygame.transform.flip(surf, False, True), up)

      def __init__(self, label, pos, choices, default=None, on_change=None):
            self._choices = list(choices)
            self.index = 0
            self.label = label
            if default != None:
                  self.value = default
            if on_change:
                  self.on_change = on_change
            Widget.__init__(self, pos, text='', on_click=None)
            up_pos = (pos[0] - SpinBox.up[0].get_width(), pos[1])
            down_pos = (pos[0] - SpinBox.up[0].get_width(), pos[1] + self.normal_surface.get_height() - SpinBox.down[0].get_height())
            self.up_widget = Widget( up_pos, surfaces=SpinBox.up, on_click=lambda:self.change(1))
            self.down_widget = Widget( down_pos, surfaces=SpinBox.down, on_click=lambda:self.change(-1))
            self.update()

      def choices():
            def fget(self):
                  return self._choices
            def fset(self, choices):
                  selected_element = self._choices[self.index]
                  self._choices = choices
                  try:
                        self.index = choices.index(selected_element)
                  except ValueError:
                        self.index = 0
                  self.update()
            return locals()
      choices = property(**choices())

      def change(self, diff):
            self.index += diff
            if hasattr(self, 'on_change'):
                  self.on_change()
            self.update()

      def update(self):
            self.surfaces_from_text(self.label + ': ' + str(self.choices[self.index]))
            self.down_widget.inactive = self.index == 0
            self.up_widget.inactive = self.index == len(self.choices) -1

      def value():
            def fset(self, value):
                  try:
                        self.index = self.choices.index(value)
                  except NameError:
                        raise NameError, "Could not find value in list of choices!"
            def fget(self):
                  return self.choices[self.index]
            return locals()
      value = property(**value())


class LineEdit(Widget):

      class EditState(WidgetState):
            def __init__(self, widget):
                  WidgetState.__init__(self)
                  self.widget = widget
                  self.show_cursor = True
                  pygame.time.set_timer(USEREVENT+1, 600)
                  Widget.freeze_highlight = self.widget
                  self.widget.update_text(self.show_cursor)

                  # get widgets from previous State
                  from state import State
                  self.widgets = State.stack[-2].widgets

            def __del__(self):
                  pygame.time.set_timer(USEREVENT+1, 0)
                  Widget.freeze_highlight = None

            def blink(self, event):
                  self.show_cursor = not self.show_cursor
                  self.widget.update_text(self.show_cursor)

            def handleKeypress(self, event):
                  if event.key == K_BACKSPACE:
                        self.widget.value = self.widget.value[:-1]
                  elif event.key in (K_RETURN, K_ESCAPE):
                        self.quit()
                  elif event.unicode:
                        self.widget.value += event.unicode
                  self.widget.update_text(self.show_cursor)

            events = {
                  MOUSEBUTTONDOWN: lambda self, event: self.quit(),
                  USEREVENT+1: blink,
                  KEYDOWN: handleKeypress,
            }

      def __init__(self, label, pos, start_value):
            self.value = start_value
            self.label = label
            Widget.__init__(self, pos, text='', on_click=lambda: self.EditState(self))
            self.update_text()

      def update_text(self, show_cursor=False):
            if show_cursor:
                  cursor = '|'
            else:
                  cursor = ''
            self.surfaces_from_text(self.label + ': ' + str(self.value) + cursor)
      
      def get_value(self):
            return self.value

class KeyConfigButton(Widget):

      def get_key(self):
            event = pygame.event.wait()
            while event.type != KEYDOWN:
                  event = pygame.event.wait()
            self.key_list[0] = event.key
            self.update_text()
            
      def update_text(self):
            self.surfaces_from_text(self.label + ': ' + pygame.key.name(self.key_list[0]))

      def __init__(self, label, pos, key_list):
            self.label = label
            self.key_list = key_list
            Widget.__init__(self, pos, text='', on_click=self.get_key)
            self.update_text()


Generated by  Doxygen 1.6.0   Back to index