Refactored code in the structures file for easier structure adding. Added the beginning of a resizable function.

This commit is contained in:
Joey Payne 2014-01-29 22:41:49 -07:00
commit 067c77ac23
2 changed files with 125 additions and 34 deletions

View file

@ -1,3 +1,4 @@
import colorsys
class StructureBase(object): class StructureBase(object):
@classmethod @classmethod
@ -16,8 +17,12 @@ class StructureBase(object):
d[a] = getattr(self, a) d[a] = getattr(self, a)
return d return d
def _dict_items(self):
for a in reversed(self._attrs()):
yield a, getattr(self,a)
def _dict_string(self): def _dict_string(self):
return ', '.join('{}={}'.format(key, val) for key, val in self._dict().items()) return ', '.join('{}={}'.format(key, val) for key, val in self._dict_items())
def __repr__(self): def __repr__(self):
return unicode(self) return unicode(self)
@ -28,6 +33,25 @@ class StructureBase(object):
def __unicode__(self): def __unicode__(self):
return u'{} [{}]'.format(self.__class__.__name__, self._dict_string()) return u'{} [{}]'.format(self.__class__.__name__, self._dict_string())
def __eq__(self, other):
eq = True
for attr in self._attrs():
val = getattr(self, attr)
if hasattr(other, attr):
eq &= getattr(other, attr) == val
else:
return False
return eq
def __getitem__(self, index):
return list(self)[index]
def __len__(self):
return len(self._attrs())
def __ne__(self, other):
return not(self == other)
@classmethod @classmethod
def is_like(cls, obj): def is_like(cls, obj):
"""Checks if the object is like the current class """Checks if the object is like the current class
@ -37,6 +61,13 @@ class StructureBase(object):
return False return False
return True return True
@classmethod
def from_value(cls, value):
try:
return cls(*value)
except TypeError:
return cls()
class Position(StructureBase): class Position(StructureBase):
def __init__(self, x=0, y=0): def __init__(self, x=0, y=0):
self.x = x self.x = x
@ -50,28 +81,15 @@ class Position(StructureBase):
other = Position.from_value(other) other = Position.from_value(other)
return Position(self.x-other.x, self.y-other.y) return Position(self.x-other.x, self.y-other.y)
def __eq__(self, other): def __iter__(self):
return self.x == other.x and self.y == other.y yield self.x
yield self.y
def __ne__(self, other):
return not(self == other)
@classmethod
def from_value(cls, value):
if not value:
return cls()
if cls.is_like(value):
return value
elif len(value) >= 2:
return cls(value[0], value[1])
else:
return cls()
class Size(StructureBase): class Size(StructureBase):
def __init__(self, width=0, height=0): def __init__(self, width=0, height=0):
self.height = height
self.width = width self.width = width
self.height = height
def __add__(self, other): def __add__(self, other):
other = Size.from_value(other) other = Size.from_value(other)
@ -81,23 +99,83 @@ class Size(StructureBase):
other = Size.from_value(other) other = Size.from_value(other)
return Size(self.width-other.width, self.height-other.height) return Size(self.width-other.width, self.height-other.height)
def __eq__(self, other): def __iter__(self):
return self.width == other.width and self.height == other.height yield self.width
yield self.height
def __ne__(self, other):
return not(self == other) class Color(StructureBase):
def __init__(self, r=0, g=0, b=0, a=1):
self.r = float(r)
self.g = float(g)
self.b = float(b)
self.a = float(a)
def __add__(self, other):
"""Blend two colors using self as the background and other as the foreground"""
other = Color.from_value(other)
r = Color()
r.a = 1 - (1-other.a)*(1-self.a)
r_a_inv = self.a*(1-other.a)/r.a
o_factor = other.a/r.a
r.r = other.r*o_factor + self.r*r_a_inv
r.g = other.g*o_factor + self.g*r_a_inv
r.b = other.b*o_factor + self.b*r_a_inv
return r
def brightness(self, value):
h, s, v = colorsys.rgb_to_hsv(self.r, self.g, self.b)
v = value
self.r, self.g, self.b = colorsys.hsv_to_rgb(h, s, v)
def hue(self, value):
h, s, v = colorsys.rgb_to_hsv(self.r, self.g, self.b)
h = value
self.r, self.g, self.b = colorsys.hsv_to_rgb(h, s, v)
def saturation(self, value):
h, s, v = colorsys.rgb_to_hsv(self.r, self.g, self.b)
s = value
self.r, self.g, self.b = colorsys.hsv_to_rgb(h, s, v)
def from_hsv(self, h, s, v):
self.r, self.g, self.b = colorsys.hsv_to_rgb(h, s, v)
return self
def __iter__(self):
yield self.r
yield self.g
yield self.b
yield self.a
@classmethod
def hex_to_rgba(cls, hex_val):
"""Converts a hex string in the format 0xFFAABB/CC or an integer to rgba"""
if isinstance(hex_val, (long, int)):
hexstring = "{0:x}".format(abs(hex_val))
elif isinstance(hex_val, basestring):
hexstring = hexval[2:]
else:
return None
if len(hexstring) % 2 != 0:
hexstring = '0' + hexstring
if len(hexstring) != 6 and len(hexstring) != 8:
return None
ba = []
for i in xrange(0, len(hexstring), 2):
ba.append(int(hexstring[i:i+2], 16))
c = cls(*ba)
return c
@classmethod @classmethod
def from_value(cls, value): def from_value(cls, value):
if not value: try:
return cls(*value)
except TypeError:
c = cls.hex_to_rgba(value)
if c is not None:
return c
return cls() return cls()
if cls.is_like(value):
return value
elif len(value) >= 2:
return cls(value[0], value[1])
else:
return cls()
class Rectangle(StructureBase): class Rectangle(StructureBase):
def __init__(self, position=None, size=None): def __init__(self, position=None, size=None):
@ -118,6 +196,10 @@ class Rectangle(StructureBase):
def position(self, position): def position(self, position):
self._position = Position.from_value(position) self._position = Position.from_value(position)
def __iter__(self):
yield list(self.position)
yield list(self.size)
@property @property
def size(self): def size(self):
return self._size return self._size

View file

@ -1,6 +1,6 @@
import cairo import cairo
import math import math
from .structures import Size, Position, Rectangle from .structures import Size, Position, Rectangle, Color
from ..events.events import WindowEventSource from ..events.events import WindowEventSource
class Surface(object): class Surface(object):
@ -44,6 +44,8 @@ class WindowSurface(object):
def draw_circle(self, position, size, color=(1,1,1), outline_width=1.0, outline_color=(0,0,0), start_angle=0.0, end_angle=360.0): def draw_circle(self, position, size, color=(1,1,1), outline_width=1.0, outline_color=(0,0,0), start_angle=0.0, end_angle=360.0):
color = Color.from_value(color)
outline_color = Color.from_value(outline_color)
context = self.context context = self.context
position = Position.from_value(position) position = Position.from_value(position)
size = Size.from_value(size) size = Size.from_value(size)
@ -69,6 +71,8 @@ class WindowSurface(object):
def draw_rounded_rect(self, position, size, color=(1,1,1), outline_width=1, outline_color=(0,0,0), corner_radius=10): def draw_rounded_rect(self, position, size, color=(1,1,1), outline_width=1, outline_color=(0,0,0), corner_radius=10):
position = Position.from_value(position) position = Position.from_value(position)
size = Size.from_value(size) size = Size.from_value(size)
color = Color.from_value(color)
outline_color = Color.from_value(outline_color)
context = self.context context = self.context
radius = corner_radius radius = corner_radius
@ -85,7 +89,7 @@ class WindowSurface(object):
context.arc(x + radius + outline_width/2.0, y + radius + outline_width/2.0, radius, 180 * degrees, 270 * degrees) context.arc(x + radius + outline_width/2.0, y + radius + outline_width/2.0, radius, 180 * degrees, 270 * degrees)
context.close_path() context.close_path()
context.set_source_rgb(*color) context.set_source_rgba(*color)
context.fill_preserve() context.fill_preserve()
context.set_source_rgba(*outline_color) context.set_source_rgba(*outline_color)
context.set_line_width(outline_width) context.set_line_width(outline_width)
@ -105,7 +109,7 @@ class WindowSurface(object):
class Window(WindowEventSource, WindowSurface): class Window(WindowEventSource, WindowSurface):
def __init__(self, name, position=None, size=None, context=None, draggable=False): def __init__(self, name, position=None, size=None, context=None, draggable=False, resizable=False):
super(Window, self).__init__() super(Window, self).__init__()
self.context = context self.context = context
self.name = name self.name = name
@ -122,6 +126,10 @@ class Window(WindowEventSource, WindowSurface):
self.focused = False self.focused = False
self.visible = True self.visible = True
self.draggable = draggable self.draggable = draggable
self.resizable = resizable
if resizable:
pass
if self.draggable: if self.draggable:
self.accept('mouse-left-drag', self.drag) self.accept('mouse-left-drag', self.drag)
@ -132,7 +140,7 @@ class Window(WindowEventSource, WindowSurface):
obj.position = mouse_pos - self.mouse_diff obj.position = mouse_pos - self.mouse_diff
def click(self, obj, mouse_pos): def click(self, obj, mouse_pos):
self.mouse_diff = mouse_pos - self.position self.mouse_diff = mouse_pos - obj.position
def click_up(self, obj, mouse_pos): def click_up(self, obj, mouse_pos):
self.mouse_diff = Position(0, 0) self.mouse_diff = Position(0, 0)
@ -211,6 +219,7 @@ class Window(WindowEventSource, WindowSurface):
if not self.mouse_in: if not self.mouse_in:
print 'mouse-enter', self.name print 'mouse-enter', self.name
self.dispatch('mouse-enter', self) self.dispatch('mouse-enter', self)
self.dispatch('hover', self)
self.mouse_in = True self.mouse_in = True
else: else:
if self.mouse_in: if self.mouse_in: