Added a copy of SGC
This commit is contained in:
parent
90ff7ceba8
commit
52eb18994d
22 changed files with 3283 additions and 0 deletions
299
sgc/widgets/base_widget.py
Normal file
299
sgc/widgets/base_widget.py
Normal file
|
@ -0,0 +1,299 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
# Copyright (C) 2010-2012 Sam Bull
|
||||
|
||||
"""
|
||||
Base widget, all widgets inherit from this.
|
||||
|
||||
"""
|
||||
|
||||
import pygame
|
||||
from pygame.locals import Rect
|
||||
|
||||
from _locals import *
|
||||
from _locals import (has_focus, is_active, add_widget, remove_widget_order,
|
||||
set_cursor, remove_cursor)
|
||||
try:
|
||||
import opengl
|
||||
except ImportError:
|
||||
print "OpenGL widgets disabled."
|
||||
|
||||
class Simple(pygame.sprite.Sprite):
|
||||
|
||||
"""
|
||||
Widget foundations all widgets should inherit from.
|
||||
This can also be used as a simple widget that does nothing, such as
|
||||
displaying an image.
|
||||
|
||||
Attributes:
|
||||
image: The current surface that will be drawn to the screen.
|
||||
rect: The ``pygame.Rect`` used for the widget's position and size.
|
||||
rect_abs: A ``pygame.Rect`` using the absolute screen position.
|
||||
pos: The widget's position. Can be retrieved or assigned as a shortcut
|
||||
for rect.topleft. Also a shortcut for setting pos through config().
|
||||
pos_abs: The widget's absolute screen position.
|
||||
|
||||
"""
|
||||
|
||||
# Widget settings
|
||||
_can_focus = False
|
||||
_modal = False
|
||||
_layered = False # Layered updates for dialog windows etc.
|
||||
_default_size = None
|
||||
_parent = None
|
||||
_available_images = ()
|
||||
_extra_images = {}
|
||||
_settings_default = {}
|
||||
|
||||
_fade = None # Alpha level when fading
|
||||
_fade_up = True
|
||||
_custom_image = False
|
||||
|
||||
def __init__(self, surf=None, **kwargs):
|
||||
"""
|
||||
Args:
|
||||
surf: The surface that should be drawn to screen, of type:
|
||||
pygame.Surface: Use an existing surface.
|
||||
tuple,list: Contains size as (width,height), creates a new surface.
|
||||
str: Contains file name to load an image.
|
||||
dict: Contains multiple images to be loaded. The documentation will
|
||||
specify if a widget uses multiple images and what names to use.
|
||||
kwargs: Any number of keyword arguments matching those for config().
|
||||
|
||||
"""
|
||||
pygame.sprite.Sprite.__init__(self)
|
||||
|
||||
# Implicitly pass attributes into _draw()
|
||||
# Used to reduce complexity for widget developers
|
||||
draw = self._draw
|
||||
self._draw = lambda d=self.get_draw(): draw(d)
|
||||
|
||||
# Initialise attributes
|
||||
self._images = {}
|
||||
self._available_images = ("image",) + self._available_images
|
||||
self._settings = self._settings_default.copy()
|
||||
self.rect = Rect((0,0), (0,0))
|
||||
|
||||
# Use default size if none specified
|
||||
if surf is None:
|
||||
surf = self._default_size
|
||||
|
||||
# Create base surfaces if not None.
|
||||
# If None, widget is expected to call this function later.
|
||||
if surf is not None:
|
||||
self._create_base_images(surf)
|
||||
|
||||
self.config(init=None, **kwargs)
|
||||
|
||||
|
||||
def config(self, **kwargs):
|
||||
"""
|
||||
Update widget configuration and redraw the widget.
|
||||
|
||||
Keyword Args:
|
||||
pos: ``tuple`` (x,y) Position to set widget to.
|
||||
|
||||
"""
|
||||
if "pos" in kwargs:
|
||||
self.rect.topleft = kwargs["pos"]
|
||||
self._config(**kwargs)
|
||||
self._draw()
|
||||
|
||||
def _config(self, **kwargs):
|
||||
"""Widgets should overload for custom widget configuration."""
|
||||
pass
|
||||
|
||||
def add(self, order=None, fade=True):
|
||||
"""
|
||||
Add widget to screen.
|
||||
|
||||
Args:
|
||||
order: Integer representing the order widget should receive focus
|
||||
when user presses TAB. The widget with the lowest order will
|
||||
receive focus first, then moving up with increasing values.
|
||||
fade: True if widget should fade in, False if not.
|
||||
|
||||
"""
|
||||
added = add_widget(self, order)
|
||||
|
||||
# Fade widget in
|
||||
if fade:
|
||||
self._fade_up = True
|
||||
if added and self._fade is None: self._fade = 1
|
||||
self.image.set_alpha(self._fade)
|
||||
else:
|
||||
self._fade = None
|
||||
self.image.set_alpha(255)
|
||||
|
||||
def remove(self, fade=True):
|
||||
"""
|
||||
Remove widget from screen.
|
||||
|
||||
Args:
|
||||
fade: True if widget should fade out.
|
||||
|
||||
"""
|
||||
if fade: # Fade widget out
|
||||
self._fade_up = False
|
||||
if self._fade == None: self._fade = 250
|
||||
else: # Remove widget immediately
|
||||
self.kill()
|
||||
remove_widget_order(self)
|
||||
|
||||
def active(self):
|
||||
"""Return True if widget is active (onscreen)."""
|
||||
return is_active(self)
|
||||
|
||||
def has_focus(self):
|
||||
"""Return True if this widget has focus."""
|
||||
return has_focus(self)
|
||||
|
||||
def get_draw(self):
|
||||
"""
|
||||
Return appropriate draw module for pygame or OpenGL.
|
||||
|
||||
Use like:
|
||||
``draw = self.get_draw()``
|
||||
``draw.rect(self.image, ...)``
|
||||
|
||||
"""
|
||||
if not get_screen()._opengl:
|
||||
return pygame.draw
|
||||
else:
|
||||
return opengl.draw
|
||||
|
||||
def update(self, time):
|
||||
"""Placeholder for function that updates the widget per frame."""
|
||||
pass
|
||||
|
||||
def _event(self, event):
|
||||
"""Placeholder for function that receives event for the widget."""
|
||||
pass
|
||||
|
||||
def _draw(self, draw):
|
||||
"""Widgets should overload to draw default images."""
|
||||
pass
|
||||
|
||||
def _create_base_images(self, surf, parent=None):
|
||||
"""
|
||||
Creates the base surfaces to draw on, or uses existing images.
|
||||
|
||||
If self._default_size is None, widget is expected to call this
|
||||
function manually when no size is given.
|
||||
|
||||
"""
|
||||
Image = opengl.OpenGLImage if get_screen()._opengl else pygame.Surface
|
||||
def create_image(surf):
|
||||
"""Return a created surface."""
|
||||
if isinstance(surf, pygame.Surface):
|
||||
surf.set_colorkey(0)
|
||||
self._custom_image = True
|
||||
return surf
|
||||
elif isinstance(surf, (tuple,list)):
|
||||
self._custom_image = False
|
||||
if isinstance(surf[0], (tuple,list)):
|
||||
surf = (self.rect.w * surf[0][0] + surf[0][1],
|
||||
self.rect.h * surf[1][0] + surf[1][1])
|
||||
surf = Image(surf)
|
||||
surf.set_colorkey(0)
|
||||
return surf
|
||||
elif isinstance(surf, str):
|
||||
self._custom_image = True
|
||||
return pygame.image.load(surf).convert_alpha()
|
||||
|
||||
# Create base images
|
||||
if isinstance(surf, dict):
|
||||
for img in surf:
|
||||
assert (img in self._available_images or
|
||||
img in self._extra_images), "Incorrect image."
|
||||
self._images[img] = create_image(surf[img])
|
||||
else:
|
||||
self._images["image"] = create_image(surf)
|
||||
|
||||
# Copy other images, if any have not been supplied.
|
||||
assert "image" in self._images, "Must supply 'image'"
|
||||
for count, name in enumerate(self._available_images):
|
||||
if name not in self._images:
|
||||
img = self._images[self._available_images[count-1]]
|
||||
self._images[name] = img.copy()
|
||||
|
||||
self.image = self._images["image"].copy()
|
||||
self.rect.size = self.image.get_size()
|
||||
|
||||
# Set up extra images
|
||||
for name in self._extra_images:
|
||||
if name not in self._images:
|
||||
self._images[name] = create_image(self._extra_images[name])
|
||||
|
||||
def _change_focus(self, forward=True):
|
||||
"""
|
||||
Called when focus should be changed. Container widget
|
||||
should override this function.
|
||||
|
||||
Args:
|
||||
forward: True if toggling focus forwards, False if backwards.
|
||||
|
||||
Returns:
|
||||
True if widget should change focus from this widget.
|
||||
|
||||
"""
|
||||
return True
|
||||
|
||||
def _focus_enter(self, focus=0):
|
||||
"""
|
||||
Called when the widget gains focus.
|
||||
|
||||
Args:
|
||||
focus: 1 if focused by keyboard, 2 if by mouse.
|
||||
|
||||
"""
|
||||
pass
|
||||
|
||||
def _focus_exit(self):
|
||||
"""Called when the widget loses focus."""
|
||||
pass
|
||||
|
||||
def _dotted_rect(self, col=(255,255,255)):
|
||||
"""Draw a dotted rectangle to show keyboard focus."""
|
||||
self.image.lock()
|
||||
for i in range(0, self.rect.w, 3):
|
||||
# Draw horizontal lines
|
||||
self.image.set_at((i, 0), col)
|
||||
self.image.set_at((i, self.rect.h-1), col)
|
||||
for i in range(0, self.rect.h, 2):
|
||||
# Draw vertical lines
|
||||
self.image.set_at((0, i), col)
|
||||
self.image.set_at((self.rect.w-1, i), col)
|
||||
self.image.unlock()
|
||||
|
||||
def _set_cursor(self, size, hotspot, xormasks, andmasks):
|
||||
set_cursor(self, size, hotspot, xormasks, andmasks)
|
||||
|
||||
def _remove_cursor(self):
|
||||
remove_cursor(self)
|
||||
|
||||
|
||||
# --PROPERTIES--
|
||||
|
||||
@property
|
||||
def rect_abs(self):
|
||||
if self._parent is None:
|
||||
return self.rect
|
||||
else:
|
||||
p_abs = self._parent.pos_abs
|
||||
p = (self.rect.x + p_abs[0], self.rect.y + p_abs[1])
|
||||
return Rect(p, self.rect.size)
|
||||
|
||||
@property
|
||||
def pos(self):
|
||||
return self.rect.topleft
|
||||
@pos.setter
|
||||
def pos(self, value):
|
||||
self.rect.topleft = value
|
||||
@property
|
||||
def pos_abs(self):
|
||||
if self._parent is None:
|
||||
return self.rect.topleft
|
||||
else:
|
||||
p_abs = self._parent.pos_abs
|
||||
return (self.rect.x + p_abs[0], self.rect.y + p_abs[1])
|
Loading…
Add table
Add a link
Reference in a new issue