Merge branch 'master' of ssh://github.com/kivy/kivy
Please enter a commit message to explain why this merge is necessary,
|
@ -31,6 +31,7 @@ kivy/core/window/sdl.c
|
|||
python
|
||||
python.exe
|
||||
.idea
|
||||
dist
|
||||
|
||||
MANIFEST
|
||||
|
||||
|
@ -47,3 +48,11 @@ kivy/lib/vidcore_lite/bcm.c
|
|||
kivy/lib/vidcore_lite/bcm.h
|
||||
|
||||
kivy/lib/vidcore_lite/egl.c
|
||||
|
||||
# PyDev
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Virtualenv
|
||||
venv
|
||||
|
||||
|
|
|
@ -204,18 +204,153 @@ Mageia 1 onwards
|
|||
# pip install --upgrade cython
|
||||
# pip install pygments
|
||||
|
||||
*Installation*
|
||||
==============
|
||||
|
||||
*Installation in a Virtual Environment with System Site Packages*
|
||||
=================================================================
|
||||
|
||||
This is a recommended compromise between installing Kivy and its dependencies
|
||||
system wide and installing as much as possible into a virtual environment.
|
||||
|
||||
|
||||
Ubuntu 12.04 with Python 2.7
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
If you're installing Kivy for the first time, do::
|
||||
|
||||
$ sudo easy_install kivy
|
||||
Install System-wide Dependencies
|
||||
--------------------------------
|
||||
|
||||
If you already installed kivy before, you can upgrade it with::
|
||||
Note that these commands will remove any pre-existing versions of
|
||||
python-virtualenv and replace it with the current version. It will also remove
|
||||
cython, numpy, and pygame installed from your Linux distro's repository and
|
||||
replace them with current versions from pip or the pygame Mercurial repository.
|
||||
|
||||
$ sudo easy_install --upgrade kivy
|
||||
::
|
||||
|
||||
# Install necessary system packages
|
||||
sudo apt-get install -y build-essential mercurial git python2.7 \
|
||||
python-setuptools python-dev ffmpeg libsdl-image1.2-dev \
|
||||
libsdl-mixer1.2-dev libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev \
|
||||
libportmidi-dev libswscale-dev libavformat-dev libavcodec-dev zlib1g-dev
|
||||
|
||||
# Bootstrap a current Python environment
|
||||
sudo apt-get remove --purge -y python-virtualenv python-pip
|
||||
sudo easy_install-2.7 -U pip
|
||||
sudo pip2.7 install -U virtualenv
|
||||
|
||||
# Install current version of Cython
|
||||
sudo apt-get remove --purge -y cython
|
||||
sudo pip2.7 install -U cython
|
||||
|
||||
# Install other PyGame dependencies
|
||||
sudo apt-get remove --purge -y python-numpy
|
||||
sudo pip2.7 install -U numpy
|
||||
|
||||
# Install PyGame
|
||||
sudo apt-get remove --purge python-pygame
|
||||
hg clone https://bitbucket.org/pygame/pygame
|
||||
cd pygame
|
||||
python2.7 setup.py build
|
||||
sudo python2.7 setup.py install
|
||||
cd ..
|
||||
sudo rm -rf pygame
|
||||
|
||||
|
||||
Create a Kivy Virtualenv
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
# Create a vitualenv
|
||||
rm -rf venv
|
||||
virtualenv -p python2.7 --system-site-packages venv
|
||||
|
||||
# Install stable version of Kivy into the virtualenv
|
||||
venv/bin/pip install kivy
|
||||
# For the development version of Kivy, use the following command instead
|
||||
# venv/bin/pip install git+https://github.com/kivy/kivy.git@master
|
||||
|
||||
# Install development version of buildozer into the virtualenv
|
||||
venv/bin/pip install git+https://github.com/kivy/buildozer.git@master
|
||||
|
||||
# Install development version of plyer into the virtualenv
|
||||
venv/bin/pip install git+https://github.com/kivy/plyer.git@master
|
||||
|
||||
# Install a couple of dependencies for KivyCatalog
|
||||
venv/bin/pip install -U pygments docutils
|
||||
|
||||
|
||||
Ubuntu 12.04 with Python 3.3
|
||||
----------------------------
|
||||
|
||||
|
||||
Install System-wide Dependencies
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Note that these commands will remove any pre-existing versions of
|
||||
python-virtualenv and replace it with the current version. It will also remove
|
||||
cython, numpy, and pygame installed from your Linux distro's repository and
|
||||
replace them with current versions from pip or the pygame Mercurial repository.
|
||||
|
||||
::
|
||||
|
||||
# Bootstrap Python3.3
|
||||
sudo apt-get install python-software-properties
|
||||
sudo add-apt-repository ppa:fkrull/deadsnakes
|
||||
sudo apt-get update
|
||||
|
||||
# Install necessary system packages
|
||||
sudo apt-get install -y build-essential mercurial git python3.3 \
|
||||
python3.3-dev ffmpeg libsdl-image1.2-dev libsdl-mixer1.2-dev \
|
||||
libsdl-ttf2.0-dev libsmpeg-dev libsdl1.2-dev libportmidi-dev \
|
||||
libswscale-dev libavformat-dev libavcodec-dev zlib1g-dev
|
||||
|
||||
# Bootstrap current setuptools
|
||||
wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py -O - | sudo python3.3
|
||||
|
||||
# Bootstrap a current Python environment
|
||||
sudo apt-get remove --purge -y python-virtualenv python-pip
|
||||
sudo easy_install-3.3 -U pip
|
||||
sudo pip3.3 install -U virtualenv
|
||||
|
||||
# Install current version of Cython
|
||||
sudo apt-get remove --purge -y cython
|
||||
sudo pip3.3 install -U cython
|
||||
|
||||
# Install other PyGame dependencies
|
||||
sudo apt-get remove --purge -y python-numpy
|
||||
sudo pip3.3 install -U numpy
|
||||
|
||||
# Install PyGame
|
||||
hg clone https://bitbucket.org/pygame/pygame
|
||||
cd pygame
|
||||
python3.3 setup.py build
|
||||
sudo python3.3 setup.py install
|
||||
cd ..
|
||||
sudo rm -rf pygame
|
||||
|
||||
|
||||
Create a Kivy Virtualenv
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
::
|
||||
|
||||
# Create a vitualenv
|
||||
rm -rf venv
|
||||
virtualenv -p python3.3 --system-site-packages venv
|
||||
|
||||
# Install stable version of Kivy into the virtualenv
|
||||
venv/bin/pip install kivy
|
||||
# For the development version of Kivy, use the following command instead
|
||||
# venv/bin/pip install git+https://github.com/kivy/kivy.git@master
|
||||
|
||||
# Install development version of buildozer into the virtualenv
|
||||
#venv/bin/pip install git+https://github.com/kivy/buildozer.git@master
|
||||
|
||||
# Install development version of plyer into the virtualenv
|
||||
venv/bin/pip install git+https://github.com/kivy/plyer.git@master
|
||||
|
||||
# Install a couple of dependencies for KivyCatalog
|
||||
venv/bin/pip install -U pygments docutils
|
||||
|
||||
|
||||
.. _linux-run-app:
|
||||
|
|
|
@ -97,6 +97,7 @@ void main() {
|
|||
}
|
||||
'''
|
||||
|
||||
|
||||
class ShaderWidget(FloatLayout):
|
||||
|
||||
# property to set the source code for fragment shader
|
||||
|
@ -132,7 +133,7 @@ class ShaderWidget(FloatLayout):
|
|||
|
||||
def update_glsl(self, *largs):
|
||||
self.canvas['time'] = Clock.get_boottime()
|
||||
self.canvas['resolution'] = map(float, self.size)
|
||||
self.canvas['resolution'] = [float(v) for v in self.size]
|
||||
|
||||
def on_fs(self, instance, value):
|
||||
# set the fragment shader to our source code
|
||||
|
@ -191,6 +192,7 @@ class ShaderTreeApp(App):
|
|||
# shader
|
||||
btn = Button(text='Change fragment shader', size_hint=(1, None),
|
||||
height=50)
|
||||
|
||||
def change(*largs):
|
||||
sw.fs = available_shaders[self.shader_index]
|
||||
self.shader_index = (self.shader_index + 1) % len(available_shaders)
|
||||
|
|
|
@ -19,7 +19,7 @@ PageLayout:
|
|||
|
||||
Button:
|
||||
text: 'test'
|
||||
on_press: print "test"
|
||||
on_press: print("test")
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
|
@ -51,7 +51,7 @@ PageLayout:
|
|||
source: 'http://kivy.org/slides/kivyandroid-thumb.jpg'
|
||||
Button:
|
||||
text: 'test'
|
||||
on_press: print "test last page"
|
||||
on_press: print("test last page")
|
||||
AsyncImage:
|
||||
source: 'http://kivy.org/slides/kivypictures-thumb.jpg'
|
||||
Widget
|
||||
|
|
|
@ -182,7 +182,7 @@ class ImageLoaderBase(object):
|
|||
imagedata = self._data[count]
|
||||
imagedata.source = '{}{}|{}'.format(
|
||||
'zip|' if self.filename.endswith('.zip') else '',
|
||||
self._nocache, uid)
|
||||
self._nocache, uid)
|
||||
texture = Texture.create_from_data(
|
||||
imagedata, mipmap=self._mipmap)
|
||||
if not self._nocache:
|
||||
|
|
|
@ -91,6 +91,10 @@ cdef extern from "CoreGraphics/CGColorSpace.h":
|
|||
CGColorSpaceRef CGColorSpaceCreateDeviceRGB()
|
||||
void CGColorSpaceRelease(CGColorSpaceRef cs)
|
||||
|
||||
cdef extern from "CoreGraphics/CGAffineTransform.h":
|
||||
ctypedef void *CGAffineTransform
|
||||
CGAffineTransform CGAffineTransformMake(float a, float b, float c, float d, float tx, float ty)
|
||||
|
||||
cdef extern from "CoreGraphics/CGContext.h":
|
||||
ctypedef void *CGContextRef
|
||||
void CGContextRelease(CGContextRef c)
|
||||
|
@ -98,6 +102,7 @@ cdef extern from "CoreGraphics/CGContext.h":
|
|||
int kCGBlendModeCopy
|
||||
int kCGBlendModeNormal
|
||||
void CGContextSetBlendMode(CGContextRef, int)
|
||||
void CGContextConcatCTM(CGContextRef fc, CGAffineTransform matrix)
|
||||
|
||||
cdef extern from "CoreGraphics/CGBitmapContext.h":
|
||||
CGImageRef CGBitmapContextCreateImage(CGColorSpaceRef)
|
||||
|
@ -181,11 +186,11 @@ def load_image_data(bytes _url):
|
|||
|
||||
return (width, height, 'rgba', r_data)
|
||||
|
||||
def save_image_rgba(filename, width, height, data):
|
||||
def save_image_rgba(filename, width, height, data, flipped):
|
||||
# compatibility, could be removed i guess
|
||||
save_image(filename, width, height, 'rgba', data)
|
||||
save_image(filename, width, height, 'rgba', data, flipped)
|
||||
|
||||
def save_image(filename, width, height, fmt, data):
|
||||
def save_image(filename, width, height, fmt, data, flipped):
|
||||
# save a RGBA string into filename using CoreGraphics
|
||||
|
||||
# FIXME only png output are accepted.
|
||||
|
@ -232,12 +237,39 @@ def save_image(filename, width, height, fmt, data):
|
|||
cdef CGImageDestinationRef dest = CGImageDestinationCreateWithURL(url,
|
||||
ctype, 1, NULL)
|
||||
|
||||
# release everything
|
||||
CGImageDestinationAddImage(dest, cgImage, NULL)
|
||||
# copy the image into a transformed context
|
||||
cdef CGContextRef flippedContext
|
||||
cdef CGImageRef newImageRef
|
||||
|
||||
if flipped:
|
||||
flippedContext = CGBitmapContextCreate(
|
||||
NULL, width, height,
|
||||
8, # bitsPerComponent
|
||||
fmt_length * width, # bytesPerRow
|
||||
colorSpace,
|
||||
kCGImageAlphaNoneSkipLast)
|
||||
|
||||
CGContextConcatCTM(flippedContext, CGAffineTransformMake(1.0, 0.0,
|
||||
0.0, -1.0,
|
||||
0.0, height))
|
||||
|
||||
CGContextDrawImage(flippedContext,
|
||||
CGRectMake(0, 0, width, height),
|
||||
cgImage)
|
||||
|
||||
newImageRef = CGBitmapContextCreateImage(flippedContext)
|
||||
CGImageDestinationAddImage(dest, newImageRef, NULL)
|
||||
CGImageDestinationFinalize(dest)
|
||||
CFRelease(newImageRef)
|
||||
CFRelease(flippedContext)
|
||||
else:
|
||||
CGImageDestinationAddImage(dest, cgImage, NULL)
|
||||
CGImageDestinationFinalize(dest)
|
||||
|
||||
#Release everything
|
||||
CFRelease(cgImage)
|
||||
CFRelease(bitmapContext)
|
||||
CFRelease(colorSpace)
|
||||
CGImageDestinationFinalize(dest)
|
||||
free(pixels)
|
||||
|
||||
class ImageLoaderImageIO(ImageLoaderBase):
|
||||
|
@ -267,8 +299,8 @@ class ImageLoaderImageIO(ImageLoaderBase):
|
|||
return True
|
||||
|
||||
@staticmethod
|
||||
def save(filename, width, height, fmt, pixels):
|
||||
save_image(filename, width, height, fmt, pixels)
|
||||
def save(filename, width, height, fmt, pixels, flipped=False):
|
||||
save_image(filename, width, height, fmt, pixels, flipped)
|
||||
return True
|
||||
|
||||
# register
|
||||
|
|
|
@ -795,10 +795,11 @@ class WindowBase(EventDispatcher):
|
|||
self.close()
|
||||
return True
|
||||
if Config:
|
||||
on_keyboard.exit_on_escape = Config.get('kivy', 'exit_on_escape')
|
||||
on_keyboard.exit_on_escape = Config.getboolean('kivy', 'exit_on_escape')
|
||||
|
||||
def __exit(section, name, value):
|
||||
WindowBase.on_keyboard.exit_on_escape = value
|
||||
WindowBase.__dict__['on_keyboard'].exit_on_escape = \
|
||||
Config.getboolean('kivy', 'exit_on_escape')
|
||||
|
||||
Config.add_callback(__exit, 'kivy', 'exit_on_escape')
|
||||
|
||||
|
|
Before Width: | Height: | Size: 71 KiB After Width: | Height: | Size: 71 KiB |
|
@ -37,6 +37,7 @@ cdef class Texture:
|
|||
cdef void allocate(self)
|
||||
|
||||
cpdef flip_vertical(self)
|
||||
cpdef flip_horizontal(self)
|
||||
cpdef get_region(self, x, y, width, height)
|
||||
cpdef bind(self)
|
||||
|
||||
|
|
|
@ -731,6 +731,16 @@ cdef class Texture:
|
|||
self._uvh = -self._uvh
|
||||
self.update_tex_coords()
|
||||
|
||||
cpdef flip_horizontal(self):
|
||||
'''Flip tex_coords for horizontal display.
|
||||
|
||||
.. versionadded:: 1.8.1
|
||||
|
||||
'''
|
||||
self._uvx += self._uvw
|
||||
self._uvw = -self._uvw
|
||||
self.update_tex_coords()
|
||||
|
||||
cpdef get_region(self, x, y, width, height):
|
||||
'''Return a part of the texture defined by the rectangular arguments
|
||||
(x, y, width, height). Returns a :class:`TextureRegion` instance.'''
|
||||
|
|
|
@ -26,9 +26,9 @@ class FileChooserUnicodeTestCase(unittest.TestCase):
|
|||
|
||||
# this will test creating unicode and bytes filesnames
|
||||
ufiles = [u'कीवीtestu',
|
||||
u'कीवीtestu' + unicode_char(0xFFFF),
|
||||
u'कीवीtestu' + unicode_char(0xFFFF - 1),
|
||||
u'कीवीtestu' + unicode_char(0xFF)]
|
||||
u'कीवीtestu' + unicode_char(0xEEEE),
|
||||
u'कीवीtestu' + unicode_char(0xEEEE - 1),
|
||||
u'कीवीtestu' + unicode_char(0xEE)]
|
||||
# don't use non-ascii directly because that will test source file
|
||||
# text conversion, not path issues :)
|
||||
bfiles = [b'\xc3\xa0\xc2\xa4\xe2\x80\xa2\xc3\xa0\xc2\xa5\xe2\x82\xac\
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
{ "match": ".*?:$",
|
||||
"name": "support.function.kivy" },
|
||||
{ "name": "entity.name.section.kivy",
|
||||
"match": "(.*?):" },
|
||||
"match": "(.*?):$" },
|
||||
{ "include": "source.python" }
|
||||
],
|
||||
"uuid": "49cecc44-5094-48ec-a876-91f597e8bf81"
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
</dict>
|
||||
<dict>
|
||||
<key>match</key>
|
||||
<string>(.*?):</string>
|
||||
<string>(.*?):$</string>
|
||||
<key>name</key>
|
||||
<string>entity.name.section.kivy</string>
|
||||
</dict>
|
||||
|
|
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.5 KiB |
|
@ -284,8 +284,8 @@ the cls or template.
|
|||
|
||||
.. note::
|
||||
|
||||
Only the ListItemLabel, ListItemButton or custom classes like them, and
|
||||
neither the bare Label nor Button classes, are to be used in the listview
|
||||
Only the ListItemLabel, ListItemButton or custom classes like them (and
|
||||
not the simple Label or Button classes) are to be used in the listview
|
||||
system.
|
||||
|
||||
.. warning::
|
||||
|
@ -449,12 +449,12 @@ custom class you have defined and registered with the system.
|
|||
An args_converter needs to be constructed that goes along with such a kv
|
||||
template. For example, to use the kv template above::
|
||||
|
||||
list_item_args_converter = \
|
||||
list_item_args_converter = \\
|
||||
lambda row_index, rec: {'text': rec['text'],
|
||||
'is_selected': rec['is_selected'],
|
||||
'size_hint_y': None,
|
||||
'height': 25}
|
||||
integers_dict = \
|
||||
integers_dict = \\
|
||||
{ str(i): {'text': str(i), 'is_selected': False} for i in range(100)}
|
||||
|
||||
dict_adapter = DictAdapter(sorted_keys=[str(i) for i in range(100)],
|
||||
|
|
|
@ -851,6 +851,11 @@ class Settings(BoxLayout):
|
|||
:Events:
|
||||
`on_config_change`: ConfigParser instance, section, key, value
|
||||
Fired when section/key/value of a ConfigParser changes.
|
||||
|
||||
.. warning:
|
||||
|
||||
value will be str/unicode type, regardless of the setting
|
||||
type (numeric, boolean, etc)
|
||||
`on_close`
|
||||
Fired by the default panel when the Close button is pressed.
|
||||
|
||||
|
|
|
@ -374,9 +374,16 @@ class TextInput(Widget):
|
|||
|
||||
self.bind(pos=self._trigger_update_graphics)
|
||||
|
||||
self._trigger_position_handles = Clock.create_trigger(
|
||||
self._position_handles)
|
||||
self._trigger_show_handles = Clock.create_trigger(
|
||||
self._show_handles, .05)
|
||||
self._trigger_refresh_line_options()
|
||||
self._trigger_refresh_text()
|
||||
|
||||
self.bind(pos=self._trigger_position_handles,
|
||||
size=self._trigger_position_handles)
|
||||
|
||||
# when the gl context is reloaded, trigger the text rendering again.
|
||||
_textinput_list.append(ref(self, TextInput._reload_remove_observer))
|
||||
|
||||
|
@ -1009,19 +1016,25 @@ class TextInput(Widget):
|
|||
on_release=self._handle_released)
|
||||
if not self._handle_middle.parent and self.text:
|
||||
self._win.add_widget(handle_middle)
|
||||
self._position_handles('middle')
|
||||
self._position_handles(mode='middle')
|
||||
return True
|
||||
|
||||
def _handle_pressed(self, instance):
|
||||
self._hide_cut_copy_paste()
|
||||
sf, st = self._selection_from, self.selection_to
|
||||
if sf > st:
|
||||
self._selection_from , self._selection_to = st, sf
|
||||
|
||||
def _handle_released(self, instance):
|
||||
if self.selection_to != self.selection_from:
|
||||
self._update_selection()
|
||||
self._show_cut_copy_paste(
|
||||
(instance.x + ((1 if instance is self._handle_left else - 1)
|
||||
* self._bubble.width / 2) if self._bubble else 0,
|
||||
instance.y + self.line_height), self._win)
|
||||
sf, st = self._selection_from, self.selection_to
|
||||
if sf == st:
|
||||
return
|
||||
|
||||
self._update_selection()
|
||||
self._show_cut_copy_paste(
|
||||
(instance.x + ((1 if instance is self._handle_left else - 1)
|
||||
* self._bubble.width / 2) if self._bubble else 0,
|
||||
instance.y + self.line_height), self._win)
|
||||
|
||||
def _handle_move(self, instance, touch):
|
||||
if touch.grab_current != instance:
|
||||
|
@ -1031,51 +1044,65 @@ class TextInput(Widget):
|
|||
handle_left = self._handle_left
|
||||
handle_middle = self._handle_middle
|
||||
|
||||
x, y = self.to_widget(*touch.pos)
|
||||
cursor = get_cursor(
|
||||
touch.x, touch.y + instance._touch_diff + (self.line_height / 2))
|
||||
x,
|
||||
y + instance._touch_diff + (self.line_height / 2))
|
||||
|
||||
if instance != touch.grab_current:
|
||||
return
|
||||
|
||||
if instance == handle_middle:
|
||||
self.cursor = cursor
|
||||
self._position_handles('middle')
|
||||
self._position_handles(mode='middle')
|
||||
return
|
||||
|
||||
ci = self.cursor_index(cursor=cursor)
|
||||
sf, st = self._selection_from, self.selection_to
|
||||
|
||||
if instance == handle_left:
|
||||
self._selection_from = self.cursor_index(cursor=cursor)
|
||||
self._selection_from = ci
|
||||
elif instance == handle_right:
|
||||
self._selection_to = self.cursor_index(cursor=cursor)
|
||||
self._selection_to = ci
|
||||
self._trigger_update_graphics()
|
||||
Clock.schedule_once(lambda dt: self._position_handles())
|
||||
self._trigger_position_handles()
|
||||
|
||||
def _position_handles(self, *args, **kwargs):
|
||||
if not self.text:
|
||||
return
|
||||
mode = kwargs.get('mode', 'both')
|
||||
|
||||
def _position_handles(self, mode='both'):
|
||||
group = self.canvas.get_group('selection')
|
||||
lh = self.line_height
|
||||
to_win = self.to_window
|
||||
|
||||
if mode[0] == 'm':
|
||||
handle_middle = self._handle_middle
|
||||
handle_middle = self._handle_middle
|
||||
if handle_middle:
|
||||
hp_mid = self.cursor_pos
|
||||
pos = self.to_window(*hp_mid)
|
||||
pos = to_win(*hp_mid)
|
||||
handle_middle.x = pos[0] - handle_middle.width / 2
|
||||
handle_middle.top = pos[1] - lh
|
||||
if mode[0] == 'm':
|
||||
return
|
||||
|
||||
group = self.canvas.get_group('selection')
|
||||
if not group:
|
||||
return
|
||||
self._win.remove_widget(self._handle_middle)
|
||||
|
||||
if mode[0] != 'm':
|
||||
handle_left = self._handle_left
|
||||
hp_left = group[2].pos
|
||||
handle_left.pos = self.to_window(*hp_left)
|
||||
handle_left.x -= handle_left.width
|
||||
handle_left.y -= handle_left.height
|
||||
handle_left = self._handle_left
|
||||
if not handle_left:
|
||||
return
|
||||
hp_left = group[2].pos
|
||||
handle_left.pos = to_win(*hp_left)
|
||||
handle_left.x -= handle_left.width
|
||||
handle_left.y -= handle_left.height
|
||||
|
||||
#if mode[0] in ('b', 'r'):
|
||||
handle_right = self._handle_right
|
||||
last_rect = group[-1]
|
||||
hp_right = last_rect.pos[0], last_rect.pos[1]
|
||||
handle_right.pos = self.to_window(*hp_right)
|
||||
handle_right.x += last_rect.size[0]
|
||||
handle_right.y -= handle_right.height
|
||||
handle_right = self._handle_right
|
||||
last_rect = group[-1]
|
||||
hp_right = last_rect.pos[0], last_rect.pos[1]
|
||||
x, y = to_win(*hp_right)
|
||||
handle_right.x = x + last_rect.size[0]
|
||||
handle_right.y = y - handle_right.height
|
||||
|
||||
def _hide_handles(self, win=None):
|
||||
win = win or self._win
|
||||
|
@ -1095,10 +1122,11 @@ class TextInput(Widget):
|
|||
anim.bind(on_complete=lambda *args: win.remove_widget(bubble))
|
||||
anim.start(bubble)
|
||||
|
||||
def _show_handles(self, win):
|
||||
if not self.use_handles:
|
||||
def _show_handles(self, dt):
|
||||
if not self.use_handles or not self.text:
|
||||
return
|
||||
|
||||
win = self._win
|
||||
if not win:
|
||||
self._set_window()
|
||||
win = self._win
|
||||
|
@ -1121,12 +1149,13 @@ class TextInput(Widget):
|
|||
on_touch_move=self._handle_move,
|
||||
on_release=self._handle_released)
|
||||
else:
|
||||
win.remove_widget(self._handle_left)
|
||||
win.remove_widget(self._handle_right)
|
||||
if self._handle_left.parent:
|
||||
self._position_handles()
|
||||
return
|
||||
if not self.parent:
|
||||
return
|
||||
|
||||
Clock.schedule_once(lambda dt: self._position_handles())
|
||||
self._trigger_position_handles()
|
||||
if self.selection_from != self.selection_to:
|
||||
self._handle_left.opacity = self._handle_right.opacity = 0
|
||||
win.add_widget(self._handle_left)
|
||||
|
@ -1221,7 +1250,7 @@ class TextInput(Widget):
|
|||
return
|
||||
else:
|
||||
#XXX where do `value` comes from?
|
||||
Clock.schedule_once(partial(self.on_focus, self, value), 0)
|
||||
Clock.schedule_once(partial(self.on_focus, self, largs), 0)
|
||||
return
|
||||
|
||||
def on_focus(self, instance, value, *largs):
|
||||
|
@ -1681,6 +1710,7 @@ class TextInput(Widget):
|
|||
padding_left, padding_right, x,
|
||||
canvas_add, selection_color)
|
||||
y -= dy
|
||||
self._position_handles('both')
|
||||
|
||||
def _draw_selection(self, *largs):
|
||||
pos, size, line_num, (s1c, s1r), (s2c, s2r),\
|
||||
|
@ -2375,8 +2405,8 @@ class TextInput(Widget):
|
|||
'''
|
||||
|
||||
def on_selection_text(self, instance, value):
|
||||
if value:
|
||||
self._show_handles(self._win)
|
||||
if value and self.use_handles:
|
||||
self._trigger_show_handles()
|
||||
|
||||
focus = BooleanProperty(False)
|
||||
'''If focus is True, the keyboard will be requested and you can start
|
||||
|
|