Conflicts:
	kivy/data/images/defaulttheme-0.png
	kivy/data/images/defaulttheme.atlas
This commit is contained in:
qua-non 2012-11-20 14:19:48 +05:30
commit 6fd44448c1
186 changed files with 4190 additions and 921 deletions

19
.travis.yml Normal file
View File

@ -0,0 +1,19 @@
language: python
python:
- "2.6"
- "2.7"
# command to install dependencies
before_install:
- sudo apt-get update
- sudo apt-get install python-dev libsdl-image1.2-dev libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsdl1.2-dev libsmpeg-dev python-numpy libportmidi-dev ffmpeg libswscale-dev libavformat-dev libavcodec-dev libjpeg-dev libtiff4-dev libx11-6 libX11-dev
- sudo apt-get install python-setuptools python-opengl gstreamer0.10-plugins-good build-essential libgl1-mesa-dev libgles2-mesa-dev mercurial
- sudo apt-get install xvfb
install:
- pip install hg+http://bitbucket.org/pygame/pygame
- pip install --upgrade cython pil --use-mirrors
- make
# command to run tests
script:
- xvfb-run -s "+extension GLX" make test

View File

@ -23,6 +23,7 @@ import kivy
# force loading of kivy modules
import kivy.app
import kivy.metrics
import kivy.atlas
import kivy.core.audio
import kivy.core.camera
@ -43,6 +44,7 @@ import kivy.modules.monitor
import kivy.modules.touchring
import kivy.modules.inspector
import kivy.modules.recorder
import kivy.modules.screen
import kivy.network.urlrequest
import kivy.support
import kivy.input.recorder
@ -50,7 +52,7 @@ import kivy.interactive
from kivy.factory import Factory
# force loading of all classes from factory
for x in Factory.classes:
for x in Factory.classes.keys()[:]:
getattr(Factory, x)

View File

@ -25,4 +25,9 @@ stunning applications in short time using the framework.
contact
.. toctree::
:maxdepth: 3
guide2-index
.. include:: api-index.rst

View File

@ -175,11 +175,43 @@ get instant karma. Congratulations, you're a hero!
Documentation Contributions
---------------------------
Documentation contributions generally follow the same workflow as code
contributions, just a bit more lax. We don't ask you to go through all the
hassle just to correct a single typo. For more complex contributions, please
consider following the suggested workflow though.
Documentation contributions generally follow the same workflow as code contributions, just a bit more lax.
#. Following the instructions above,
#. Fork the repository.
#. Clone your fork to your computer.
#. Setup kivy repo as a remote source.
#. Install python-sphinx. (See docs/sources/README for assistance.)
#. Use ReStructuredText_Markup_ to make changes to the HTML documentation in docs/sources.
.. _ReStructuredText_Markup: http://docutils.sourceforge.net/rst.html
To submit a documentation update, use the following steps:
#. Create a new, appropriately named branch in your local repository.::
git checkout -b my_docs_update
#. Modify the documentation with your correction or improvement.
#. Re-generate the HTML pages, and review your update.::
make html
#. Give each commit an appropriate commit message, so that others who are not familiar with the matter get a good idea of what you changed.
#. Keep each commit focused on a single related theme. Don't commit other stuff that doesn't logically belong to this update.
#. Push to your remote repository on GitHub::
git push
#. Send a *Pull Request* with a description of what you changed via the button in the GitHub interface of your repository.
We don't ask you to go through all the hassle just to correct a single typo, but for more complex contributions, please follow the suggested workflow.
Docstrings
~~~~~~~~~~

View File

@ -107,6 +107,8 @@ Examples
.. |wdg_desc1| replace:: Usage and Showcase of :class:`Accordion <kivy.uix.accordion>` Widget.
.. |wdg_file2| replace:: asyncimage.py
.. |wdg_desc2| replace:: Usage and Showcase of :class:`AsyncImage <kivy.uix.image.AsyncImage>` Widget.
.. |wdg_file25| replace:: boxlayout_pos_hint.py
.. |wdg_desc25| replace:: Showcase of pos_hint under BoxLayout :class:`BoxLayout <kivy.uix.boxlayout>`
.. |wdg_file3| replace:: bubble_test.py
.. |wdg_desc3| replace:: Usage and Showcase of :class:`Bubble <kivy.uix.bubble>` Widget.
.. |wdg_file4| replace:: customcollide.py
@ -118,7 +120,11 @@ Examples
.. |wdg_file7| replace:: keyboardlistener.py
.. |wdg_desc7| replace:: listen to the keyboard input and spew result to console.
.. |wdg_file8| replace:: label_mipmap.py
.. |wdg_desc8| replace:: How to use :class:`Label <kivy.uix.label>` widget with mipmap.
.. |wdg_desc8| replace:: How to use :class:`Label <kivy.uix.label>` widget with
.. |wdg_file81| replace:: label_with_markup.py
.. |wdg_desc81| replace:: Useage of :class:`Label <kivy.uix.label>` widget with markup.
.. |wdg_file82| replace:: popup_with_kv.py
.. |wdg_desc82| replace:: Useage of :class:`Popup <kivy.uix.popup>` widget with ``kv`` language
.. |wdg_file9| replace:: rstexample.py
.. |wdg_desc9| replace:: Usage and Showcase of :class:`RstDocument <kivy.uix.rst.RstDocument>` Widget.
.. |wdg_file10| replace:: scatter.py
@ -198,12 +204,15 @@ Examples
+------------+---------------+------------------------+
|- |wdg_dir| | - |wdg_file1| |- |wdg_desc1| |
| | - |wdg_file2| |- |wdg_desc2| |
| | - |wdg_file25||- |wdg_desc25| |
| | - |wdg_file3| |- |wdg_desc3| |
| | - |wdg_file4| |- |wdg_desc4| |
| | - |wdg_file5| |- |wdg_desc5| |
| | - |wdg_file6| |- |wdg_desc6| |
| | - |wdg_file7| |- |wdg_desc7| |
| | - |wdg_file8| |- |wdg_desc8| |
| | - |wdg_file81||- |wdg_desc81| |
| | - |wdg_file82||- |wdg_desc82| |
| | - |wdg_file9| |- |wdg_desc9| |
| | - |wdg_file10||- |wdg_desc10| |
| | - |wdg_file11||- |wdg_desc11| |

View File

@ -1,3 +1,5 @@
.. _guide-index:
Programming Guide
=================

View File

@ -6,6 +6,9 @@
Designing with the Kivy Language
================================
The code goes in main.py
~~~~~~~~~~~~~~~~~~~~~~~~
Let's start with a little example. First, the Python file named `main.py`:
.. include:: ../../../examples/guide/designwithkv/main.py
@ -20,6 +23,9 @@ In addition, we are creating a ``do_action()`` method, that will use both of
these properties. It will change the ``info`` text, and change text in the
``label_wid`` widget.
The layout goes in controller.kv
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Executing this application without a corresponding `.kv` file will work, but
nothing will be shown on the screen. This is expected, because the
``Controller`` class has no widgets in it, it's just a ``FloatLayout``. We can

View File

@ -32,11 +32,6 @@ KIVY_NO_FILELOG
KIVY_NO_CONSOLELOG
If set, logs will be not print on the console
KIVY_DPI
If set, the value will be used instead of the value returned by the window.
.. versionadded:: 1.4.0
Path control
------------
@ -101,3 +96,22 @@ KIVY_CLIPBOARD
Values: pygame, dummy
Metrics
-------
KIVY_DPI
If set, the value will be used for :data:`Metrics.dpi`.
.. versionadded:: 1.4.0
KIVY_METRICS_DENSITY
If set, the value will be used for :data:`Metrics.density`.
.. versionadded:: 1.5.0
KIVY_METRICS_FONTSCALE
If set, the value will be used for :data:`Metrics.fontscale`.
.. versionadded:: 1.5.0

View File

@ -169,17 +169,15 @@ This is what has changed:
:class:`~kivy.graphics.vertex_instructions.Line`, you will see that
it accepts a ``points`` argument that has to be a list of 2D point
coordinates, like ``(x1, y1, x2, y2, ..., xN, yN)``.
* Line 8: This is where it gets interesting. ``touch.ud`` is a Python
* Line 13: This is where it gets interesting. ``touch.ud`` is a Python
dictionary (type <dict>) that allows us to store *custom attributes*
for a touch. On this line we simply get a reference to it to make it
more clear that ``ud`` stands for ``userdata``. You could just as
well write ``touch.ud`` instead of ``userdata``.
for a touch.
* Line 13: We make use of the Line instruction that we imported and
set a Line up for drawing. Since this is done in ``on_touch_down``,
there will be a new line for every new touch. By creating the line
inside the ``with`` block, the canvas automatically knows about the
line and will draw it. We just want to modify the line later, so we
store a reference to it in the ``userdata`` dictionary under the
store a reference to it in the ``touch.ud`` dictionary under the
arbitrarily chosen but aptly named key 'line'.
We pass the line that we're creating the initial touch position
because that's where our line will begin.
@ -193,13 +191,13 @@ This is what has changed:
shortly see why.
* Line 16: Remember: This is the same touch object that we got in
``on_touch_down``, so we can simply access the data we stored away
in the userdata dictionary!
in the ``touch.ud`` dictionary!
To the line we set up for this touch earlier, we now add the current
position of the touch as a new point. We know that we need to extend
the line because this happens in ``on_touch_move``, which is only
called when the touch has moved, which is exactly why we want to
update the line.
Storing the line in the userdata makes it a whole lot
Storing the line in the ``touch.ud`` makes it a whole lot
easier for us as we don't have to maintain our own touch-to-line
bookkeeping.
@ -218,13 +216,11 @@ Here are the changes:
* Line 1: We import Python's random() function that will give us
random values in the range of [0., 1.).
* Line 10: We want to memorize the color for this touch, so we store
it in the touch's userdata dictionary.
In this case we simply create a new tuple of 3 random
* Line 10: In this case we simply create a new tuple of 3 random
float values that will represent a random RGB color. Since we do
this in ``on_touch_down``, every new touch will get its own color.
Don't get confused by the use of two ``=`` operators. We're just
binding the tuple to ``c`` as well as a shortcut for use within this
binding the tuple to ``color`` as well as a shortcut for use within this
method because we're lazy.
* Line 12: As before, we set the color for the canvas. Only this time
we use the random values we generated and feed them to the color
@ -248,7 +244,7 @@ might even be able to create a nice little drawing!
There is a nice trick to prevent this: Instead of creating a tuple with
three random values, create a tuple like this: ``(random(), 1., 1.)``.
Then, when passing it to the color instruction, set the mode to HSV
color space: ``Color(*c, mode='hsv')``. This way you will have a
color space: ``Color(*color, mode='hsv')``. This way you will have a
smaller number of possible colors, but the colors that you get will
always be equally bright. Only the hue changes.

View File

@ -115,6 +115,10 @@ is where the Kivy language can be useful.
Usage of the Kivy language for graphics
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
.. note::
By default the name of the ``.kv`` file to be loaded is decided by the name of your main class. So if you main class's name is ``MyTestApp`` or ``MultiMapMayhem`` then ``mytest.kv`` or ``multimapmayhem.kv`` file will be auto-loaded respectively.
The Kivy language has a lot of benefits for this example ``Button``. You can
create a rule that will match your widget, create graphics instructions, and
update their properties according to a python expression. Here is the complete

View File

@ -10,6 +10,12 @@ Create a package for Android
.. _Packaging your application into APK:
TestDrive
---------
There is a VirtualBox Image we provide with the prerequisites along with
Android SDK and NDK preinstalled to ease your installation woes. You can
download it from `here <http://www.google.com/url?sa=D&q=https://docs.google.com/file/d/0B1WO07-OL50_VDNESDRUaDhXSmM/edit&usg=AFQjCNGrsg0SU8EMgAcLHWxbjSe8KM2kyA>`_.
Packaging your application into APK
-----------------------------------
@ -29,7 +35,7 @@ First, follow the prerequisites needed for the project:
http://python-for-android.readthedocs.org/en/latest/prerequisites/
Then a console, and type::
Then open a console, and type::
git clone git://github.com/kivy/python-for-android

View File

@ -81,6 +81,8 @@ You can customize the build in many ways:
#. Go to the settings panel > build, search for "strip" options, and
triple-check that they are all set to NO. Stripping is not working with
Python dynamic modules, and will strip needed symbols.
#. Indicate a launch image in portrait/landscape for ipad with and without
retina display.
.. _Known issues:
@ -90,12 +92,6 @@ Known issues
Currently, the project have few issues as (we'll fixes them during the
development):
- Loading time: Apple provide a way to reduce the feeling of a slow application
loading by showing an image when the application is initialize. But, due to
the SDL approach, IOS remove the launch image before we have started. So if
you are using a launch image, the user will see: The launch image -> black
screen -> your app. Remove the launch image for now.
- Application configuration not writing: we are learning how IOS manage its
filesystem.

View File

@ -68,7 +68,7 @@ Build the spec
#. Go to the pyinstaller directory, and build the spec::
cd pyinstaller-2.0
python Build.py touchtracer\\touchtracer.spec
python pyinstaller.py touchtracer\\touchtracer.spec
#. The package will be in the `touchtracer\\dist\\touchtracer` directory !

View File

@ -16,7 +16,7 @@ it will be generated like this:
.. image:: images/api-button.jpg
It should be read like this: the "Button" class is into the "kivy.uix.button"
It should be read like this: the "Button" class is in the "kivy.uix.button"
module. So if you want to import that class in your code, write that::
from kivy.uix.button import Button

View File

@ -0,0 +1,19 @@
Programming Guide 2
===================
.. warning::
We are currently refactoring the whole Programming Guide. This is a work in
progress, and might change at any times.
.. toctree::
:maxdepth: 2
guide2/basic
guide2/events
guide2/widgets
guide2/graphics
guide2/lang
guide2/bestpractices
guide2/advancedgraphics
guide2/packaging

View File

@ -0,0 +1,13 @@
.. _advancedgraphics:
Advanced Graphics
=================
Create your own Shader
----------------------
Rendering in a Framebuffer
--------------------------
Optimizations
-------------

View File

@ -0,0 +1,47 @@
.. _basic:
Basic Kivy
==========
Installation of Kivy environment
--------------------------------
Kivy depends on multiples dependencies, such as pygame, gstreamer, PIL, cairo,
and more. All of them are not required, but depending the platform you're
working on, it can be a pain to install them. For Windows and MacOSX, we
provide a portable package that you can just unzip and use.
.. toctree::
:maxdepth: 1
/installation/installation-windows.rst
/installation/installation-macosx.rst
/installation/installation-linux.rst
If you want to install everything yourself, ensure that you have at least
`Cython <http://cython.org>`_, `Pygame <http://pygame.org>`. A typical pip
installation look like::
pip install cython
pip install hg+http://bitbucket.org/pygame/pygame
pip install kivy
The `development version <https://github.com/kivy/kivy>`_ can be installed with
git::
git clone https://github.com/kivy/kivy
make
Create an application
---------------------
Running the application
-----------------------
Customize the application
-------------------------
Platform specifics
------------------

View File

@ -0,0 +1,17 @@
.. _bestpractices:
Best Practices
==============
Designing your Application code
-------------------------------
Handle Window resizing
----------------------
Managing resources
------------------
Platform consideration
----------------------

View File

@ -0,0 +1,23 @@
.. _events:
.. _properties:
Events and Properties
=====================
Introduction to Event Dispatcher
--------------------------------
Creating custom events
----------------------
Attaching callbacks
-------------------
Introduction to properties
--------------------------
Declaration of a Property
-------------------------
Dispatching a Property event
----------------------------

View File

@ -0,0 +1,17 @@
.. _graphics:
Graphics
========
Introduction to Canvas
----------------------
Context instructions
--------------------
Drawing instructions
--------------------
Manipulating instructions
-------------------------

View File

@ -0,0 +1,19 @@
.. _lang:
Kv language
===========
Concept behind the language
---------------------------
Rule context
------------
Instanciate children
--------------------
Extend canvas
-------------
Templating
----------

View File

@ -0,0 +1,2 @@
Packaging
=========

View File

@ -0,0 +1,17 @@
.. _widgets:
Widgets
=======
Introduction to Widget
----------------------
Manipulating the Widget tree
----------------------------
Organize with Layouts
---------------------
Seperate with Screen Manager
----------------------------

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 859 KiB

After

Width:  |  Height:  |  Size: 554 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

After

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 406 KiB

After

Width:  |  Height:  |  Size: 795 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.1 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 41 KiB

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 644 KiB

After

Width:  |  Height:  |  Size: 764 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

View File

@ -8,12 +8,10 @@ Welcome to Kivy's documentation. Kivy is an open source software library for rap
development of applications equipped with novel user interfaces, such as
multi-touch apps.
You are probably wondering why you'd be interested in using Kivy. There is
a document outlining our :ref:`philosophy` that we encourage you to read.
We recommend that you get started with :doc:`/gettingstarted/index`. Then head over the :ref:`guide-index`. We also have a :ref:`quickstart` if you are impatient.
We recommend that you get started with :ref:`installation` and then head over to
the :ref:`quickstart` document. Besides the quickstart, there is also a more
detailed :ref:`architecture`.
You are probably wondering why you'd be interested in using Kivy. There is
a document outlining our :ref:`philosophy` that we encourage you to read, and an detailed :ref:`architecture`.
If you want to contribute to Kivy, make sure to read :ref:`contributing`. If your
concern isn't addressed in the documentation, feel free to :ref:`contact`.

View File

@ -6,14 +6,15 @@ Installation on Linux
Prerequisites
-------------
Ubuntu (11.10)
~~~~~~~~~~~~~~
Ubuntu (11.10 or newer)
~~~~~~~~~~~~~~~~~~~~~~~
::
$ sudo apt-get install python-setuptools python-pygame python-opengl \
python-gst0.10 python-enchant gstreamer0.10-plugins-good cython python-dev \
build-essential libgl1-mesa-dev libgles2-mesa-dev
python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
build-essential libgl1-mesa-dev libgles2-mesa-dev python-pip
$ sudo pip install --upgrade cython
Fedora (16)
~~~~~~~~~~~
@ -21,10 +22,10 @@ Fedora (16)
::
$ sudo yum install python-distutils-extra python-enchant freeglut PyOpenGL \
SDL_ttf-devel SDL_mixer-devel pygame pygame-devel Cython khrplatform-devel \
SDL_ttf-devel SDL_mixer-devel pygame pygame-devel khrplatform-devel \
mesa-libGLES mesa-libGLES-devel gstreamer-plugins-good gstreamer \
gstreamer-python mtdev-devel
gstreamer-python mtdev-devel python-pip
$ sudo pip install --upgrade cython
OpenSuse (12.1)
~~~~~~~~~~~~~~~
@ -33,8 +34,9 @@ OpenSuse (12.1)
$ sudo zypper install python-distutils-extra python-pygame python-opengl \
python-gstreamer-0_10 python-enchant gstreamer-0_10-plugins-good \
python-Cython python-devel Mesa-devel
python-devel Mesa-devel python-pip
$ zypper install -t pattern devel_C_C++
$ sudo pip install --upgrade cython
Mageia (1 and 2(cauldron))
@ -47,6 +49,8 @@ Mageia (1 and 2(cauldron))
gstreamer0.10-python python-enchant gstreamer0.10-plugins-good \
python-cython lib64python-devel lib64mesagl1-devel lib64mesaegl1-devel \
lib64mesaglesv2_2-devel make gcc
$ sudo easy_install pip
$ sudo pip install --upgrade cython
Installation

View File

@ -21,7 +21,7 @@ file that contains:
To install Kivy, you must:
1. Download the latest version from http://kivy.org/#downloads
1. Download the latest version from http://kivy.org/#download
2. Double-click to open it
3. Drag the Kivy.app into your Applications folder
4. Make sure to read the Readme.txt

View File

@ -4,7 +4,7 @@ Installation
============
We try not to reinvent the wheel, but to bring something innovative to the
market. As a consequence, we're focused on our own code and use pre-existing,
market. As a consequence, we're focused on our own code and use pre-existing,
high-quality third-party libraries where possible.
To support the full, rich set of features that Kivy offers, several other libraries are
required. If you do not use a specific feature (e.g. video playback) you
@ -12,7 +12,7 @@ don't need the corresponding dependency, however.
That said, there is one dependency that Kivy **does** require:
`Cython <http://cython.org>`_.
In addition, you need a `Python <http://python.org/>`_ 2.x (**not** 3.x)
In addition, you need a `Python <http://python.org/>`_ 2.x (2.6 <= x < 3.0)
interpreter. If you want to enable features like windowing (i.e., open a Window),
audio/video playback or spelling correction, additional dependencies must
be available. For these, we recommend `Pygame <http://pygame.org>`_, `Gst-Python
@ -79,8 +79,14 @@ necessary packages:
::
$ sudo apt-get install python-setuptools python-pygame python-opengl \
python-gst0.10 python-enchant gstreamer0.10-plugins-good cython python-dev \
build-essential libgl1-mesa-dev libgles2-mesa-dev
python-gst0.10 python-enchant gstreamer0.10-plugins-good python-dev \
build-essential libgl1-mesa-dev libgles2-mesa-dev python-pip
Kivy require a recent version of cython, so it's better to use the last
version published on pypi.
::
$ sudo pip install --upgrade cython
.. _dev-install:

View File

@ -106,8 +106,8 @@ def callback_signature(app, what, name, obj, options, signature,
def setup(app):
import kivy
sys.path += [join(dirname(kivy.__file__), 'tools', 'highlight', 'pygments')]
from lexer_kivy import KivyLexer
sys.path += [join(dirname(kivy.__file__), 'extras')]
from highlight import KivyLexer
app.add_lexer('kv', KivyLexer())
app.add_autodocumenter(CythonMethodDocumenter)

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

View File

@ -0,0 +1,24 @@
Compass
=======
Demonstrate the combination of the Android Magnetic Field Sensor and the Kivy functionality viewing a Compass.
Kivy Python-For-Android
-----------------------
Please look at the lastest docs of the
`Kivy Python-For-Android Project <http://python-for-android.readthedocs.org/en/latest/>`__
Building an APK
---------------
::
./distribute.sh -m "pyjnius kivy"
::
./build.py --package org.test.compass --name compass \
--version 1.0 --dir ~/code/kivy/examples/android/compass debug

View File

@ -0,0 +1,3 @@
title=Compass
author=Nik Klever
orientation=portrait

View File

@ -0,0 +1,223 @@
import kivy
kivy.require('1.3.0')
import math
import time
from kivy.app import App
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.button import Button
from kivy.uix.scatter import Scatter
from kivy.clock import Clock
from kivy.vector import Vector
from kivy.core.window import Window
from kivy.graphics import Color, Ellipse, Rectangle, Triangle
from kivy.logger import Logger
from jnius import autoclass
Logger.info('COMPASS: STARTED')
def LoggerDisplayMetrics(metrics):
"""
Logging all values of the Java Android DisplayMetrics class
to get some more information about the metrics of Android devices
"""
display = {'Default':metrics.DENSITY_DEFAULT,
'Device':metrics.DENSITY_DEVICE,
'High':metrics.DENSITY_HIGH,
'Low':metrics.DENSITY_LOW,
'Medium':metrics.DENSITY_MEDIUM,
'XHIGH':metrics.DENSITY_XHIGH,
'density':metrics.density,
'densityDpi':metrics.densityDpi,
'heightPixels':metrics.heightPixels,
'scaledDensity':metrics.scaledDensity,
'widthPixels':metrics.widthPixels,
'xdpi':metrics.xdpi,
'ydpi':metrics.ydpi}
for (k,v) in display.items():
Logger.info('COMPASS: display %s = %s'%(k,v))
class CompassWidget(FloatLayout):
def __init__(self, **kwargs):
"""
Constructor of the CompassWidget class
"""
super(CompassWidget, self).__init__(**kwargs)
def build(self,pos,size):
"""
building the background of the CompassWidget with a circle of a
compass windrose image
(Source of this image: Wikipedia - http://en.wikipedia.org/wiki/Compass_rose)
"""
with self.canvas:
self.pos = pos
self.size = size
self.windrose = Ellipse(source="500px-Windrose.svg.png", pos=pos, size=size)
class NeedleWidget(Scatter):
def __init__(self, **kwargs):
"""
Constructor of the NeedleWidget class
do_rotation, do_translation, do_scale are all set to False
to indicate that the scatter widget can onlybe updated from the
app and not by an interaction with your fingers
"""
super(NeedleWidget, self).__init__(**kwargs)
self.do_rotation = False
self.do_translation = False
self.do_scale = False
self.auto_bring_to_front = True
def rotateNeedle(self,angle):
"""
rotate the NeedleWidget with the parameter angle
90 is subtracted because North of the windrose is at 90 degrees
of the device
"""
self.rotation = angle - 90
def build(self,center,needleSize):
"""
building the needle with two Triangles of different color
"""
self.pos = center - needleSize/2.
self.size = needleSize
self.size_hint = [None, None]
with self.canvas:
Color(1., 0, 0)
needleTP1 = Vector(needleSize[0]/2.,needleSize[1])
needleTP2 = Vector(needleSize[0]/2.,0)
needleTP3 = Vector(-needleSize[0],needleSize[1]/2.)
needlePoints = (needleTP1[0],needleTP1[1],
needleTP2[0],needleTP2[1],
needleTP3[0],needleTP3[1])
self.needleT1 = Triangle(points=needlePoints)
Color(0.5, 0.5, 0.5)
needleTP3 = Vector(2*needleSize[0],needleSize[1]/2.)
needlePoints = (needleTP1[0],needleTP1[1],
needleTP2[0],needleTP2[1],
needleTP3[0],needleTP3[1])
self.needleT2 = Triangle(points=needlePoints)
class CompassApp(App):
def __init__(self, **kwargs):
"""
Constructor of the Compass App
1) The Java Android API DisplayMetrics is called to get
information about the densityDpi factor of the Android device
2) The Kivy Python-For-Android Android API is called to
get access to the hardware sensors of the Android device
"""
super(CompassApp, self).__init__(**kwargs)
DisplayMetrics = autoclass('android.util.DisplayMetrics')
metrics = DisplayMetrics()
metrics.setToDefaults()
LoggerDisplayMetrics(metrics)
self.densityDpi = metrics.densityDpi
Hardware = autoclass('org.renpy.android.Hardware')
self.hw = Hardware()
Logger.info('COMPASS: Hardware Objects: %s'%(str(dir(self.hw))))
Logger.info('COMPASS: Hardware Sensors\n%s\n'%(self.hw.getHardwareSensors()))
def viewCompass(self, *largs):
"""
viewCompass calls the readSensor method of the
magneticFieldSensor instance of the generic3AxisSensor, it reads the
3-tuple value of the magnetic field
the declination angle is computed as the angle of the magnetic field
vector in the x,y-plane and the unity-vector of the y-axis.
afterwards the rotateNeedle function rotates the needle as given
by the declination angle parameter
"""
(x, y, z) = self.hw.magneticFieldSensor.readSensor()
declination = Vector(x,y).angle((0,1))
#Logger.info('COMPASS: viewCompass x=%s y=%s z=%s declination=%s'%(x,y,z,declination))
self.needle.rotateNeedle(declination)
def stopApp(self,*largs):
"""
this function is called when pushed the stopButton, disables
the magneticFieldSensor and stops the app
"""
self.hw.magneticFieldSensor.changeStatus(False)
Logger.info('COMPASS: stop largs '+str(largs))
self.stop()
def build(self):
"""
Building all together:
1) Creating the parent widget and clearing it to white background color
2) Defining a suitable position and size of the CompassWidget, the
needleSize and the stopButtonHeight depending on the densityDpi value
given by DisplayMetrics
3) Creating an instance of the CompassWidget and adding it to the
parent widget and calling the appropriate build function
4) Creating an instance of the NeedleWidget and adding it also to the
parent widget and calling the appropriate build function
5) Creating an instance of a Button widget and adding it as stopButton
also to the parent widget and bind it with the stopApp function
6) Calling the instance method changeStatus of the magneticFieldSensor
instance with parameter True to enable the magnetic field sensor
and additionally calling the function schedule_interval of the Clock
class for a repeated call of the function viewCompass every second.
"""
parent = FloatLayout(size=(500,500))
Window.clearcolor = (1, 1, 1, 1)
if self.densityDpi == 240:
CompassPos = Vector(50., 200.)
CompassSize = Vector(400., 400.)
needleSize = Vector(100., 60.)
stopButtonHeight = 60
elif self.densityDpi == 320:
CompassPos = Vector(75., 300.)
CompassSize = Vector(600., 600.)
needleSize = Vector(150., 90.)
stopButtonHeight = 90
else:
Logger.info('COMPASS: widget size should be adopted - minimum used for densityDpi=%s'%(str(self.densityDpi)))
CompassPos = Vector(50., 200.)
CompassSize = Vector(400., 400.)
needleSize = Vector(100., 60.)
stopButtonHeight = 60
self.Compass = CompassWidget()
parent.add_widget(self.Compass)
self.Compass.build(pos=CompassPos,size=CompassSize)
self.needle = NeedleWidget()
parent.add_widget(self.needle)
self.needle.build(center=CompassPos+CompassSize/2.,needleSize=needleSize)
self.stopButton = Button(text='Stop', pos_hint={'right':1}, size_hint=(None,None), height=stopButtonHeight)
parent.add_widget(self.stopButton)
self.stopButton.bind(on_press=self.stopApp)
self.hw.magneticFieldSensor.changeStatus(True)
Clock.schedule_interval(self.viewCompass, 1.)
return parent
if __name__ in ('__main__', '__android__'):
CompassApp().run()

View File

@ -0,0 +1 @@
1323529642.46

View File

@ -28,8 +28,7 @@ class TestApp(App):
def build(self):
# create a button, and attach animate() method as a on_press handler
button = Button(size_hint=(None, None), text='plop')
button.bind(on_press=self.animate)
button = Button(size_hint=(None, None), text='plop', on_press=self.animate)
return button
if __name__ == '__main__':

View File

@ -34,14 +34,14 @@ class StressCanvasApp(App):
label = Label(text='0')
btn_add100 = Button(text='+ 100 rects')
btn_add100.bind(on_press=partial(self.add_rects, label, wid, 100))
btn_add100 = Button(text='+ 100 rects',
on_press=partial(self.add_rects, label, wid, 100))
btn_add500 = Button(text='+ 500 rects')
btn_add500.bind(on_press=partial(self.add_rects, label, wid, 500))
btn_add500 = Button(text='+ 500 rects',
on_press=partial(self.add_rects, label, wid, 500))
btn_reset = Button(text='Reset')
btn_reset.bind(on_press=partial(self.reset_rects, label, wid))
btn_reset = Button(text='Reset',
on_press=partial(self.reset_rects, label, wid))
layout = BoxLayout(size_hint=(1, None), height=50)
layout.add_widget(btn_add100)

View File

@ -83,6 +83,20 @@ Builder.load_string('''
Label:
center: root.center
text: 'Rectangle'
<LineBezier>:
canvas:
Color:
rgba: .1, .1, 1, .9
Line:
width: 2.
bezier: (self.x, self.y, self.center_x - 40, self.y + 100, self.center_x + 40, self.y - 100, self.right, self.y)
Label:
center: root.center
text: 'Bezier'
''')
@ -107,6 +121,9 @@ class LineCircle3(Widget):
class LineRectangle(Widget):
pass
class LineBezier(Widget):
pass
class LineExtendedApp(App):
def build(self):
root = GridLayout(cols=2, padding=50, spacing=50)
@ -117,6 +134,7 @@ class LineExtendedApp(App):
root.add_widget(LineCircle2())
root.add_widget(LineCircle3())
root.add_widget(LineRectangle())
root.add_widget(LineBezier())
return root
if __name__ == '__main__':

View File

@ -0,0 +1,8 @@
This is the Kivy Catalog viewer. It serves two purposes:
1. To showcase the various widgets available in Kivy
2. To allow interactive editing of Kivy language files
to get immediate feedback as to how they work
Known bugs:
* The DropDown
* Some widgets are still missing

View File

@ -0,0 +1,15 @@
#:kivy 1.4
AnchorLayout:
anchor_x: "right"
anchor_y: "bottom"
Button:
text: "Button 1"
size_hint: .2, .4
Button:
text: "Button 2"
size_hint: .4, .2
Button:
text: "Button 3"
size_hint: .2, .2

View File

@ -0,0 +1,14 @@
#:kivy 1.4
BoxLayout:
orientation: 'vertical'
padding: 20
spacing: 10
Button:
text: "Button 1"
size_hint: 1, None
Button:
text: "Button 2"
size_hint: 1, 0.5
Button:
text: "Button 3"

View File

@ -0,0 +1,27 @@
#:kivy 1.4
GridLayout:
cols: 2
Button:
text: "Button 1"
Button:
text: "Button 2"
font_size: 24
Button:
text: "Button 3"
background_color: .7, .7, 1, 1
Button:
text: "Button 4"
on_press: self.text = 'pressed'
on_release: self.text = 'Button 4'
ToggleButton:
text: "A toggle button"
ToggleButton:
text: "a toggle button in a group"
group: "money"
ToggleButton:
text: "A toggle in the down state"
state: "down"
ToggleButton:
text: "another toggle button in a group"
group: "money"

View File

@ -0,0 +1,27 @@
#:kivy 1.4
GridLayout:
cols: 2
CheckBox:
Label:
text: "A checkbox"
active: True
CheckBox:
Label:
text: "Another checkbox"
CheckBox:
group: "money"
Label:
text: "A radio in a group"
CheckBox:
group: "money"
Label:
text: "Another radio in same group"
active: True
Switch:
Label:
text: "A Switch"
Switch:
active: True
Label:
text: "An active switch"

View File

@ -0,0 +1,19 @@
#:kivy 1.4
BoxLayout:
# Double as a Tabbed Panel Demo!
TabbedPanel:
tab_pos: "top_right"
default_tab_text: "List View"
default_tab_content: list_view_tab
TabbedPanelHeader:
text: 'Icon View'
content: icon_view_tab
FileChooserListView:
id: list_view_tab
FileChooserIconView:
id: icon_view_tab
show_hidden: True

View File

@ -0,0 +1,16 @@
#:kivy 1.4
FloatLayout:
Button:
text: "Button 1"
pos: 100, 100
size_hint: .2, .4
Button:
text: "Button 2"
pos: 200, 200
size_hint: .4, .2
Button:
text: "Button 3"
pos_hint: {'x': .8, 'y': .6}
size_hint: .2, .2

View File

@ -0,0 +1,20 @@
#:kivy 1.4
GridLayout:
cols: 2
Button:
text: "Button 1"
size_hint_x: None
width: 100
Button:
text: "Button 2"
Button:
text: "Button 3"
size_hint_x: None
Button:
text: "Button 4"
Button:
text: "Button 5"
Button:
text: "Button 6"
size_hint_x: None

View File

@ -0,0 +1,21 @@
#:kivy 1.4
GridLayout:
rows: 2
Label:
text: "Label 1"
Label:
text: "Label with\nmultiple lines"
Label:
text: "Label [color=ff3333]with[/color] [color=3333ff][b]markup[/b][/color]"
markup: True
Label:
text: "Label with [ref=reference]reference[/ref]"
markup: True
on_ref_press: self.text = "ref clicked"
Label:
text: "different font"
bold: True
font_name: "data/fonts/DroidSansMono.ttf"
font_size: 32
valign: "bottom"

View File

@ -0,0 +1,9 @@
#:kivy 1.4
BoxLayout:
orientation: "vertical"
Image:
source: "../../widgets/softboy.png"
Video:
source: "../../widgets/softboy.avi"
state: "play"

View File

@ -0,0 +1,4 @@
#:kivy 1.4
RstDocument:
text: "Welcome\n---------------\nThe Kivy Catalog is an interactive showcase of Kivy Widgets defined in the Kivy language. For each widget you see, you can directly edit the .kv language syntax to see what effects your changes have on the widget. Click 'Render' or hit 'Ctrl-S' to view your changes.\n\nThere is also a playground on this tab where you can test your Kivy language code directly. This is beta software. The basics seem to work, but some widgets are missing or don't have the ideal .kv representation. Not all widgets are represented yet. It is trivial to add a new .kv file to the interface.\n\nPull requests are welcome."

View File

@ -0,0 +1,23 @@
#:kivy 1.4
BoxLayout:
orientation: "vertical"
Bubble:
size_hint: (None, None)
size: (150, 50)
pos_hint: {'center_x': .5, 'y': .6}
arrow_pos: 'bottom_mid'
orientation: 'horizontal'
BubbleButton:
text: 'Click'
BubbleButton:
text: 'A'
BubbleButton:
text: 'Bubble'
Popup:
id: popup
title: "An example popup"
content: popupcontent
Label:
id: popupcontent
text: "Some text\nin the popup"

View File

@ -0,0 +1,17 @@
#:kivy 1.4
BoxLayout:
orientation: 'vertical'
padding: 50
ProgressBar:
id: bar
value: 140
max: 300
Slider:
id: slider
max: 200
value: 140
on_value: bar.value = self.value
Slider:
orientation: 'vertical'
on_value: slider.value = self.value

View File

@ -0,0 +1,5 @@
#:kivy 1.4
BoxLayout:
RstDocument:
text: ".. _top:\n\nHello world\n===========\n\nThis is an **emphased text**, some ``interpreted text``.\nAnd this is a reference to top_::\n\n $ print 'Hello world'\n"

View File

@ -0,0 +1,16 @@
#:kivy 1.4
FloatLayout:
Scatter:
size_hint: None, None
size: 100, 100
pos: 100, 100
Image:
source: "../../widgets/softboy.png"
Scatter:
size_hint: None, None
size: 100, 100
pos: 100, 100
do_rotation: False
Label:
text: "something"

View File

@ -0,0 +1,10 @@
#:kivy 1.4
BoxLayout:
orientation: 'vertical'
Spinner:
text: "Work"
values: "Work", "Home", "Mobile", "Skype"
size_hint: (None, None)
size: (100, 44)
# Wanted to put DropDown here, too, but it seems not to be working too well when loaded from .kv

View File

@ -0,0 +1,25 @@
#:kivy 1.4
StackLayout:
orientation: 'tb-lr'
padding: 10
spacing: 5
Button:
text: "Button 1"
size_hint: .2, .4
width: 100
Button:
text: "Button 2"
size_hint: .2, .4
Button:
text: "Button 3"
size_hint: .2, .4
Button:
text: "Button 4"
size_hint: .2, .4
Button:
text: "Button 5"
size_hint: .2, .4
Button:
text: "Button 6"
size_hint: .2, .4

View File

@ -0,0 +1,20 @@
#:kivy 1.4
BoxLayout:
orientation: "vertical"
TextInput:
text: "Single Line Input"
multiline: False
TextInput:
text: "Text Input, start typing here\nmultiline\nsupport"
background_color: .8, .8, 0, 1
size_hint: 1, 3
TextInput:
text: "Password (but you can't see it)"
password: True
multiline: False
on_text: viewer.text = self.text
TextInput:
id: viewer
read_only: True
text: "edit the password to see it here"

View File

@ -0,0 +1,147 @@
#:kivy 1.4
#:import KivyLexer kivy.extras.highlight.KivyLexer
[ContainerToggle@ToggleButton]:
group: "container_toggle"
text: ctx.text
on_press: root.parent.parent.parent.show_kv(*args)
state: ctx.state if hasattr(ctx, "state") else "normal"
<Catalog>:
language_box: language_box
screen_manager: screen_manager
auto_reload: chkbx.active
info_label: info_lbl
orientation: 'vertical'
BoxLayout:
BoxLayout:
size_hint: None, 1
orientation: "vertical"
ContainerToggle:
text: "Welcome"
state: "down"
ContainerToggle:
text: "Float Layout"
ContainerToggle:
text: "Box Layout"
ContainerToggle:
text: "Anchor Layout"
ContainerToggle:
text: "Grid Layout"
ContainerToggle:
text: "Stack Layout"
ContainerToggle:
text: "Buttons"
ContainerToggle:
text: "Labels"
ContainerToggle:
text: "Booleans"
ContainerToggle:
text: "Progress Bar"
ContainerToggle:
text: "Media"
ContainerToggle:
text: "Text"
ContainerToggle:
text: "Popups"
ContainerToggle:
text: "Selectors"
ContainerToggle:
text: "File Choosers"
ContainerToggle:
text: "Scatter"
ContainerToggle:
text: "ReST"
ScreenManager:
id: screen_manager
Screen:
name: "Welcome"
PlaygroundContainer:
Screen:
name: "Float Layout"
FloatLayoutContainer
Screen:
name: "Box Layout"
BoxLayoutContainer:
Screen:
name: "Anchor Layout"
AnchorLayoutContainer:
Screen:
name: "Grid Layout"
GridLayoutContainer:
Screen:
name: "Stack Layout"
StackLayoutContainer:
Screen:
name: "Buttons"
ButtonContainer:
Screen:
name: "Labels"
LabelContainer:
Screen:
name: "Booleans"
CheckBoxContainer:
Screen:
name: "Progress Bar"
ProgressBarContainer:
Screen:
name: "Media"
MediaContainer:
Screen:
name: "Text"
TextContainer:
Screen:
name: "Popups"
PopupContainer:
Screen:
name: "Selectors"
SelectorsContainer:
Screen:
name: "File Choosers"
FileChooserContainer:
Screen:
name: "Scatter"
ScatterContainer:
Screen:
name: "ReST"
RestContainer:
BoxLayout:
id: bl
orientation: "vertical"
size_hint: None, 1
width: 400
KivyRenderTextInput:
lexer: KivyLexer()
text_size: self.width-20, self.height-20
font_name: "data/fonts/DroidSansMono.ttf"
valign: "top"
id: language_box
text: "This box will display the kivy language for whatever has been selected"
on_text: root.schedule_reload()
BoxLayout:
size_hint: 1, None
height: '30pt'
BoxLayout:
CheckBox:
id: chkbx
active: True
Label:
text: "Auto Reload"
Button:
text: 'Render Now'
on_release: root.change_kv(*args)
FloatLayout:
size_hint: 1, None
height: 0
TextInput:
id:info_lbl
readonly: True
font_size: '14sp'
background_color: (0, 0, 0, 1)
foreground_color: (1, 1, 1, 1)
opacity:0
size_hint: 1, None
text_size: self.size
height: '150pt'
top: 0

View File

@ -0,0 +1,166 @@
import kivy
kivy.require('1.4.2')
import os
import sys
from kivy.app import App
from kivy.factory import Factory
from kivy.lang import Builder, Parser, ParserException
from kivy.properties import ObjectProperty
from kivy.config import Config
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.popup import Popup
from kivy.uix.label import Label
from kivy.uix.codeinput import CodeInput
from kivy.animation import Animation
from kivy.clock import Clock
print Config.get('graphics', 'width')
Config.set('graphics', 'width', '1024')
Config.set('graphics', 'height', '768')
'''List of classes that need to be instantiated in the factory from .kv files.
'''
CONTAINER_CLASSES = [c[:-3] for c in os.listdir('container_kvs')
if c.endswith('.kv')]
class Container(BoxLayout):
'''A container is essentially a class that loads its root from a known
.kv file.
The name of the .kv file is taken from the Container's class.
We can't just use kv rules because the class may be edited
in the interface and reloaded by the user.
See :meth: change_kv where this happens.
'''
def __init__(self, **kwargs):
super(Container, self).__init__(**kwargs)
parser = Parser(content=file(self.kv_file).read())
widget = Factory.get(parser.root.name)()
Builder._apply_rule(widget, parser.root, parser.root)
self.add_widget(widget)
@property
def kv_file(self):
'''Get the name of the kv file, a lowercase version of the class
name.
'''
return os.path.join('container_kvs',
self.__class__.__name__ + ".kv")
for class_name in CONTAINER_CLASSES:
globals()[class_name] = type(class_name, (Container,), {})
class KivyRenderTextInput(CodeInput):
def _keyboard_on_key_down(self, window, keycode, text, modifiers):
is_osx = sys.platform == 'darwin'
# Keycodes on OSX:
ctrl, cmd = 64, 1024
key, key_str = keycode
if text and not key in (self.interesting_keys.keys() + [27]):
# This allows *either* ctrl *or* cmd, but not both.
if modifiers == ['ctrl'] or (is_osx and modifiers == ['meta']):
if key == ord('s'):
self.parent.parent.parent.change_kv(True)
return
super(KivyRenderTextInput, self)._keyboard_on_key_down(
window, keycode, text, modifiers)
class Catalog(BoxLayout):
'''Catalog of widgets. This is the root widget of the app. It contains
a tabbed pain of widgets that can be displayed and a textbox where .kv
language files for widgets being demoed can be edited.
The entire interface for the Catalog is defined in kivycatalog.kv,
although individual containers are defined in the container_kvs
directory.
To add a container to the catalog,
first create the .kv file in container_kvs
The name of the file (sans .kv) will be the name of the widget available
inside the kivycatalog.kv
Finally modify kivycatalog.kv to add an AccordionItem
to hold the new widget.
Follow the examples in kivycatalog.kv to ensure the item
has an appropriate id and the class has been referenced.
You do not need to edit any python code, just .kv language files!
'''
language_box = ObjectProperty()
screen_manager = ObjectProperty()
def __init__(self, **kwargs):
super(Catalog, self).__init__(**kwargs)
self.show_kv(None)
def show_kv(self, object):
'''Called when an accordionitem is collapsed or expanded. If it
was expanded, we need to show the .kv language file associated with
the newly revealed container.'''
# if object is not passed, it's initialization, we just need to load
# the file
if object:
# one button must always be pressed, even if user presses it again
if object.state == "normal":
object.state = "down"
self.screen_manager.current = object.text
with open(self.screen_manager.current_screen.content.children[
0].kv_file) as file:
self.language_box.text = file.read()
# reset undo/redo history
self.language_box.reset_undo()
def schedule_reload(self):
if self.auto_reload:
Clock.unschedule(self.change_kv)
Clock.schedule_once(self.change_kv, 2)
def change_kv(self, *largs):
'''Called when the update button is clicked. Needs to update the
interface for the currently active kv widget, if there is one based
on the kv file the user entered. If there is an error in their kv
syntax, show a nice popup.'''
kv_container = self.screen_manager.current_screen.content.children[0]
try:
parser = Parser(content=self.language_box.text.encode('utf8'))
kv_container.clear_widgets()
widget = Factory.get(parser.root.name)()
Builder._apply_rule(widget, parser.root, parser.root)
kv_container.add_widget(widget)
except (SyntaxError, ParserException) as e:
self.info_label.text = str(e)
self.anim = Animation(top=190.0, opacity=1, d=2, t='in_back') +\
Animation(top=190.0, d=2) +\
Animation(top=0, opacity=0, d=2)
self.anim.start(self.info_label)
except:
import traceback
traceback.print_exc()
popup = Popup(title="Boom",
content=Label(text='Something horrible happened while parsing'
+ 'your Kivy Language', text_size=(350, None),
size_hint=(None, None), size=(400, 400)))
popup.open()
class KivyCatalogApp(App):
'''The kivy App that runs the main root. All we do is build a catalog
widget into the root.'''
def build(self):
return Catalog()
if __name__ == "__main__":
KivyCatalogApp().run()

View File

@ -1,4 +1,5 @@
#:kivy 1.0
#: import GLShaderLexer pygments.lexers.GLShaderLexer
<ShaderEditor>:
viewer: viewer
@ -13,16 +14,18 @@
text: 'Fragment Shader'
size_hint_y: None
height: self.texture_size[1] + 10
TextInput:
CodeInput:
text: root.fs
lexer: GLShaderLexer()
on_text: root.fs = args[1]
Label:
text: 'Vertex Shader'
size_hint_y: None
height: self.texture_size[1] + 10
TextInput:
CodeInput:
text: root.vs
lexer: GLShaderLexer()
on_text: root.vs = args[1]
ShaderViewer:

View File

@ -16,6 +16,7 @@ from kivy.properties import StringProperty
from kivy.clock import Clock
import random
class Showcase(FloatLayout):
pass
@ -60,6 +61,7 @@ class BoxLayoutShowcase(FloatLayout):
super(BoxLayoutShowcase, self).__init__(**kwargs)
self.buttons = 0
self.txt = 'horizontal'
self.text_size = self.size
Clock.schedule_once(self.add_button, 1)
def add_button(self, *l):
@ -71,7 +73,10 @@ class BoxLayoutShowcase(FloatLayout):
self.txt = self.blayout.orientation = 'horizontal'
else:
self.txt = self.blayout.orientation = 'vertical'
self.blayout.add_widget(Button(text = self.txt))
btn = Button(text=self.txt, halign='center', valign='middle')
btn.bind(size=btn.setter('text_size'))
self.blayout.add_widget(btn)
Clock.schedule_once(self.add_button, 1)
@ -87,9 +92,9 @@ class FloatLayoutShowcase(FloatLayout):
if self.buttons > 5:
self.buttons = 0
self.flayout.clear_widgets()
self.flayout.add_widget(Button(text = 'no restrictions\n what so ever',
size_hint = (None, None), size = (150, 40),
pos_hint = {'x':random.random(), 'y': random.random()}))
self.flayout.add_widget(Button(text='no restrictions\n what so ever',
size_hint=(None, None), size=(150, 40),
pos_hint={'x': random.random(), 'y': random.random()}))
Clock.schedule_once(self.add_button, 1)
@ -106,7 +111,7 @@ class GridLayoutShowcase(FloatLayout):
def add_button(self, *l):
self.buttons += 1
if self.buttons > 20:
if self.buttons > 10:
self.buttons = 0
self.glayout.clear_widgets()
if self.txt == "rows = 3":
@ -117,7 +122,7 @@ class GridLayoutShowcase(FloatLayout):
self.glayout.rows = 3
self.glayout.cols = 7
self.txt = "rows = 3"
self.glayout.add_widget(Button(text = self.txt))
self.glayout.add_widget(Button(text=self.txt))
Clock.schedule_once(self.add_button, 1)
@ -157,9 +162,11 @@ class StandardWidgets(FloatLayout):
class ComplexWidgets(FloatLayout):
pass
class TreeViewWidgets(FloatLayout):
pass
class ShowcaseApp(App):
def on_select_node(self, instance, value):
@ -243,17 +250,16 @@ class ShowcaseApp(App):
return col
def show_popup(self):
btnclose = Button(text='Close this popup', size_hint_y=None, height=50)
btnclose = Button(text='Close this popup', size_hint_y=None, height='50sp')
content = BoxLayout(orientation='vertical')
content.add_widget(Label(text='Hello world'))
content.add_widget(btnclose)
popup = Popup(content=content, title='Modal popup example',
size_hint=(None, None), size=(300, 300),
auto_dismiss=False)
size_hint=(None, None), size=('300dp', '300dp'))
btnclose.bind(on_release=popup.dismiss)
button = Button(text='Open popup', size_hint=(None, None),
size=(150, 70))
button.bind(on_release=popup.open)
size=('150sp', '70dp'),
on_release=popup.open)
popup.open()
col = AnchorLayout()
col.add_widget(button)

View File

@ -14,17 +14,18 @@
orientation: 'vertical'
BoxLayout:
padding: 10
spacing: 10
padding: '10dp'
spacing: '10dp'
size_hint: 1, None
pos_hint: {'top': 1}
height: 44
height: '44dp'
Image:
size_hint: None, None
size: 24, 24
source: 'data/logo/kivy-icon-24.png'
size: '24dp', '24dp'
source: 'data/logo/kivy-icon-64.png'
mipmap: True
Label:
height: 24
height: '24dp'
text_size: self.width, None
color: (1, 1, 1, .8)
text: 'Kivy %s - Showcase' % kivy.__version__
@ -55,7 +56,7 @@
[Title@Label]
pos_hint: {'center_x': .5, 'y': .3}
text: ctx.text
font_size: 22
font_size: '29dp'
<AnchorLayoutShowcase>
Title:
@ -153,9 +154,9 @@
[HSeparator@Label]:
size_hint_y: None
height: 45
height: max(dp(45), self.texture_size[1] + dp(10))
text: ctx.text if 'text' in ctx else ''
text_size: self.size
text_size: self.width, None
valign: 'middle'
halign: 'center'
canvas.before:
@ -257,18 +258,18 @@
TextInput:
text: 'Monoline textinput'
size_hint_y: None
height: 30
height: sp(30)
TextInput:
text: 'This is a password'
size_hint_y: None
height: 30
height: sp(30)
password: True
TextInput:
text: 'Readonly textinput'
size_hint_y: None
height: 30
height: sp(30)
readonly: True
TextInput:
@ -313,6 +314,8 @@
title: 'Panel 1'
Label:
text: 'This is a label fit to the content view'
halign: 'center'
text_size: self.width, None
AccordionItem:
title: 'Panel 2'
@ -323,6 +326,8 @@
title: 'Panel 3'
Label:
text: 'This is a label fit to the content view'
halign: 'center'
text_size: self.width, None
Accordion:
@ -333,6 +338,7 @@
title: 'Panel 1'
Label:
text: 'This is a label fit to the content view'
text_size: self.width, None
AccordionItem:
title: 'Panel 2'
@ -343,6 +349,7 @@
title: 'Panel 3'
Label:
text: 'This is a label fit to the content view'
text_size: self.width, None
VSeparator

View File

@ -10,17 +10,18 @@
size: self.size
BoxLayout:
padding: 10
spacing: 10
padding: '10dp'
spacing: '10dp'
size_hint: 1, None
pos_hint: {'top': 1}
height: 44
height: '44dp'
Image:
size_hint: None, None
size: 24, 24
source: 'data/logo/kivy-icon-24.png'
size: '24dp', '24dp'
source: 'data/logo/kivy-icon-64.png'
mipmap: True
Label:
height: 24
height: '24dp'
text_size: self.width, None
color: (1, 1, 1, .8)
text: 'Kivy %s - Touchtracer' % kivy.__version__

View File

@ -4,14 +4,16 @@ from kivy.graphics import Color, Ellipse
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
with self.canvas:
Color(1, 1, 0)
d = 30.
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
class MyPaintApp(App):
def build(self):
return MyPaintWidget()

View File

@ -4,19 +4,20 @@ from kivy.graphics import Color, Ellipse, Line
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
userdata = touch.ud
with self.canvas:
Color(1, 1, 0)
d = 30.
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
userdata['line'] = Line(points=(touch.x, touch.y))
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]
class MyPaintApp(App):
def build(self):
return MyPaintWidget()

View File

@ -5,20 +5,21 @@ from kivy.graphics import Color, Ellipse, Line
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
userdata = touch.ud
userdata['color'] = c = (random(), random(), random())
color = (random(), random(), random())
with self.canvas:
Color(*c)
Color(*color)
d = 30.
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
userdata['line'] = Line(points=(touch.x, touch.y))
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]
class MyPaintApp(App):
def build(self):
return MyPaintWidget()

View File

@ -8,13 +8,12 @@ from kivy.graphics import Color, Ellipse, Line
class MyPaintWidget(Widget):
def on_touch_down(self, touch):
userdata = touch.ud
userdata['color'] = c = (random(), 1, 1)
color = (random(), 1, 1)
with self.canvas:
Color(*c, mode='hsv')
d = 30
Ellipse(pos=(touch.x - d/2, touch.y - d/2), size=(d, d))
userdata['line'] = Line(points=(touch.x, touch.y))
Color(*color, mode='hsv')
d = 30.
Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
touch.ud['line'] = Line(points=(touch.x, touch.y))
def on_touch_move(self, touch):
touch.ud['line'].points += [touch.x, touch.y]

View File

@ -17,7 +17,7 @@ class BlehApp(App):
def build(self):
root = BoxLayout()
for idx, word in enumerate(('Hello', 'World')):
wid = Builder.template('BlehItem', {
wid = Builder.template('BlehItem', **{
'idx': idx, 'word': word,
})
root.add_widget(wid)

View File

@ -0,0 +1,52 @@
from kivy.uix.gridlayout import GridLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Demo>:
cols: 1
BoxLayout:
orientation: 'vertical'
Button:
size_hint_x: 0.4
pos_hint: {'x': 0}
text: 'pos_hint: x=0'
Button:
size_hint_x: 0.2
pos_hint: {'center_x': 0.5}
text: 'pos_hint: center_x=0.5'
Button:
size_hint_x: 0.4
pos_hint: {'right': 1}
text: 'pos_hint: right=1'
BoxLayout:
Button:
size_hint_y: 0.4
pos_hint: {'y': 0}
text: 'pos_hint: y=0'
Button:
size_hint_y: 0.2
pos_hint: {'center_y': .5}
text: 'pos_hint: center_y=0.5'
Button:
size_hint_y: 0.4
pos_hint: {'top': 1}
text: 'pos_hint: top=1'
''')
class Demo(GridLayout):
pass
class DemoApp(App):
def build(self):
return Demo()
if __name__ == '__main__':
DemoApp().run()

View File

@ -0,0 +1,37 @@
'''
Carousel example with button inside.
This is a tiny test for testing the scroll distance/timeout
And ensure the down/up are dispatched if no gesture is done.
'''
from kivy.uix.carousel import Carousel
from kivy.uix.gridlayout import GridLayout
from kivy.app import App
from kivy.lang import Builder
Builder.load_string('''
<Page>:
cols: 3
Label:
text: str(id(root))
Button
Button
Button
Button
Button
Button
Button
Button
''')
class Page(GridLayout):
pass
class TestApp(App):
def build(self):
root = Carousel()
for x in xrange(10):
root.add_widget(Page())
return root
if __name__ == '__main__':
TestApp().run()

View File

@ -0,0 +1,179 @@
from kivy.app import App
from kivy.extras.highlight import KivyLexer
from kivy.uix.spinner import Spinner, SpinnerOption
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.codeinput import CodeInput
from kivy.uix.popup import Popup
from kivy.properties import ListProperty
from kivy.core.window import Window
from pygments import lexers
from pygame import font as fonts
import codecs, os
example_text = '''
---------------------Python----------------------------------
import kivy
kivy.require('1.0.6') # replace with your current kivy version !
from kivy.app import App
from kivy.uix.button import Button
class MyApp(App):
def build(self):
return Button(text='Hello World')
if __name__ == '__main__':
MyApp().run()
----------------------Java-----------------------------------
public static byte toUnsignedByte(int intVal) {
byte byteVal;
return (byte)(intVal & 0xFF);
}
---------------------kv lang---------------------------------
#:kivy 1.0
<YourWidget>:
canvas:
Color:
rgb: .5, .5, .5
Rectangle:
pos: self.pos
size: self.size
---------------------HTML------------------------------------
<!-- Place this tag where you want the +1 button to render. -->
<div class="g-plusone" data-annotation="inline" data-width="300"></div>
<!-- Place this tag after the last +1 button tag. -->
<script type="text/javascript">
(function() {
var po = document.createElement('script');
po.type = 'text/javascript';
po.async = true;
po.src = 'https://apis.google.com/js/plusone.js';
var s = document.getElementsByTagName('script')[0];
s.parentNode.insertBefore(po, s);
})();
</script>
'''
class Fnt_SpinnerOption(SpinnerOption):
pass
class LoadDialog(Popup):
def load(self, path, selection):
self.choosen_file = [None, ]
self.choosen_file = selection
Window.title = selection[0][selection[0].rfind(os.sep)+1:]
self.dismiss()
def cancel(self):
self.dismiss()
class SaveDialog(Popup):
def save(self, path, selection):
_file = codecs.open(selection, 'w', encoding='utf8')
_file.write(self.text)
Window.title = selection[selection.rfind(os.sep)+1:]
_file.close()
self.dismiss()
def cancel(self):
self.dismiss()
class CodeInputTest(App):
files = ListProperty([None, ])
def build(self):
b = BoxLayout(orientation='vertical')
languages = Spinner(
text='language',
values=sorted(['KvLexer', ] + lexers.LEXERS.keys()))
languages.bind(text=self.change_lang)
menu = BoxLayout(
size_hint_y=None,
height='30pt')
fnt_size = Spinner(
text='12',
values=map(str, range(5, 40)))
fnt_size.bind(text=self._update_size)
fnt_name = Spinner(
text='DroidSansMono',
option_cls=Fnt_SpinnerOption,
values=sorted(map(str, fonts.get_fonts())))
fnt_name.bind(text=self._update_font)
mnu_file = Spinner(
text='File',
values=('Open', 'SaveAs', 'Save', 'Close'))
mnu_file.bind(text=self._file_menu_selected)
menu.add_widget(mnu_file)
menu.add_widget(fnt_size)
menu.add_widget(fnt_name)
menu.add_widget(languages)
b.add_widget(menu)
self.codeinput = CodeInput(
lexer=KivyLexer(),
font_name='data/fonts/DroidSansMono.ttf', font_size=12,
text=example_text)
b.add_widget(self.codeinput)
return b
def _update_size(self, instance, size):
self.codeinput.font_size = float(size)
def _update_font(self, instance, fnt_name):
instance.font_name = self.codeinput.font_name =\
fonts.match_font(fnt_name)
def _file_menu_selected(self, instance, value):
if value == 'File':
return
instance.text = 'File'
if value == 'Open':
if not hasattr(self, 'load_dialog'):
self.load_dialog = LoadDialog()
self.load_dialog.open()
self.load_dialog.bind(choosen_file=self.setter('files'))
elif value == 'SaveAs':
if not hasattr(self, 'saveas_dialog'):
self.saveas_dialog = SaveDialog()
self.saveas_dialog.text = self.codeinput.text
self.saveas_dialog.open()
elif value == 'Save':
if self.files[0]:
_file = codecs.open(self.files[0], 'w', encoding='utf8')
_file.write(self.codeinput.text)
_file.close()
elif value == 'Close':
if self.files[0]:
self.codeinput.text = ''
Window.title = 'untitled'
def on_files(self, instance, values):
if not values[0]:
return
_file = codecs.open(values[0], 'r', encoding='utf8')
self.codeinput.text = _file.read()
_file.close()
def change_lang(self, instance, l):
if l == 'KvLexer':
lx = KivyLexer()
else:
lx = lexers.get_lexer_by_name(lexers.LEXERS[l][2][0])
self.codeinput.lexer = lx
if __name__ == '__main__':
CodeInputTest().run()

View File

@ -0,0 +1,55 @@
#:import fonts pygame.font
#:import os os
<Fnt_SpinnerOption>:
fnt_name: fonts.match_font(self.text)
font_name: self.fnt_name if self.fnt_name else self.font_name
<LoadDialog>:
title: filechooser.path
choosen_file: None
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
path: os.getcwd()
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Load"
on_release: root.load(filechooser.path, filechooser.selection)
<SaveDialog>:
text_input: text_input
BoxLayout:
size: root.size
pos: root.pos
orientation: "vertical"
FileChooserListView:
id: filechooser
path: os.getcwd()
on_selection: text_input.text = self.selection and self.selection[0] or ''
TextInput:
id: text_input
size_hint_y: None
height: 30
multiline: False
BoxLayout:
size_hint_y: None
height: 30
Button:
text: "Cancel"
on_release: root.cancel()
Button:
text: "Save"
on_release: root.save(filechooser.path, text_input.text)

View File

@ -22,8 +22,7 @@ class CustomPopup(Popup):
class TestApp(App):
def build(self):
b = Button()
b.bind(on_press=self.show_popup)
b = Button(on_press=self.show_popup)
return b
def show_popup(self, b):

View File

@ -54,8 +54,9 @@ Builder.load_string('''
<PanelLeft>
size_hint: (.45, .45)
pos_hint: {'center_x': .25, 'y': .55}
#replace the default tab with our custom tab
#replace the default tab with our custom tab class
default_tab_cls: sh.__class__
do_default_tab: True
default_tab_content: default_content
tab_width: 40
tab_height: 70
@ -100,19 +101,18 @@ Builder.load_string('''
size_hint: None, 1
orientation: 'vertical'
width: 22
Widget:
Button:
border: 0,0,0,0
background_normal: 'tools/theming/defaulttheme/close.png'
on_release: root.panel.remove_widget(root)
Widget:
Image:
source: 'tools/theming/defaulttheme/close.png'
on_touch_down:
if self.collide_point(*args[1].pos) :\
root.panel.remove_widget(root)
<PanelRight>
tab_pos: 'top_right'
size_hint: (.45, .45)
pos_hint: {'center_x': .75, 'y': .55}
#replace the default tab with our custom tab
# replace the default tab with our custom tab
default_tab: def_tab
#allow variable tab width
tab_width: None
@ -170,29 +170,23 @@ Builder.load_string('''
tab_pos: 'bottom_left'
size_hint: (.45, .45)
pos_hint: {'center_x': .25, 'y': .02}
default_tab_text: 'Settings'
default_tab_content: default_content
FloatLayout:
do_default_tab: False
TabbedPanelItem:
id: settings
text: 'Settings'
RstDocument:
id: default_content
text: '\\n'.join(("Normal tabs", "-------------",\
"Tabs in \\'%s\\' position" %root.tab_pos))
Image:
id: tab_2_content
pos: self.parent.pos
size: self.parent.size
source: 'data/images/defaulttheme-0.png'
Image:
id: tab_3_content
pos:self.parent.pos
size: self.parent.size
source: 'data/images/image-loading.gif'
TabbedPanelHeader:
"Tabs in \\'%s\\' position" %root.tab_pos))
TabbedPanelItem:
text: 'tab2'
content: tab_2_content
TabbedPanelHeader:
BubbleButton:
text: 'switch to settings'
on_press: root.switch_to(settings)
TabbedPanelItem:
text: 'tab3'
content: tab_3_content
Image:
source: 'data/images/image-loading.gif'
<PanelbRight>
tab_pos: 'right_top'
@ -257,26 +251,23 @@ Builder.load_string('''
class Tp(TabbedPanel):
#override tab switching method to animate on tab switch
def switch_to(self, header):
anim = Animation(color=(1, 1, 1, 0), d =.24, t = 'in_out_quad')
anim = Animation(opacity=0, d=.24, t='in_out_quad')
def start_anim(_anim, child, in_complete, *lt):
if hasattr(child, 'color'):
_anim.start(child)
elif not in_complete:
_on_complete()
_anim.start(child)
def _on_complete(*lt):
if hasattr(header.content, 'color'):
header.content.color = (0, 0, 0, 0)
anim = Animation(color =
(1, 1, 1, 1), d =.23, t = 'in_out_quad')
if header.content:
header.content.opacity = 0
anim = Animation(opacity=1, d=.43, t='in_out_quad')
start_anim(anim, header.content, True)
super(Tp, self).switch_to(header)
anim.bind(on_complete = _on_complete)
if self.content:
if self.current_tab.content:
start_anim(anim, self.current_tab.content, False)
else:
_on_complete()

View File

@ -15,30 +15,24 @@ Builder.load_string("""
<Test>:
size_hint: .5, .5
pos_hint: {'center_x': .5, 'center_y': .5}
default_tab_content: set1_content
do_default_tab: False
Label:
id: set1_content
text: 'First tab content area'
BoxLayout:
id: set2_content
TabbedPanelItem:
text: 'first tab'
Label:
text: 'Second tab content area'
Button:
text: 'Button that does nothing'
text: 'First tab content area'
TabbedPanelItem:
text: 'tab2'
BoxLayout:
Label:
text: 'Second tab content area'
Button:
text: 'Button that does nothing'
TabbedPanelItem:
text: 'tab3'
RstDocument:
text: '\\n'.join(("Hello world", "-----------", "You are in the third tab."))
RstDocument:
id: set3_content
text: '\\n'.join(("Hello world", "-----------", "You are in the third tab."))
# now categorize widgets inserted above in a specific header
TabbedPanelHeader:
text: 'Tab 2'
content: set2_content
TabbedPanelHeader:
text: 'Tab 3'
content: set3_content
""")
class Test(TabbedPanel):

View File

@ -5,25 +5,50 @@ from kivy.lang import Builder
from kivy.properties import StringProperty, ObjectProperty
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.spinner import SpinnerOption
from kivy.uix.popup import Popup
import os
Builder.load_string(
'''
#: import utils kivy
#: import os os
#: import font pygame.font
#: import Factory kivy.factory.Factory
<FntSpinnerOption>
fnt_name: font.match_font(self.text)
font_name: self.fnt_name if self.fnt_name else self.font_name
<Unicode_TextInput>
orientation: 'vertical'
txt_input: unicode_txt
spnr_fnt: fnt_spnr
BoxLayout:
size_hint: 1, .05
Spinner:
id: fnt_spnr
text: 'DroidSansMono'
fnt_name: font.match_font(self.text)
font_name: self.fnt_name if self.fnt_name else self.font_name
values: sorted(font.get_fonts())
option_cls: Factory.FntSpinnerOption
Spinner:
id: fntsz_spnr
text: '15'
values: map(str, map(sp, range(5,39)))
ScrollView:
size_hint: 1, .9
TextInput:
id: unicode_txt
background_color: [.5, .5, .5, 1]
foreground_color: .5, 1, .5, 1
background_color: .8811, .8811, .8811, 1
foreground_color: 0, 0, 0, 1
font_name: fnt_spnr.font_name
font_size: fntsz_spnr.text + 'sp'
text: root.unicode_string
size_hint: 1, None
height: 1364
height: 1494
on_font_name: self.height = (self.line_height + self.padding_y) * (len(self._lines)-1)
BoxLayout:
size_hint: 1, .05
Label:
@ -86,6 +111,8 @@ if _platform == 'linux' else '/system/fonts' if _platform == 'android' else os.p
(filechooser.path, filechooser.selection)
''')
class FntSpinnerOption(SpinnerOption):
pass
class LoadDialog(FloatLayout):
load = ObjectProperty(None)
@ -172,6 +199,9 @@ Yiddish: דער גיך ברוין פוקס דזשאַמפּס איבער
def load(self, _path, _fname):
self.txt_input.font_name = _fname[0]
_f_name = _fname[0][_fname[0].rfind(os.sep) + 1:]
self.spnr_fnt.text = _f_name[:_f_name.rfind('.')]
self._popup.dismiss()
def show_load(self):

View File

@ -28,7 +28,7 @@ __all__ = (
'kivy_config_fn', 'kivy_usermodules_dir',
)
__version__ = '1.4.1-dev'
__version__ = '1.4.2-dev'
import sys
import shutil
@ -201,7 +201,7 @@ for option in kivy_options:
if key in environ:
try:
if type(kivy_options[option]) in (list, tuple):
kivy_options[option] = (str(environ[key]), )
kivy_options[option] = environ[key].split(',')
else:
kivy_options[option] = environ[key].lower() in \
('true', '1', 'yes', 'yup')
@ -369,11 +369,15 @@ if not environ.get('KIVY_DOC_INCLUDE'):
Logger.info('Core: Kivy configuration saved.')
sys.exit(0)
# android hooks: force fullscreen and add android touch input provider
if platform() == 'android':
from kivy.config import Config
Config.set('graphics', 'fullscreen', 'auto')
Config.remove_section('input')
Config.add_section('input')
Config.set('input', 'androidtouch', 'android')
# configure all activated modules
from kivy.modules import Modules
Modules.configure()
# android hooks: force fullscreen and add android touch input provider
if platform() == 'android':
from kivy.config import Config
Config.set('graphics', 'fullscreen', 'auto')
Config.remove_section('input')
Config.add_section('input')
Config.set('input', 'androidtouch', 'android')

7
kivy/_event.pxd Normal file
View File

@ -0,0 +1,7 @@
cdef class EventDispatcher(object):
cdef dict __event_stack
cdef dict __properties
cdef dict __storage
cpdef dict properties(self)
cdef readonly int uid

View File

@ -19,7 +19,6 @@ from functools import partial
from kivy.weakmethod import WeakMethod
from kivy.properties cimport Property, ObjectProperty
cdef tuple forbidden_properties = ('touch_down', 'touch_move', 'touch_up')
cdef int widget_uid = 0
cdef dict cache_properties = {}
@ -29,18 +28,17 @@ cdef class EventDispatcher(object):
See the module docstring for usage.
'''
cdef dict __event_stack
cdef dict __properties
def __cinit__(self, *largs, **kwargs):
global widget_uid, cache_properties
cdef dict widget_dict = self.__dict__
cdef dict cp = cache_properties
cdef dict attrs_found
cdef list attrs
cdef Property attr
cdef str k
self.__event_stack = {}
self.__storage = {}
__cls__ = self.__class__
# XXX for the moment, we need to create a uniq id for properties.
@ -48,8 +46,7 @@ cdef class EventDispatcher(object):
# are longer than using a custom __uid. I hope we can figure out a way
# of doing that without require any python code. :)
widget_uid += 1
widget_dict['__uid'] = widget_uid
widget_dict['__storage'] = {}
self.uid = widget_uid
if __cls__ not in cp:
attrs_found = cp[__cls__] = {}
@ -58,7 +55,7 @@ cdef class EventDispatcher(object):
uattr = getattr(__cls__, k)
if not isinstance(uattr, Property):
continue
if k in forbidden_properties:
if k == 'touch_down' or k == 'touch_move' or k == 'touch_up':
raise Exception('The property <%s> have a forbidden name' % k)
attrs_found[k] = uattr
else:
@ -175,6 +172,7 @@ cdef class EventDispatcher(object):
print 'press on button', obj, 'with date:', value
'''
cdef Property prop
for key, value in kwargs.iteritems():
if key[:3] == 'on_':
if key not in self.__event_stack:
@ -183,13 +181,15 @@ cdef class EventDispatcher(object):
handler = WeakMethod(value)
self.__event_stack[key].append(handler)
else:
self.__properties[key].bind(self, value)
prop = self.__properties[key]
prop.bind(self, value)
def unbind(self, **kwargs):
'''Unbind properties from callback functions.
Same usage as :func:`bind`.
'''
cdef Property prop
for key, value in kwargs.iteritems():
if key[:3] == 'on_':
if key not in self.__event_stack:
@ -201,7 +201,8 @@ cdef class EventDispatcher(object):
self.__event_stack[key].remove(handler)
break
else:
self.__properties[key].unbind(self, value)
prop = self.__properties[key]
prop.unbind(self, value)
def dispatch(self, str event_type, *largs):
'''Dispatch an event across all the handler added in bind().
@ -224,11 +225,13 @@ cdef class EventDispatcher(object):
#
# Properties
#
def __proxy_setter(self, dstinstance, name, instance, value):
self.__properties[name].__set__(dstinstance, value)
def __proxy_setter(self, EventDispatcher dstinstance, name, instance, value):
cdef Property prop = self.__properties[name]
prop.set(dstinstance, value)
def __proxy_getter(self, dstinstance, name, instance):
return self.__properties[name].__get__(dstinstance)
def __proxy_getter(self, EventDispatcher dstinstance, name, instance):
cdef Property prop = self.__properties[name]
return prop.get(dstinstance)
def setter(self, name):
'''Return the setter of a property. Useful if you want to directly bind
@ -261,7 +264,7 @@ cdef class EventDispatcher(object):
'''
return self.__properties[name]
cpdef dict properties(self):
cpdef dict properties(EventDispatcher self):
'''Return all the properties in that class in a dictionnary of
key/property class. Can be used for introspection.
@ -270,7 +273,7 @@ cdef class EventDispatcher(object):
cdef dict ret, p
ret = {}
p = self.__properties
for x in self.__dict__['__storage'].keys():
for x in self.__storage:
ret[x] = p[x]
return ret

View File

@ -126,7 +126,7 @@ class Animation(EventDispatcher):
return self._transition
@property
def animated_animated_properties(self):
def animated_properties(self):
'''Return the properties used to animate
'''
return self._animated_properties
@ -231,7 +231,7 @@ class Animation(EventDispatcher):
# no more properties to animation ? kill the animation.
if not props['properties']:
self.stop(widget)
self.cancel(widget)
#
# Private

View File

@ -381,6 +381,7 @@ class App(EventDispatcher):
if clsname.endswith('App'):
clsname = clsname[:-3]
filename = join(kv_directory, '%s.kv' % clsname.lower())
Logger.debug('App: Loading kv <{0}>'.format(filename))
if not exists(filename):
Logger.debug('App: kv <%s> not found' % filename)
return False
@ -472,6 +473,7 @@ class App(EventDispatcher):
filename = self.get_application_config()
if filename is None:
return config
Logger.debug('App: Loading configuration <{0}>'.format(filename))
if exists(filename):
try:
config.read(filename)
@ -481,6 +483,8 @@ class App(EventDispatcher):
self.build_config(config)
pass
else:
Logger.debug('App: First configuration, create <{0}>'.format(
filename))
config.filename = filename
config.write()
return config
@ -542,6 +546,10 @@ class App(EventDispatcher):
runTouchApp()
self.dispatch('on_stop')
# Clear the window children
for child in window.children:
window.remove_widget(child)
def stop(self, *largs):
'''Stop the application.

Some files were not shown because too many files have changed in this diff Show More