ios-support: merge osx-support

This commit is contained in:
Christopher Denter 2011-05-27 00:12:06 +02:00
commit 7624819fa5
25 changed files with 431 additions and 203 deletions

View File

@ -162,4 +162,5 @@ Tablets
- Samsung Galaxy Tab
- Motorola Xoom
- Asus EeePad Transformer

View File

@ -0,0 +1,87 @@
.. _environment:
Controling the environment
==========================
Many environment variables are available to control the initialization and
behavior of Kivy.
For example, for restricting text rendering to cairo implementation::
$ KIVY_TEXT=cairo python main.py
Environment variable can be set before importing kivy::
import os
os.environ['KIVY_TEXT'] = 'cairo'
import kivy
Configuration
-------------
KIVY_USE_DEFAULTCONFIG
If this name is found in environ, Kivy will not read the user config file.
Path control
------------
.. versionadded:: 1.0.7
You can control where is located default directory of modules, extensions, and
kivy datas.
KIVY_DATA_DIR
Location of the Kivy data, default to `<kivy path>/data`
KIVY_EXTS_DIR
Location of the Kivy extensions, default to `<kivy path>/extensions`
KIVY_MODULES_DIR
Location of the Kivy modules, default to `<kivy path>/modules`
Restrict core to specific implementation
----------------------------------------
:mod:`kivy.core` try to select the best implementation available for your
platform. For testing or custom installation, you might want to restrict the
selector to a specific implementation.
KIVY_WINDOW
Implementation to use for creating the Window
Values: pygame
KIVY_TEXT
Implementation to use for rendering text
Values: pil, cairo, pygame
KIVY_VIDEO
Implementation to use for rendering video
Values: gstreamer, pyglet
KIVY_AUDIO
Implementation to use for playing audio
Values: gstreamer, pygame
KIVY_IMAGE
Implementation to use for reading image
Values: pil, pygame
KIVY_CAMERA
Implementation to use for reading camera
Values: gstreamer, opencv, videocapture
KIVY_SPELLING
Implementation to use for spelling
Values: enchant, osxappkit
KIVY_CLIPBOARD
Implementation to use for clipboard management
Values: pygame, dummy

View File

@ -23,9 +23,9 @@ See http://kivy.org for more information.
__all__ = (
'require',
'kivy_configure', 'kivy_register_post_configuration',
'kivy_options', 'kivy_base_dir', 'kivy_libs_dir',
'kivy_options', 'kivy_base_dir',
'kivy_modules_dir', 'kivy_data_dir', 'kivy_shader_dir',
'kivy_providers_dir', 'kivy_icons_dir', 'kivy_home_dir',
'kivy_icons_dir', 'kivy_home_dir',
'kivy_config_fn', 'kivy_usermodules_dir',
)
@ -194,7 +194,6 @@ kivy_options = {
'audio': ('pygame', 'gstreamer', ),
'image': ('osxcoreimage', 'pil', 'pygame'),
'camera': ('opencv', 'gstreamer', 'videocapture'),
'svg': ('squirtle', ),
'spelling': ('enchant', 'osxappkit', ),
'clipboard': ('pygame', 'dummy'), }
@ -215,18 +214,17 @@ for option in kivy_options:
# Extract all needed path in kivy
#: Kivy directory
kivy_base_dir = dirname(sys.modules[__name__].__file__)
#: Kivy external libraries directory
kivy_libs_dir = join(kivy_base_dir, 'lib')
#: Kivy modules directory
kivy_modules_dir = join(kivy_base_dir, 'modules')
kivy_modules_dir = environ.get('KIVY_MODULES_DIR',
join(kivy_base_dir, 'modules'))
#: Kivy extension directory
kivy_exts_dir = join(kivy_base_dir, 'extensions')
kivy_exts_dir = environ.get('KIVY_EXTS_DIR',
join(kivy_base_dir, 'extensions'))
#: Kivy data directory
kivy_data_dir = join(kivy_base_dir, 'data')
kivy_data_dir = environ.get('KIVY_DATA_DIR',
join(kivy_base_dir, 'data'))
#: Kivy glsl shader directory
kivy_shader_dir = join(kivy_data_dir, 'glsl')
#: Kivy input provider directory
kivy_providers_dir = join(kivy_base_dir, 'input', 'providers')
#: Kivy icons config path (don't remove the last '')
kivy_icons_dir = join(kivy_data_dir, 'icons', '')
#: Kivy user-home storage directory
@ -236,9 +234,6 @@ kivy_config_fn = None
#: Kivy user modules directory
kivy_usermodules_dir = None
# Add libs to pythonpath
sys.path = [kivy_libs_dir] + sys.path
# Don't go further if we generate documentation
if basename(sys.argv[0]) in ('sphinx-build', 'autobuild.py'):
environ['KIVY_DOC'] = '1'
@ -285,7 +280,7 @@ if not 'KIVY_DOC_INCLUDE' in environ:
sys.argv = sys.argv[:1]
try:
opts, args = getopt(sys_argv[1:], 'hp:fkawFem:snr:dc:',
opts, args = getopt(sys_argv[1:], 'hp:fkawFem:sr:dc:',
['help', 'fullscreen', 'windowed', 'fps', 'event',
'module=', 'save', 'fake-fullscreen', 'auto-fullscreen',
'display=', 'size=', 'rotate=', 'config=', 'debug'])
@ -348,8 +343,6 @@ if not 'KIVY_DOC_INCLUDE' in environ:
need_save = True
elif opt in ('-r', '--rotation'):
Config.set('graphics', 'rotation', arg)
elif opt in ('-n', ):
kivy_options['shadow_window'] = False
elif opt in ('-d', '--debug'):
level = LOG_LEVELS.get('debug')
Logger.setLevel(level=level)

View File

@ -339,7 +339,7 @@ class ClockBase(object):
# call that function to release all the direct reference to any callback
# and replace it with a weakref
events = self._events
for cid in events:
for cid in events.keys()[:]:
[x.release() for x in events[cid] if x.callback is not None]
def _remove_empty(self):

View File

@ -20,6 +20,7 @@ class ImageLoaderOSXCoreImage(ImageLoaderBase):
def extensions():
'''Return accepted extension for this loader'''
# See http://www.pythonware.com/library/pil/handbook/index.htm
# XXX
return ('bmp', 'bufr', 'cur', 'dcx', 'fits', 'fl', 'fpx', 'gbr',
'gd', 'gif', 'grib', 'hdf5', 'ico', 'im', 'imt', 'iptc',
'jpeg', 'jpg', 'mcidas', 'mic', 'mpeg', 'msp', 'pcd',
@ -27,7 +28,7 @@ class ImageLoaderOSXCoreImage(ImageLoaderBase):
'tga', 'tiff', 'wal', 'wmf', 'xbm', 'xpm', 'xv')
def load(self, filename):
ret = osxcoreimage.load_raw_image_data(filename)
ret = osxcoreimage.load_image_data(filename)
if ret is None:
Logger.warning('Image: Unable to load image <%s>' % filename)
raise Exception('Unable to load image')

View File

@ -7,7 +7,10 @@ __all__ = ('ImageLoaderPIL', )
try:
from PIL import Image
except:
raise
try:
import Image
except:
raise
from kivy.logger import Logger
from . import ImageLoaderBase, ImageData, ImageLoader

View File

@ -1,25 +1,94 @@
from array import array
from libcpp cimport bool
ctypedef unsigned long size_t
ctypedef signed long CFIndex
cdef extern from "stdlib.h":
void* calloc(size_t, size_t)
cdef extern from "Python.h":
object PyString_FromStringAndSize(char *s, Py_ssize_t len)
#cdef extern from "CoreGraphics/CGDataProvider.h":
cdef extern from "ApplicationServices/ApplicationServices.h":
ctypedef void *CFDataRef
# XXX
# char or int?
unsigned char * CFDataGetBytePtr(CFDataRef)
ctypedef void *CGDataProviderRef
CFDataRef CGDataProviderCopyData(CGDataProviderRef)
ctypedef void *CGDataProviderRef
CFDataRef CGDataProviderCopyData(CGDataProviderRef)
ctypedef void *CGImageRef
CGDataProviderRef CGImageGetDataProvider(CGImageRef)
# guessing these, because of no wifi:
size_t CGImageGetWidth(CGImageRef)
size_t CGImageGetHeight(CGImageRef)
size_t CGImageGetBitsPerPixel(CGImageRef)
int CGImageGetAlphaInfo(CGImageRef)
int kCGImageAlphaNone
int kCGImageAlphaNoneSkipLast
int kCGImageAlphaNoneSkipFirst
int kCGImageAlphaFirst
int kCGImageAlphaLast
int kCGImageAlphaPremultipliedLast
int kCGImageAlphaPremultipliedFirst
int kCGBitmapByteOrder32Host
ctypedef void *CGColorSpaceRef
CGColorSpaceRef CGImageGetColorSpace(CGImageRef image)
CGColorSpaceRef CGColorSpaceCreateDeviceRGB()
ctypedef void *CGContextRef
void CGContextTranslateCTM(CGContextRef, float, float)
void CGContextScaleCTM (CGContextRef, float, float)
ctypedef struct CGPoint:
float x
float y
ctypedef struct CGSize:
float width
float height
ctypedef struct CGRect:
CGPoint origin
CGSize size
CGRect CGRectMake(float, float, float, float)
CGContextRef CGBitmapContextCreate(
void *data,
size_t width,
size_t height,
size_t bitsPerComponent,
size_t bytesPerRow,
CGColorSpaceRef colorspace,
unsigned int bitmapInfo
)
#void CGContextSetBlendMode (CGContextRef, int)
void CGContextDrawImage(CGContextRef, CGRect, CGImageRef)
int kCGBlendModeCopy
void CGContextSetBlendMode(CGContextRef, int)
cdef extern from "CoreFoundation/CFBase.h":
ctypedef void *CFAllocatorRef
cdef extern from "CoreFoundation/CFData.h":
ctypedef void *CFDataRef
# XXX
# char or int?
unsigned char * CFDataGetBytePtr(CFDataRef)
#cdef extern from "CoreFoundation/CFData.h":
cdef extern from "CoreGraphics/CGDataProvider.h":
ctypedef void *CGDataProviderRef
CFDataRef CGDataProviderCopyData(CGDataProviderRef)
#cdef extern from "CoreGraphics/CGDataProvider.h":
#cdef extern from "QuartzCore/QuartzCore.h":
cdef extern from "CoreFoundation/CFURL.h":
@ -53,7 +122,8 @@ cdef extern from "CoreGraphics/CGImage.h":
int kCGImageAlphaNone
cdef extern from "ImageIO/CGImageSource.h":
#cdef extern from "ImageIO/CGImageSource.h":
cdef extern from "QuartzCore/QuartzCore.h":
ctypedef void *CGImageSourceRef
CGImageSourceRef CGImageSourceCreateWithURL(CFURLRef,
CFDictionaryRef)
@ -61,57 +131,48 @@ cdef extern from "ImageIO/CGImageSource.h":
size_t, CFDictionaryRef)
def load_raw_image_data(bytes _url):
def load_image_data(bytes _url):
cdef CFURLRef url
url = CFURLCreateFromFileSystemRepresentation(NULL, <bytes> _url, len(_url), 0)
cdef CGImageSourceRef myImageSourceRef
# or maybe: UIImage* uiImage = [UIImage imageWithContentsOfFile:fullPath];
# see iphone3d book
myImageSourceRef = CGImageSourceCreateWithURL(url, NULL)
if myImageSourceRef == NULL:
print 'myImageSourceRef is NULL'
return None
cdef CGImageSourceRef myImageSourceRef = CGImageSourceCreateWithURL(url, NULL)
cdef CGImageRef myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL)
cdef CGImageRef myImageRef
myImageRef = CGImageSourceCreateImageAtIndex (myImageSourceRef, 0, NULL)
if myImageRef == NULL:
print 'myImageRef is NULL'
return None
cdef size_t width = CGImageGetWidth(myImageRef)
cdef size_t height = CGImageGetHeight(myImageRef)
cdef CGRect rect = CGRectMake(0, 0, width, height)
cdef void * myData = calloc(width * 4, height)
cdef CGColorSpaceRef space = CGColorSpaceCreateDeviceRGB()
cdef CGContextRef myBitmapContext = CGBitmapContextCreate(myData,
width, height, 8,
width*4, space,
# endianness: kCGBitmapByteOrder32Little = (2 << 12)
#(2 << 12) | kCGImageAlphaPremultipliedLast)
kCGBitmapByteOrder32Host
|
# XXX first or last? in
# the docs they use
# first
kCGImageAlphaNoneSkipFirst)
cdef int width = CGImageGetWidth(myImageRef)
cdef int height = CGImageGetHeight(myImageRef)
cdef int hasAlpha = CGImageGetAlphaInfo(myImageRef) != kCGImageAlphaNone
# This is necessary as the image would be vertically flipped otherwise
CGContextTranslateCTM(myBitmapContext, 0, height)
CGContextScaleCTM(myBitmapContext, 1, -1)
# correctly detect the image type !!!
imgtype = 'rgb'
typesize = 3
if hasAlpha > 0:
imgtype = 'rgba'
typesize = 4
CGContextSetBlendMode(myBitmapContext, kCGBlendModeCopy)
CGContextDrawImage(myBitmapContext, rect, myImageRef)
#CGContextRelease(myBitmapContext)
cdef CFDataRef data
data = CGDataProviderCopyData(CGImageGetDataProvider(myImageRef))
r_data = PyString_FromStringAndSize(<char *> myData, width * height * 4)
r_data = PyString_FromStringAndSize(<char *>CFDataGetBytePtr(data),
width * height * typesize)
# XXX
# kivy doesn't like to process 'bgra' data. we swap manually to 'rgba'.
# would be better to fix this in texture.pyx
a = array('b', r_data)
a[0::4], a[2::4] = a[2::4], a[0::4]
r_data = a.tostring()
imgtype = 'rgba'
# XXX clean image object
print 'Image:', _url, width, height, imgtype
return (width, height, imgtype, r_data)
#
# bool hasAlpha = CGImageGetAlphaInfo(cgImage) != kCGImageAlphaNone; CGColorSpaceRef colorSpace = CGImageGetColorSpace(cgImage); switch (CGColorSpaceGetModel(colorSpace)) {
# case kCGColorSpaceModelMonochrome: description.Format =
# hasAlpha ? TextureFormatGrayAlpha : TextureFormatGray; break;
# case kCGColorSpaceModelRGB: description.Format =
# Texture Formats and Types
# | 189
# }
# hasAlpha ? TextureFormatRgba : TextureFormatRgb; break;
# default: assert(!"Unsupported color space."); break;
# } description.BitsPerComponent = CGImageGetBitsPerComponent(cgImage);
# return description;
#
#

View File

@ -138,6 +138,7 @@ class WindowSDL(WindowBase):
if event is None:
continue
print 'sdl received', event
action, args = event[0], event[1:]
if action == 'quit':
EventLoop.quit = True

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 B

View File

@ -47,7 +47,7 @@ cdef class EventDispatcher(object):
def on_swipe_callback(*largs):
print 'my swipe is called', largs
w = MyWidget()
w.dispatch_event('on_swipe')
w.dispatch('on_swipe')
'''
if not event_type.startswith('on_'):

View File

@ -52,7 +52,7 @@ import sys
import imp
from glob import glob
from os import listdir, mkdir, sep, environ
from os.path import join, isdir, exists
from os.path import join, isdir, exists, dirname
from zipfile import ZipFile
from shutil import move
@ -67,8 +67,8 @@ if not 'KIVY_DOC' in environ:
NEED_UNZIP = True
# XXX platform check?
def load(extname, version):
# XXX platform check?
'''Use this function to tell Kivy to load a specific version of the given
Extension. This is different from kivy's require() in that it will always
use the exact same major version you specify, even if a newer (major)
@ -203,7 +203,10 @@ def unzip_extensions():
for epath in EXTENSION_PATHS:
if not isdir(epath):
mkdir(epath)
try:
mkdir(epath)
except OSError:
continue
files = []
else:
files = listdir(epath)
@ -235,48 +238,32 @@ def unzip_extensions():
"extracted manually, just moving the zip.")
already_unzipped = True
members = zipf.namelist()
def get_root_member(zipf):
root = None
multiple = False
for m1 in members:
for m2 in members:
if not m2.startswith(m1):
break
else:
if root != None:
multiple = True
root = m1
if not root or multiple:
# There either is no root or there is more than one root.
# We require only one root, so the extension is malformed.
Logger.warn("Malformed extension '%s'! Skipping it." % extname)
return
# return root name without the trailing slash
return root[:-1]
root = get_root_member(zipf)
if not root:
# Skip this extension as we told the user
continue
# Filter the namelist of zipfile to take only the members that start
# with the extension name (MyExt/...)
members = [x for x in zipf.namelist() \
if x.startswith(extname + '/')]
if not already_unzipped:
# Unzip the extension
try:
cache_directories = []
mkdir(join(epath, extdir))
# I know that there is zipf.extract() and zipf.extractall(), but on
# OSX, Python 2.6 is the default and in that version, both methods
# have a bug. Fixed in 2.7 only. So use this workaround until apple
# upgrades its python. See http://bugs.python.org/issue4710
# I know that there is zipf.extract() and zipf.extractall(),
# but on OSX, Python 2.6 is the default and in that version,
# both methods have a bug. Fixed in 2.7 only. So use this
# workaround until apple upgrades its python. See
# http://bugs.python.org/issue4710
for member in members:
# In zipfiles, folders always end with '/' regardless of the OS
# In zipfiles, folders always end with '/' regardless
# of the OS
mempath = join(epath, extdir, member)
if member.endswith('/') and not exists(mempath):
mkdir(join(epath, extdir, member[:-1]))
else:
with open(join(epath, extdir, member), 'wb') as memberfd:
memberfd.write(zipf.read(member))
directory = dirname(mempath)
if not directory in cache_directories:
cache_directories.append(directory)
if not exists(directory):
mkdir(join(epath, extdir, directory))
with open(join(epath, extdir, member), 'wb') as fd:
fd.write(zipf.read(member))
except Exception, e:
# Catch any error, e.g. non-writable directory, etc.
Logger.error("Failed installing extension " + \

View File

@ -172,51 +172,71 @@ cdef class Color(ContextInstruction):
self.set_state('color', [1.0, 1.0, 1.0, 1.0])
property rgba:
'''RGBA color, list of 4 values in 0-1 range
'''
def __get__(self):
return self.context_state['color']
def __set__(self, rgba):
self.set_state('color', map(float,rgba))
property rgb:
'''RGB color, list of 3 values in 0-1 range, alpha will be 1.
'''
def __get__(self):
return self.rgba[:-1]
def __set__(self, rgb):
self.rgba = (rgb[0], rgb[1], rgb[2], 1.0)
property r:
'''Red component, between 0-1
'''
def __get__(self):
return self.rgba[0]
def __set__(self, r):
self.rgba = [r, self.g, self.b, self.a]
property g:
'''Green component, between 0-1
'''
def __get__(self):
return self.rgba[1]
def __set__(self, g):
self.rgba = [self.r, g, self.b, self.a]
property b:
'''Blue component, between 0-1
'''
def __get__(self):
return self.rgba[2]
def __set__(self, b):
self.rgba = [self.r, self.g, b, self.a]
property a:
'''Alpha component, between 0-1
'''
def __get__(self):
return self.rgba[3]
def __set__(self, a):
self.rgba = [self.r, self.g, self.b, a]
property hsv:
'''HSV color, list of 3 values in 0-1 range, alpha will be 1.
'''
def __get__(self):
return rgb_to_hsv(self.r, self.h, self.b)
return rgb_to_hsv(self.r, self.g, self.b)
def __set__(self, x):
self.rgb = hsv_to_rgb(x[0], x[1], x[2])
property h:
'''Hue component, between 0-1
'''
def __get__(self):
return self.hsv[0]
def __set__(self, x):
self.hsv = [x, self.s, self.v]
property s:
'''Saturation component, between 0-1
'''
def __get__(self):
return self.hsv[1]
def __set__(self, x):
self.hsv = [self.h, x, self.v]
property v:
'''Value component, between 0-1
'''
def __get__(self):
return self.hsv[2]
def __set__(self, x):

View File

@ -594,6 +594,7 @@ cdef class Texture:
with nogil:
glBindTexture(target, self._id)
glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
glTexSubImage2D(target, 0, x, y, w, h, glfmt, glbufferfmt, cdata)
glFlush()

View File

@ -512,20 +512,32 @@ cdef class BorderImage(Rectangle):
cdef class Ellipse(Rectangle):
'''A 2D ellipse.
.. versionadded:: 1.0.7 added angle_start + angle_end
:Parameters:
`segments`: int, default to 180
Define how much segment is needed for drawing the ellipse.
The drawing will be smoother if you have lot of segment.
`angle_start`: int default to 0
Specifies the starting angle, in degrees, of the disk portion
`angle_end`: int default to 360
Specifies the ending angle, in degrees, of the disk portion
'''
cdef int _segments
cdef float _angle_start
cdef float _angle_end
def __init__(self, *args, **kwargs):
Rectangle.__init__(self, **kwargs)
self.batch.set_mode('triangle_fan')
self._segments = kwargs.get('segments', 180)
self._angle_start = kwargs.get('angle_start', 0)
self._angle_end = kwargs.get('angle_end', 360)
cdef void build(self):
cdef list tc = self.tex_coords
cdef int i
cdef int i, angle_dir
cdef float angle_start, angle_end, angle_range
cdef float x, y, angle, rx, ry, ttx, tty, tx, ty, tw, th
cdef vertex_t *vertices = NULL
cdef int *indices = NULL
@ -539,40 +551,53 @@ cdef class Ellipse(Rectangle):
rx = 0.5 * self.w
ry = 0.5 * self.h
vertices = <vertex_t *>malloc((count + 1) * sizeof(vertex_t))
vertices = <vertex_t *>malloc((count + 2) * sizeof(vertex_t))
if vertices == NULL:
raise MemoryError('vertices')
indices = <int *>malloc(3 * count * sizeof(int))
indices = <int *>malloc((count + 2) * sizeof(int))
if indices == NULL:
free(vertices)
raise MemoryError('indices')
for i in xrange(count):
# rad = deg * (pi / 180), where pi/180 = 0.0174...
angle = i * 360.0/self._segments *0.017453292519943295
x = (self.x+rx)+ (rx*cos(angle))
y = (self.y+ry)+ (ry*sin(angle))
# calculate the start/end angle in radians, and adapt the range
if self.angle_end > self.angle_start:
angle_dir = 1
else:
angle_dir = -1
# rad = deg * (pi / 180), where pi/180 = 0.0174...
angle_start = (self._angle_start % 361) * 0.017453292519943295
angle_end = (self._angle_end % 361) * 0.017453292519943295
if angle_end > angle_start:
angle_range = angle_end - angle_start
else:
angle_range = angle_start - angle_end
angle_range = angle_range / self._segments
# add start vertice in the middle
x = self.x + rx
y = self.y + ry
ttx = ((x - self.x) / self.w) * tw + tx
tty = ((y - self.y) / self.h) * th + ty
vertices[0].x = self.x + rx
vertices[0].y = self.y + ry
vertices[0].s0 = ttx
vertices[0].t0 = tty
indices[0] = 0
for i in xrange(1, count + 2):
angle = angle_start + (angle_dir * (i - 1) * angle_range)
x = (self.x+rx)+ (rx*sin(angle))
y = (self.y+ry)+ (ry*cos(angle))
ttx = ((x-self.x)/self.w)*tw + tx
tty = ((y-self.y)/self.h)*th + ty
vertices[i].x = x
vertices[i].y = y
vertices[i].s0 = ttx
vertices[i].t0 = tty
indices[i * 3] = i
indices[i * 3 + 1] = count
indices[i * 3 + 2] = (i + 1) % count
indices[i] = i
#add last verte in the middle
x, y = self.x+rx, self.y+ry
ttx = ((x-self.x)/self.w)*tw + tx
tty = ((y-self.y)/self.h)*th + ty
vertices[count].x = x
vertices[count].y = y
vertices[count].s0 = ttx
vertices[count].t0 = tty
self.batch.set_data(vertices, count + 1, indices, count * 3)
self.batch.set_data(vertices, count + 2, indices, count + 2)
free(vertices)
free(indices)
@ -585,3 +610,22 @@ cdef class Ellipse(Rectangle):
def __set__(self, value):
self._segments = value
self.flag_update()
property angle_start:
'''Angle start of the ellipse in degrees, default to 0
'''
def __get__(self):
return self._angle_start
def __set__(self, value):
self._angle_start = value
self.flag_update()
property angle_end:
'''Angle end of the ellipse in degrees, default to 360
'''
def __get__(self):
return self._angle_end
def __set__(self, value):
self._angle_end = value
self.flag_update()

View File

@ -11,7 +11,7 @@ refer to http://tuio.org -- The specification should be of special interest.
__all__ = ('TuioMotionEventProvider', 'Tuio2dCurMotionEvent',
'Tuio2dObjMotionEvent')
import osc
from kivy.lib import osc
from collections import deque
from kivy.input.provider import MotionEventProvider
from kivy.input.factory import MotionEventFactory

View File

@ -4,8 +4,7 @@ External libraries
Kivy come with other python/c libraries :
- squirtle (modified / optimized)
- oscAPI (modified / optimized)
- transformation (C)
- mtdev
'''

View File

@ -29,7 +29,7 @@ Kivy's property classes support:
Better Memory Management
The same instance of a property is shared across multiple widget
instances. The value storage is independent of the Widget.
instances.
'''
@ -42,7 +42,6 @@ __all__ = ('Property',
'ObjectProperty', 'BooleanProperty', 'BoundedNumericProperty',
'OptionProperty', 'ReferenceListProperty', 'AliasProperty')
cdef class Property:
'''Base class for building more complex properties.
@ -78,13 +77,11 @@ cdef class Property:
cdef str _name
cdef int allownone
cdef object defaultvalue
cdef dict storage
def __cinit__(self):
self._name = ''
self.allownone = 0
self.defaultvalue = None
self.storage = {}
def __init__(self, defaultvalue, **kw):
self.defaultvalue = defaultvalue
@ -121,32 +118,33 @@ cdef class Property:
d = dict()
self._name = name
self.init_storage(d)
self.storage[obj.__uid] = d
obj.__storage[name] = d
cpdef link_deps(self, object obj, str name):
pass
"""
cpdef unlink(self, obj):
'''Destroy the storage of a widget
'''
if obj in self.storage:
del self.storage[obj.__uid]
if self._name in obj.__storage:
del obj.__storage[self._name]
"""
cpdef bind(self, obj, observer):
'''Add a new observer to be called only when the value is changed
'''
observers = self.storage[obj.__uid]['observers']
observers = obj.__storage[self._name]['observers']
if not observer in observers:
observers.append(observer)
cpdef unbind(self, obj, observer):
'''Remove the observer from our widget observer list
'''
if obj.__uid not in self.storage:
return
observers = self.storage[obj.__uid]['observers']
if observer in observers:
observers.remove(observer)
observers = obj.__storage[self._name]['observers']
for obj in observers[:]:
if observer in observers:
observers.remove(obj)
def __set__(self, obj, val):
self.set(obj, val)
@ -163,7 +161,7 @@ cdef class Property:
'''Set a new value for the property
'''
value = self.convert(obj, value)
d = self.storage[obj.__uid]
d = obj.__storage[self._name]
realvalue = d['value']
if self.compare_value(realvalue, value):
return False
@ -175,7 +173,7 @@ cdef class Property:
cpdef get(self, obj):
'''Return the value of the property
'''
return self.storage[obj.__uid]['value']
return obj.__storage[self._name]['value']
#
# Private part
@ -189,7 +187,7 @@ cdef class Property:
bool, True if the value correctly validates.
'''
if x is None:
if not self.storage[obj.__uid]['allownone']:
if not obj.__storage[self._name]['allownone']:
raise ValueError('None is not allowed')
else:
return True
@ -203,8 +201,8 @@ cdef class Property:
cdef dispatch(self, obj):
'''Dispatch the value change to all observers
'''
observers = self.storage[obj.__uid]['observers']
value = self.storage[obj.__uid]['value']
observers = obj.__storage[self._name]['observers']
value = obj.__storage[self._name]['value']
for observer in observers:
observer(obj, value)
@ -244,6 +242,9 @@ cdef class StringProperty(Property):
raise ValueError('StringProperty<%s> accepts only str/unicode' %
self.name)
cdef observable_list_dispatch(object self):
cdef Property prop = self.prop
prop.dispatch(self.obj)
class ObservableList(list):
# Internal class to observe changes inside a native python list.
@ -254,69 +255,56 @@ class ObservableList(list):
def __setitem__(self, key, value):
list.__setitem__(self, key, value)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def __delitem__(self, key):
list.__delitem__(self, key)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def __setslice__(self, *largs):
list.__setslice__(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def __delslice__(self, *largs):
list.__delslice__(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def __iadd__(self, *largs):
list.__iadd__(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def __imul__(self, *largs):
list.__imul__(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def __add__(self, *largs):
cdef object result = list.__add__(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
return result
def append(self, *largs):
list.append(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def remove(self, *largs):
list.remove(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def insert(self, *largs):
list.insert(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def pop(self, *largs):
list.pop(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def extend(self, *largs):
list.extend(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
def sort(self, *largs):
list.sort(self, *largs)
cdef Property prop = self.prop
prop.dispatch(self.obj)
observable_list_dispatch(self)
cdef class ListProperty(Property):
@ -332,7 +320,7 @@ cdef class ListProperty(Property):
'''
cpdef link(self, object obj, str name):
Property.link(self, obj, name)
storage = self.storage[obj.__uid]
storage = obj.__storage[self._name]
storage['value'] = ObservableList(self, obj, storage['value'])
cdef check(self, obj, value):
@ -456,7 +444,7 @@ cdef class OptionProperty(Property):
cdef check(self, obj, value):
if Property.check(self, obj, value):
return True
valid_options = self.storage[obj.__uid]['options']
valid_options = obj.__storage[self._name]['options']
if value not in valid_options:
raise ValueError('OptionProperty<%s> have an invalid option %r. '
'Must be one of: %s' % (self.name,
@ -492,13 +480,15 @@ cdef class ReferenceListProperty(Property):
for prop in self.properties:
prop.bind(obj, self.trigger_change)
"""
cpdef unlink(self, obj):
for prop in self.properties:
prop.unbind(obj, self.trigger_change)
Property.unlink(self, obj)
"""
cpdef trigger_change(self, obj, value):
s = self.storage[obj.__uid]
s = obj.__storage[self._name]
if s['stop_event']:
return
p = s['properties']
@ -512,14 +502,14 @@ cdef class ReferenceListProperty(Property):
return list(value)
cdef check(self, obj, value):
if len(value) != len(self.storage[obj.__uid]['properties']):
if len(value) != len(obj.__storage[self._name]['properties']):
raise ValueError('ReferenceListProperty<%s> value length is '
'immutable' % self.name)
cpdef set(self, obj, _value):
cdef int idx
cdef list value
storage = self.storage[obj.__uid]
storage = obj.__storage[self._name]
value = self.convert(obj, _value)
if self.compare_value(storage['value'], value):
return False
@ -537,7 +527,7 @@ cdef class ReferenceListProperty(Property):
return True
cpdef get(self, obj):
s = self.storage[obj.__uid]
s = obj.__storage[self._name]
p = s['properties']
s['value'] = [p[x].get(obj) for x in xrange(len(p))]
return s['value']
@ -589,24 +579,26 @@ cdef class AliasProperty(Property):
oprop = getattr(obj.__class__, prop)
oprop.bind(obj, self.trigger_change)
"""
cpdef unlink(self, obj):
for prop in self.bind_objects:
oprop = getattr(obj.__class__, prop)
oprop.unbind(obj, self.trigger_change)
Property.unlink(self, obj)
"""
cpdef trigger_change(self, obj, value):
self.storage[obj.__uid]['value'] = self.get(obj)
obj.__storage[self._name]['value'] = self.get(obj)
self.dispatch(obj)
cdef check(self, obj, value):
return True
cpdef get(self, obj):
return self.storage[obj.__uid]['getter'](obj)
return obj.__storage[self._name]['getter'](obj)
cpdef set(self, obj, value):
if self.storage[obj.__uid]['setter'](obj, value):
self.storage[obj.__uid]['value'] = self.get(obj)
if obj.__storage[self._name]['setter'](obj, value):
obj.__storage[self._name]['value'] = self.get(obj)
self.dispatch(obj)

View File

@ -11,6 +11,7 @@ class Widget(object):
def __init__(self, **kwargs):
super(Widget, self).__init__(**kwargs)
self.__dict__['__uid'] = 1
self.__dict__['__storage'] = {}
wid = Widget()

View File

@ -0,0 +1,38 @@
" Vim syntax file
" Language: Kivy
" Maintainer: George Sebastian <11george.s@gmail.com>
" Last Change: 2011 May 1
" For version 5.x: Clear all syntax items.
" For version 6.x: Quit when a syntax file was already loaded.
if version < 600
syntax clear
elseif exists("b:current_syntax")
finish
endif
syn match kivyPreProc /#:.*/
syn match kivyComment /#.*/
syn match kivyRule /<\I\i*\(,\s*\I\i*\)*>:/
syn match kivyAttribute /\<\I\i*\>/ nextgroup=kivyValue
syn include @pyth $VIMRUNTIME/syntax/python.vim
syn region kivyValue start=":" end=/$/ contains=@pyth skipwhite
syn region kivyAttribute matchgroup=kivyIdent start=/[\a_][\a\d_]*:/ end=/$/ contains=@pyth skipwhite
if version >= 508 || !exists("did_python_syn_inits")
if version <= 508
let did_python_syn_inits = 1
command -nargs=+ HiLink hi link <args>
else
command -nargs=+ HiLink hi def link <args>
endif
HiLink kivyPreproc PreProc
HiLink kivyComment Comment
HiLink kivyRule Function
HiLink kivyIdent Statement
HiLink kivyAttribute Label
delcommand HiLink
endif

View File

@ -26,7 +26,7 @@ layout, and the second should be 30%. ::
The `size_hint` represent the size available after substracting all the
fixed size. For example, if you have 3 widgets (width is 200px,
50%, 50%), and if the layout have a width of 600px :
50%, 50%), and if the layout have a width of 800px :
- the first widget width will be 200px
- the second widget width will be 300px

View File

@ -107,7 +107,7 @@ class Camera(Image):
if not self._camera:
return
if value:
self._camera.play()
self._camera.start()
else:
self._camera.stop()

View File

@ -114,7 +114,7 @@ class Image(Widget):
tw, th = self.texture.size
# ensure that the width is always maximized to the containter width
iw = w if tw < w else w
iw = w if tw < w else tw
# calculate the appropriate height
ih = iw / ratio
# if the height is too higher, take the height of the container

View File

@ -43,7 +43,7 @@ class ToggleButton(Button):
def on_group(self, *largs):
groups = ToggleButton.__groups
if self._previous_group:
groups.remove(self)
groups[self._previous_group].remove(self)
group = self._previous_group = self.group
if not group in groups:
groups[group] = []

View File

@ -100,6 +100,7 @@ class Widget(EventDispatcher):
# of doing that without require any python code. :)
Widget.__widget_uid += 1
self.__dict__['__uid'] = Widget.__widget_uid
self.__dict__['__storage'] = {}
cp = Widget.__cache_properties
if __cls__ not in cp:
@ -128,13 +129,6 @@ class Widget(EventDispatcher):
# Then, return the class instance
return self
def __del__(self):
# The thing here, since the storage of the property is inside the
# Property class, we must remove ourself from the storage of each
# Property. The usage is faster, the creation / deletion is longer.
for attr in self.__properties.itervalues():
attr.unlink(self)
def __init__(self, **kwargs):
super(Widget, self).__init__()

View File

@ -107,7 +107,7 @@ ext_modules = []
# list all files to compile
pyx_files = []
pxd_files = []
kivy_libs_dir = realpath(kivy.kivy_libs_dir)
kivy_libs_dir = realpath(join(kivy.kivy_base_dir, 'libs'))
for root, dirnames, filenames in walk(join(dirname(__file__), 'kivy')):
# ignore lib directory
if realpath(root).startswith(kivy_libs_dir):
@ -124,7 +124,7 @@ if not have_cython:
# add cython core extension modules if cython is available
if True:
libraries = []
libraries = ['m']
include_dirs = []
extra_link_args = []
if platform == 'win32':
@ -183,7 +183,7 @@ if True:
sdl_extra_link_args += ['-framework', 'ImageIO']
else:
sdl_includes = ['/usr/local/include/SDL']
sdl_extra_link_args += ['-L', '/usr/local/lib/']
sdl_extra_link_args += ['-L/usr/local/lib/']
pxd_core = [x for x in pxd_files if not 'graphics' in x]
pxd_graphics = [x for x in pxd_files if 'graphics' in x]
@ -193,6 +193,7 @@ if True:
ext_files = [pyx]
ext_libraries = libraries[:]
ext_include_dirs = include_dirs[:]
ext_extra_compile_args = []
ext_extra_link_args = extra_link_args[:]
ext_extra_compile_args = []
@ -205,6 +206,7 @@ if True:
ext_libraries += sdl_libraries
ext_include_dirs += sdl_includes
ext_extra_link_args += sdl_extra_link_args
elif pyx.endswith('osxcoreimage.pyx') or pyx.endswith('osxcoreimage.c'):
if c_options['use_ios'] is False:
continue
@ -215,6 +217,7 @@ if True:
ext_extra_link_args += ['-framework', 'QuartzCore']
ext_extra_link_args += ['-framework', 'ImageIO']
ext_extra_compile_args += ['-isysroot', '/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS4.3.sdk']
elif 'graphics' in pyx:
ext_files += pxd_graphics
else:
@ -224,6 +227,7 @@ if True:
module_name,
ext_files,
libraries=ext_libraries,
extra_compile_args=ext_extra_compile_args,
include_dirs=ext_include_dirs,
extra_compile_args=ext_extra_compile_args,
extra_link_args=ext_extra_link_args))
@ -274,6 +278,7 @@ setup(
'kivy.core.text',
'kivy.core.video',
'kivy.core.window',
'kivy.ext',
'kivy.graphics',
'kivy.input',
'kivy.input.postproc',