Added initial drawing code plus a test app.
This commit is contained in:
parent
d08795e5c9
commit
2cdb9fbca6
7 changed files with 293 additions and 0 deletions
0
jgui/__init__.py
Normal file
0
jgui/__init__.py
Normal file
0
jgui/events/__init__.py
Normal file
0
jgui/events/__init__.py
Normal file
37
jgui/events/events.py
Normal file
37
jgui/events/events.py
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
|
||||||
|
class Event(object):
|
||||||
|
def __init__(self, name='event', data=None):
|
||||||
|
self.name = name
|
||||||
|
self.data = data
|
||||||
|
|
||||||
|
class EventSource(object):
|
||||||
|
types = [] # list of event names
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super(EventSource, self).__init__()
|
||||||
|
self.events = {}
|
||||||
|
for type in self.types:
|
||||||
|
self.events[type] = []
|
||||||
|
|
||||||
|
def accept(self, event, callback):
|
||||||
|
if event in self.events:
|
||||||
|
if callback not in self.events[event]:
|
||||||
|
self.events[event].append(callback)
|
||||||
|
|
||||||
|
def dispatch(self, event, *args, **kwargs):
|
||||||
|
for callback in self.events[event]:
|
||||||
|
callback(*args, **kwargs)
|
||||||
|
|
||||||
|
def reject(self, event, callback):
|
||||||
|
if event in self.events:
|
||||||
|
if callback in self.events[event]:
|
||||||
|
self.events[event].remove(callback)
|
||||||
|
|
||||||
|
class WindowEventSource(EventSource):
|
||||||
|
types = ['mouse-enter', 'mouse-leave',
|
||||||
|
'resize', 'move',
|
||||||
|
'key-repeat', 'key-down', 'key-up',
|
||||||
|
'mouse-right-down', 'mouse-right-up',
|
||||||
|
'mouse-left-down', 'mouse-left-up',
|
||||||
|
'mouse-middle-down', 'mouse-middle-up',
|
||||||
|
'scroll-up', 'scroll-down', 'drag']
|
||||||
0
jgui/surface/__init__.py
Normal file
0
jgui/surface/__init__.py
Normal file
126
jgui/surface/structures.py
Normal file
126
jgui/surface/structures.py
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
|
||||||
|
class StructureBase(object):
|
||||||
|
@classmethod
|
||||||
|
def _attrs(cls):
|
||||||
|
a = []
|
||||||
|
i = cls()
|
||||||
|
for attr in dir(i):
|
||||||
|
if not attr.startswith('_') and not callable(getattr(i, attr)):
|
||||||
|
a.append(attr)
|
||||||
|
return a
|
||||||
|
|
||||||
|
def _dict(self):
|
||||||
|
d = {}
|
||||||
|
attrs = self._attrs()
|
||||||
|
for a in attrs:
|
||||||
|
d[a] = getattr(self, a)
|
||||||
|
return d
|
||||||
|
|
||||||
|
def _dict_string(self):
|
||||||
|
return ', '.join('{}={}'.format(key, val) for key, val in self._dict().items())
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return unicode(self)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return unicode(self).encode('utf-8')
|
||||||
|
|
||||||
|
def __unicode__(self):
|
||||||
|
return u'{} [{}]'.format(self.__class__.__name__, self._dict_string())
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def is_like(cls, obj):
|
||||||
|
"""Checks if the object is like the current class
|
||||||
|
If it has everything a duck has, then it's good."""
|
||||||
|
for key in cls._attrs():
|
||||||
|
if not hasattr(obj, key):
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
class Position(StructureBase):
|
||||||
|
def __init__(self, x=0, y=0):
|
||||||
|
self.x = x
|
||||||
|
self.y = y
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
other = Position.from_value(other)
|
||||||
|
return Position(self.x+other.x, self.y+other.y)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
other = Position.from_value(other)
|
||||||
|
return Position(self.x-other.x, self.y-other.y)
|
||||||
|
|
||||||
|
@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):
|
||||||
|
def __init__(self, width=0, height=0):
|
||||||
|
self.height = height
|
||||||
|
self.width = width
|
||||||
|
|
||||||
|
def __add__(self, other):
|
||||||
|
other = Size.from_value(other)
|
||||||
|
return Size(self.width+other.width, self.height+other.height)
|
||||||
|
|
||||||
|
def __sub__(self, other):
|
||||||
|
other = Size.from_value(other)
|
||||||
|
return Size(self.width-other.width, self.height-other.height)
|
||||||
|
|
||||||
|
@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 Rectangle(StructureBase):
|
||||||
|
def __init__(self, position=None, size=None):
|
||||||
|
""" A rectangle object with coordinates and size.
|
||||||
|
position: can take the first two values of an array or a Position object
|
||||||
|
size: can take the first two values of an array or a Size object
|
||||||
|
"""
|
||||||
|
self._position = None
|
||||||
|
self._size = None
|
||||||
|
self.position = position
|
||||||
|
self.size = size
|
||||||
|
|
||||||
|
@property
|
||||||
|
def position(self):
|
||||||
|
return self._position
|
||||||
|
|
||||||
|
@position.setter
|
||||||
|
def position(self, position):
|
||||||
|
self._position = Position.from_value(position)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
return self._size
|
||||||
|
|
||||||
|
@size.setter
|
||||||
|
def size(self, size):
|
||||||
|
self._size = Size.from_value(size)
|
||||||
|
|
||||||
|
def intersects_with(self, position):
|
||||||
|
"""Checks if the position is within the bounds of the rectangle including the edges"""
|
||||||
|
pos = Position.from_value(position)
|
||||||
|
if pos.x < self.position.x + self.size.width and\
|
||||||
|
pos.x >= self.position.x:
|
||||||
|
if pos.y < self.position.y + self.size.height and\
|
||||||
|
pos.y >= self.position.y:
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
91
jgui/surface/surface.py
Normal file
91
jgui/surface/surface.py
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import cairo
|
||||||
|
import math
|
||||||
|
from .structures import Size, Position, Rectangle
|
||||||
|
from ..events.events import WindowEventSource
|
||||||
|
|
||||||
|
class Surface(object):
|
||||||
|
def __init__(self, size=None):
|
||||||
|
self.size = Size.from_value(size)
|
||||||
|
self.csurface = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.size.width, self.size.height)
|
||||||
|
self.root_window = Window('root', Position(0,0), self.size)
|
||||||
|
self.windows = [self.root_window]
|
||||||
|
|
||||||
|
def draw(self):
|
||||||
|
for window in self.windows:
|
||||||
|
window.draw(self.csurface)
|
||||||
|
|
||||||
|
surface = None
|
||||||
|
def init(size):
|
||||||
|
surface = Surface(size)
|
||||||
|
|
||||||
|
class WindowSurface(object):
|
||||||
|
def __init__(self):
|
||||||
|
super(WindowSurface, self).__init__()
|
||||||
|
#self.mouse_pos
|
||||||
|
|
||||||
|
def draw(self, surface):
|
||||||
|
Width = self.size.width
|
||||||
|
Height = self.size.height
|
||||||
|
x,y, radius = (Width/2,Height/2, Width/2-Width/10)
|
||||||
|
ctx = cairo.Context(surface)
|
||||||
|
ctx.set_operator(cairo.OPERATOR_CLEAR)
|
||||||
|
ctx.rectangle(0.0, 0.0, Width, Height)
|
||||||
|
ctx.fill()
|
||||||
|
|
||||||
|
ctx.set_operator(cairo.OPERATOR_OVER)
|
||||||
|
ctx.set_line_width(Width/10)
|
||||||
|
ctx.arc(x, y, radius, 0, 2.0 * math.pi)
|
||||||
|
ctx.set_source_rgba(0.8, 0.8, 0.8)
|
||||||
|
ctx.fill_preserve()
|
||||||
|
ctx.set_source_rgba(1, 1, 1)
|
||||||
|
ctx.stroke()
|
||||||
|
|
||||||
|
|
||||||
|
class Window(WindowEventSource, WindowSurface):
|
||||||
|
def __init__(self, name, position=None, size=None):
|
||||||
|
super(Window, self).__init__()
|
||||||
|
self.name = name
|
||||||
|
self.rectangle = Rectangle(position, size)
|
||||||
|
self.children = []
|
||||||
|
self.parent = None
|
||||||
|
self.mouse_pos = Position()
|
||||||
|
|
||||||
|
|
||||||
|
def add_child(self, child_window):
|
||||||
|
if child_window not in self.children:
|
||||||
|
child_window.parent = self
|
||||||
|
self.children.append(child_window)
|
||||||
|
|
||||||
|
def remove_child(self, child_window):
|
||||||
|
try:
|
||||||
|
self.children.remove(child_window)
|
||||||
|
child_window.parent = None
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@property
|
||||||
|
def position(self):
|
||||||
|
return self.rectangle.position
|
||||||
|
|
||||||
|
@position.setter
|
||||||
|
def position(self, position):
|
||||||
|
diff = position - self.rectangle.position
|
||||||
|
if diff.x != 0 or diff.y != 0:
|
||||||
|
self.dispatch('move', self, position)
|
||||||
|
for child in self.children:
|
||||||
|
child.position = child.position + diff
|
||||||
|
self.recangle.position = position
|
||||||
|
|
||||||
|
@property
|
||||||
|
def size(self):
|
||||||
|
return self.rectangle.size
|
||||||
|
|
||||||
|
@size.setter
|
||||||
|
def size(self, size):
|
||||||
|
diff = size - self.rectangle.size
|
||||||
|
if diff.height != 0 or diff.width != 0:
|
||||||
|
self.dispatch('resize', self, size)
|
||||||
|
for child in self.children:
|
||||||
|
child.size = child.size + diff
|
||||||
|
self.rectangle.size = size
|
||||||
|
|
||||||
39
test.py
Normal file
39
test.py
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
import cairo
|
||||||
|
import pygame
|
||||||
|
import array
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
|
||||||
|
import direct.directbase.DirectStart
|
||||||
|
from pandac.PandaModules import *
|
||||||
|
|
||||||
|
from jgui.surface.surface import *
|
||||||
|
|
||||||
|
props = WindowProperties()
|
||||||
|
props.setSize(1024,1024)
|
||||||
|
base.setBackgroundColor(0.5,1,1,1)
|
||||||
|
base.cam.setPos(0,-10,0)
|
||||||
|
base.win.requestProperties(props)
|
||||||
|
screen = loader.loadModel('/home/joey/Creationista/models/plane.egg.pz')
|
||||||
|
screen.setTransparency(TransparencyAttrib.MAlpha)
|
||||||
|
screen.setTwoSided(True)
|
||||||
|
screen.setScale(2)
|
||||||
|
Width, Height = 1024, 1024
|
||||||
|
|
||||||
|
surf = Surface([Width, Height])
|
||||||
|
|
||||||
|
cairoTexture = Texture()
|
||||||
|
cairoTexture.setFormat(cairoTexture.FRgba8)
|
||||||
|
cairoTexture.setup2dTexture(Width, Height, Texture.CMDefault, Texture.FRgba32)
|
||||||
|
|
||||||
|
screen.setTexture(cairoTexture)
|
||||||
|
screen.reparentTo(render2d)
|
||||||
|
|
||||||
|
def drawall(task):
|
||||||
|
surf.draw()
|
||||||
|
cairoTexture.setRamImage(surf.csurface.get_data())
|
||||||
|
return task.cont
|
||||||
|
|
||||||
|
taskMgr.add(drawall, 'draw')
|
||||||
|
run()
|
||||||
Loading…
Add table
Add a link
Reference in a new issue