diff --git a/kivy/tests/test_uix_textinput.py b/kivy/tests/test_uix_textinput.py index b56cf4d8c..fb92808bb 100644 --- a/kivy/tests/test_uix_textinput.py +++ b/kivy/tests/test_uix_textinput.py @@ -5,6 +5,7 @@ uix.textinput tests import unittest +from kivy.tests.common import GraphicUnitTest from kivy.uix.textinput import TextInput @@ -34,3 +35,48 @@ class TextInputTest(unittest.TestCase): # If so Secondvery... should start from the 7th line pos_S = self.test_txt.index('S') self.assertEquals(instance.get_cursor_from_index(pos_S), (0, 6)) + + +class TextInputGraphicTest(GraphicUnitTest): + def test_text_validate(self): + ti = TextInput(multiline=False) + ti.focus = True + + self.render(ti) + self.assertFalse(ti.multiline) + self.assertTrue(ti.focus) + self.assertTrue(ti.text_validate_unfocus) + + ti.validate_test = None + + ti.bind(on_text_validate=lambda *_: setattr( + ti, 'validate_test', True + )) + ti._key_down( + ( + None, # displayed_str + None, # internal_str + 'enter', # internal_action + 1 # scale + ), + repeat=False + ) + self.assertTrue(ti.validate_test) + self.assertFalse(ti.focus) + + ti.validate_test = None + ti.text_validate_unfocus = False + ti.focus = True + self.assertTrue(ti.focus) + + ti._key_down( + (None, None, 'enter', 1), + repeat=False + ) + self.assertTrue(ti.validate_test) + self.assertTrue(ti.focus) + + +if __name__ == '__main__': + import unittest + unittest.main() diff --git a/kivy/uix/textinput.py b/kivy/uix/textinput.py index 6cf713223..c25b77500 100644 --- a/kivy/uix/textinput.py +++ b/kivy/uix/textinput.py @@ -30,7 +30,7 @@ To create a multiline :class:`TextInput` (the 'enter' key adds a new line):: To create a singleline :class:`TextInput`, set the :class:`TextInput.multiline` property to False (the 'enter' key will defocus the TextInput and emit an -'on_text_validate' event):: +:meth:`TextInput.on_text_validate` event):: def on_enter(instance, value): print('User pressed enter in', instance) @@ -705,7 +705,6 @@ class TextInput(FocusBehavior, Widget): elif mode == 'float': if not re.match(self._insert_float_pat, new_text): return - self._set_line_text(cr, new_text) wrap = (self._get_text_width( @@ -2291,7 +2290,8 @@ class TextInput(FocusBehavior, Widget): self.insert_text(u'\n') else: self.dispatch('on_text_validate') - self.focus = False + if self.text_validate_unfocus: + self.focus = False elif internal_action == 'escape': self.focus = False if internal_action != 'escape': @@ -2482,6 +2482,18 @@ class TextInput(FocusBehavior, Widget): defaults to False. ''' + text_validate_unfocus = BooleanProperty(True) + '''If True, the :meth:`TextInput.on_text_validate` event will unfocus the + widget, therefore make it stop listening to the keyboard. When disabled, + the :meth:`TextInput.on_text_validate` event can be fired multiple times + as the result of TextInput keeping the focus enabled. + + .. versionadded:: 1.10.1 + + :attr:`text_validate_unfocus` is + a :class:`~kivy.properties.BooleanProperty` and defaults to True. + ''' + multiline = BooleanProperty(True) '''If True, the widget will be able show multiple lines of text. If False, the "enter" keypress will defocus the textinput instead of adding a new