diff --git a/kivy/core/text/__init__.py b/kivy/core/text/__init__.py index e45493f04..fc3155c67 100644 --- a/kivy/core/text/__init__.py +++ b/kivy/core/text/__init__.py @@ -208,11 +208,11 @@ class LabelBase(object): if segment - margin > 5: segment -= margin - return '{0}...{1}'.format(text[:segment].strip(), + return u'{0}...{1}'.format(text[:segment].strip(), text[-segment:].strip()) else: segment = max_letters - 3 # length of '...' - return '{0}...'.format(text[:segment].strip()) + return u'{0}...'.format(text[:segment].strip()) def render(self, real=False): '''Return a tuple(width, height) to create the image diff --git a/kivy/graphics/context.pxd b/kivy/graphics/context.pxd index cbc8a2e4f..805e8f5e0 100644 --- a/kivy/graphics/context.pxd +++ b/kivy/graphics/context.pxd @@ -6,6 +6,7 @@ from kivy.graphics.fbo cimport Fbo cdef class Context: cdef list observers + cdef list observers_before cdef list l_texture cdef list l_canvas cdef list l_vbo diff --git a/kivy/graphics/context.pyx b/kivy/graphics/context.pyx index 1a841f413..3a82a8c33 100644 --- a/kivy/graphics/context.pyx +++ b/kivy/graphics/context.pyx @@ -33,6 +33,7 @@ cdef class Context: def __init__(self): self.observers = [] + self.observers_before = [] self.l_texture = [] self.l_canvas = [] self.l_vbo = [] @@ -96,23 +97,34 @@ cdef class Context: self.lr_fbo.append((fbo.buffer_id, fbo.depthbuffer_id)) self.trigger_gl_dealloc() - def add_reload_observer(self, callback): + def add_reload_observer(self, callback, before=False): '''Add a callback to be called after the whole graphics context have been reloaded. This is where you can reupload your custom data in GPU. :Parameters: `callback`: func(context) -> return None The first parameter will be the context itself - ''' - self.observers.append(WeakMethod(callback)) + `before`: boolean, default to False + If True, the callback will be executed before the whole + reloading processus. Use it if you want to clear your cache for + example. - def remove_reload_observer(self, callback): + .. versionchanged:: 1.4.0 + `before` parameter added. + ''' + if before: + self.observers_before.append(WeakMethod(callback)) + else: + self.observers.append(WeakMethod(callback)) + + def remove_reload_observer(self, callback, before=False): '''Remove a callback from the observer list, previously added by :func:`add_reload_observer`. ''' - for cb in self.observers[:]: + lst = self.observers_before if before else self.observers + for cb in lst[:]: if cb.is_dead() or cb() is callback: - self.observers.remove(cb) + lst.remove(cb) continue def reload(self): @@ -122,6 +134,14 @@ cdef class Context: cdef Shader shader cdef Canvas canvas + # call reload observers that want to do something after a whole gpu + # reloading. + for callback in self.observers_before[:]: + if callback.is_dead(): + self.observers_before.remove(callback) + continue + callback()(self) + image_objects = Cache._objects['kv.image'] Cache.remove('kv.image') Cache.remove('kv.shader') diff --git a/kivy/uix/scrollview.py b/kivy/uix/scrollview.py index 8a0e311e3..3f9d7502d 100644 --- a/kivy/uix/scrollview.py +++ b/kivy/uix/scrollview.py @@ -198,8 +198,8 @@ class ScrollView(StencilView): if widget is self._viewport: self._viewport = None - def _get_uid(self): - return 'sv.%d' % id(self) + def _get_uid(self, prefix='sv'): + return '{0}.{1}'.format(prefix, self.uid) def _change_touch_mode(self, *largs): if not self._touch: @@ -287,10 +287,11 @@ class ScrollView(StencilView): return False def on_touch_down(self, touch): + if not self.collide_point(*touch.pos): + touch.ud[self._get_uid('svavoid')] = True + return if self._touch: return super(ScrollView, self).on_touch_down(touch) - if not self.collide_point(*touch.pos): - return # support scrolling ! if self._viewport and 'button' in touch.profile and \ touch.button.startswith('scroll'): @@ -323,6 +324,8 @@ class ScrollView(StencilView): return True def on_touch_move(self, touch): + if self._get_uid('svavoid') in touch.ud: + return if self._touch is not touch: super(ScrollView, self).on_touch_move(touch) return self._get_uid() in touch.ud @@ -370,6 +373,10 @@ class ScrollView(StencilView): # never ungrabed, cause their on_touch_up will be never called. # base.py: the me.grab_list[:] => it's a copy, and we are already # iterate on it. + + if self._get_uid('svavoid') in touch.ud: + return + if 'button' in touch.profile and not touch.button.startswith('scroll'): self._scroll_y_mouse = self.scroll_y @@ -385,7 +392,7 @@ class ScrollView(StencilView): elif self.auto_scroll: self._do_animation(touch) else: - if self._touch is not touch: + if self._touch is not touch and self.uid not in touch.ud: super(ScrollView, self).on_touch_up(touch) # if we do mouse scrolling, always accept it diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 541349cf4..d1ce4dcdc 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -105,6 +105,8 @@ __all__ = ('TextInput', ) import sys +from os import environ +from weakref import ref from functools import partial from kivy.logger import Logger from kivy.utils import boundary @@ -126,6 +128,26 @@ FL_IS_NEWLINE = 0x01 # late binding Clipboard = None +# for reloading, we need to keep a list of textinput to retrigger the rendering +_textinput_list = [] + + +# register an observer to clear the textinput cache when OpenGL will reload +if 'KIVY_DOC' not in environ: + + def _textinput_clear_cache(*l): + Cache.remove('textinput.label') + for wr in _textinput_list[:]: + textinput = wr() + if textinput is None: + _textinput_list.remove(wr) + else: + textinput._trigger_refresh_text() + + from kivy.graphics.context import get_context + get_context().add_reload_observer(_textinput_clear_cache, True) + + class TextInputCutCopyPaste(Bubble): # Internal class used for showing the little bubble popup when @@ -224,6 +246,10 @@ class TextInput(Widget): self._trigger_refresh_line_options() self._trigger_refresh_text() + # when the gl context is reloaded, trigger the text rendering again. + _textinput_list.append(ref(self, TextInput._reload_remove_observer)) + + def on_text_validate(self): pass @@ -700,6 +726,13 @@ class TextInput(Widget): # # Private # + + @staticmethod + def _reload_remove_observer(wr): + # called when the textinput is deleted + if wr in _textinput_list: + _textinput_list.remove(wr) + def on_focus(self, instance, value, *largs): win = self._win if not win: @@ -1550,6 +1583,7 @@ class TextInput(Widget): 10. ''' + if __name__ == '__main__': from kivy.app import App from kivy.uix.boxlayout import BoxLayout