mirror of https://github.com/kivy/kivy.git
Merge branch 'matham-focus-text4'
This commit is contained in:
commit
033d0b1f2d
|
@ -57,7 +57,7 @@ for class_name in CONTAINER_CLASSES:
|
|||
|
||||
|
||||
class KivyRenderTextInput(CodeInput):
|
||||
def _keyboard_on_key_down(self, window, keycode, text, modifiers):
|
||||
def keyboard_on_key_down(self, window, keycode, text, modifiers):
|
||||
is_osx = sys.platform == 'darwin'
|
||||
# Keycodes on OSX:
|
||||
ctrl, cmd = 64, 1024
|
||||
|
@ -70,7 +70,7 @@ class KivyRenderTextInput(CodeInput):
|
|||
self.catalog.change_kv(True)
|
||||
return
|
||||
|
||||
super(KivyRenderTextInput, self)._keyboard_on_key_down(
|
||||
super(KivyRenderTextInput, self).keyboard_on_key_down(
|
||||
window, keycode, text, modifiers)
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ from kivy.properties import ListProperty, ObjectProperty, AliasProperty, \
|
|||
NumericProperty, OptionProperty, StringProperty, BooleanProperty
|
||||
from kivy.utils import platform, reify
|
||||
from kivy.context import get_current_context
|
||||
from kivy.uix.behaviors import FocusBehavior
|
||||
|
||||
# late import
|
||||
VKeyboard = None
|
||||
|
@ -851,6 +852,7 @@ class WindowBase(EventDispatcher):
|
|||
self.dispatch('on_touch_move', me)
|
||||
elif etype == 'end':
|
||||
self.dispatch('on_touch_up', me)
|
||||
FocusBehavior._handle_post_on_touch_up(me)
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
'''Event called when a touch down event is initiated.
|
||||
|
|
|
@ -344,6 +344,7 @@ class WindowSDL(WindowBase):
|
|||
|
||||
elif action in ('keydown', 'keyup'):
|
||||
mod, key, scancode, kstr = args
|
||||
print key
|
||||
if mod in self._meta_keys:
|
||||
try:
|
||||
kstr = unichr(key)
|
||||
|
|
|
@ -37,10 +37,12 @@ import string
|
|||
# When we are generating documentation, Config doesn't exist
|
||||
_scroll_timeout = _scroll_distance = 0
|
||||
_is_desktop = False
|
||||
_keyboard_mode = 'system'
|
||||
if Config:
|
||||
_scroll_timeout = Config.getint('widgets', 'scroll_timeout')
|
||||
_scroll_distance = Config.getint('widgets', 'scroll_distance')
|
||||
_is_desktop = Config.getboolean('kivy', 'desktop')
|
||||
_keyboard_mode = Config.get('kivy', 'keyboard_mode')
|
||||
|
||||
|
||||
class ButtonBehavior(object):
|
||||
|
@ -492,11 +494,28 @@ class FocusBehavior(object):
|
|||
future version.
|
||||
'''
|
||||
|
||||
_win = None
|
||||
_focus_win = None
|
||||
_requested_keyboard = False
|
||||
_keyboard = ObjectProperty(None, allownone=True)
|
||||
_keyboards = {}
|
||||
|
||||
ignored_touch = []
|
||||
'''A list of touches that should not be used to defocus. After on_touch_up,
|
||||
every touch that is not in :attr:`ignored_touch` will defocus all the
|
||||
focused widgets, if, the config keyboard mode is not multi. Touches on
|
||||
focusable widgets that were used to focus are automatically added here.
|
||||
|
||||
Example usage:
|
||||
|
||||
class Unfocusable(Widget):
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
if self.collide_point(*touch.pos):
|
||||
FocusBehavior.ignored_touch.append(touch)
|
||||
|
||||
Notice that you need to access this as class, not instance variable.
|
||||
'''
|
||||
|
||||
def _set_keyboard(self, value):
|
||||
focused = self.focused
|
||||
keyboard = self._keyboard
|
||||
|
@ -535,6 +554,13 @@ class FocusBehavior(object):
|
|||
:attr:`keyboard` is a :class:`~kivy.properties.AliasProperty`, defaults to
|
||||
None.
|
||||
|
||||
.. note::
|
||||
|
||||
When Config's `keyboard_mode` is multi, each new touch is considered
|
||||
a touch by a different user and will focus (if clicked on a
|
||||
focusable) with a new keyboard. Already focused elements will not lose
|
||||
their focus (even if clicked on a unfocusable).
|
||||
|
||||
.. note:
|
||||
|
||||
If the keyboard property is set, that keyboard will be used when the
|
||||
|
@ -668,15 +694,52 @@ class FocusBehavior(object):
|
|||
defaults to `None`.
|
||||
'''
|
||||
|
||||
keyboard_mode = OptionProperty('auto', options=('auto', 'managed'))
|
||||
'''How the keyboard visibility should be managed (auto will have standard
|
||||
behaviour to show/hide on focus, managed requires setting keyboard_visible
|
||||
manually, or calling the helper functions ``show_keyboard()``
|
||||
and ``hide_keyboard()``.
|
||||
|
||||
:attr:`keyboard_mode` is an :class:`~kivy.properties.OptionsProperty` and
|
||||
defaults to 'auto'. Can be one of 'auto' or 'managed'.
|
||||
'''
|
||||
|
||||
input_type = OptionProperty('text', options=('text', 'number', 'url',
|
||||
'mail', 'datetime', 'tel',
|
||||
'address'))
|
||||
'''The kind of input keyboard to request.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
:attr:`input_type` is an :class:`~kivy.properties.OptionsProperty` and
|
||||
defaults to 'text'. Can be one of 'text', 'number', 'url', 'mail',
|
||||
'datetime', 'tel', 'address'.
|
||||
'''
|
||||
|
||||
unfocus_on_touch = BooleanProperty(_keyboard_mode not in
|
||||
('multi', 'systemandmulti'))
|
||||
'''Whether a instance should lose focus when clicked outside the instance.
|
||||
|
||||
When a user clicks on a widget that is focus aware and shares the same
|
||||
keyboard as the this widget (which in the case of only one keyboard, are
|
||||
all focus aware widgets), then as the other widgets gains focus, this
|
||||
widget loses focus. In addition to that, if this property is `True`,
|
||||
clicking on any widget other than this widget, will remove focus form this
|
||||
widget.
|
||||
|
||||
:attr:`unfocus_on_touch` is a :class:`~kivy.properties.BooleanProperty`,
|
||||
defaults to `False` if the `keyboard_mode` in :attr:`~kivy.config.Config`
|
||||
is `'multi'` or `'systemandmulti'`, otherwise it defaults to `True`.
|
||||
'''
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self._old_focus_next = None
|
||||
self._old_focus_previous = None
|
||||
super(FocusBehavior, self).__init__(**kwargs)
|
||||
|
||||
self._keyboard_mode = _keyboard_mode
|
||||
self.bind(focused=self._on_focused, disabled=self._on_focusable,
|
||||
is_focusable=self._on_focusable,
|
||||
# don't be at mercy of child calling super
|
||||
on_touch_down=self._focus_on_touch_down,
|
||||
focus_next=self._set_on_focus_next,
|
||||
focus_previous=self._set_on_focus_previous)
|
||||
|
||||
|
@ -685,23 +748,25 @@ class FocusBehavior(object):
|
|||
self.focused = False
|
||||
|
||||
def _on_focused(self, instance, value, *largs):
|
||||
if value:
|
||||
self._bind_keyboard()
|
||||
else:
|
||||
self._unbind_keyboard()
|
||||
if self.keyboard_mode == 'auto':
|
||||
if value:
|
||||
self._bind_keyboard()
|
||||
else:
|
||||
self._unbind_keyboard()
|
||||
|
||||
def _ensure_keyboard(self):
|
||||
if self._keyboard is None:
|
||||
win = self._win
|
||||
win = self._focus_win
|
||||
if not win:
|
||||
self._win = win = EventLoop.window
|
||||
self._focus_win = win = EventLoop.window
|
||||
if not win:
|
||||
Logger.warning('FocusBehavior: '
|
||||
'Cannot focus the element, unable to get root window')
|
||||
return
|
||||
self._requested_keyboard = True
|
||||
keyboard = self._keyboard =\
|
||||
win.request_keyboard(self._keyboard_released, self)
|
||||
win.request_keyboard(self._keyboard_released, self,
|
||||
input_type=self.input_type)
|
||||
keyboards = FocusBehavior._keyboards
|
||||
if keyboard not in keyboards:
|
||||
keyboards[keyboard] = None
|
||||
|
@ -738,12 +803,28 @@ class FocusBehavior(object):
|
|||
def _keyboard_released(self):
|
||||
self.focused = False
|
||||
|
||||
def _focus_on_touch_down(self, instance, touch):
|
||||
if not self.disabled and self.is_focusable and\
|
||||
self.collide_point(*touch.pos) and ('button' not in touch.profile
|
||||
or not touch.button.startswith('scroll')):
|
||||
def on_touch_down(self, touch):
|
||||
if not self.collide_point(*touch.pos):
|
||||
return
|
||||
if (not self.disabled and self.is_focusable and
|
||||
('button' not in touch.profile or
|
||||
not touch.button.startswith('scroll'))):
|
||||
self.focused = True
|
||||
return False
|
||||
FocusBehavior.ignored_touch.append(touch)
|
||||
return super(FocusBehavior, self).on_touch_down(touch)
|
||||
|
||||
@staticmethod
|
||||
def _handle_post_on_touch_up(touch):
|
||||
''' Called by window after each touch has finished.
|
||||
'''
|
||||
touches = FocusBehavior.ignored_touch
|
||||
if touch in touches:
|
||||
touches.remove(touch)
|
||||
return
|
||||
for focusable in FocusBehavior._keyboards.values():
|
||||
if focusable is None or not focusable.unfocus_on_touch:
|
||||
continue
|
||||
focusable.focused = False
|
||||
|
||||
def _get_focus_next(self, focus_dir):
|
||||
current = self
|
||||
|
@ -755,7 +836,7 @@ class FocusBehavior(object):
|
|||
current = getattr(current, focus_dir)
|
||||
if current is self or current is StopIteration:
|
||||
return None # make sure we don't loop forever
|
||||
if current.is_focusable:
|
||||
if current.is_focusable and not current.disabled:
|
||||
return current
|
||||
|
||||
# hit unfocusable, walk widget tree
|
||||
|
@ -769,7 +850,7 @@ class FocusBehavior(object):
|
|||
if isinstance(current, FocusBehavior):
|
||||
if current is self:
|
||||
return None
|
||||
if current.is_focusable:
|
||||
if current.is_focusable and not current.disabled:
|
||||
return current
|
||||
else:
|
||||
return None
|
||||
|
@ -823,6 +904,20 @@ class FocusBehavior(object):
|
|||
return True
|
||||
return False
|
||||
|
||||
def show_keyboard(self):
|
||||
'''
|
||||
Convenience function to show the keyboard in managed mode.
|
||||
'''
|
||||
if self.keyboard_mode == 'managed':
|
||||
self._bind_keyboard()
|
||||
|
||||
def hide_keyboard(self):
|
||||
'''
|
||||
Convenience function to hide the keyboard in managed mode.
|
||||
'''
|
||||
if self.keyboard_mode == 'managed':
|
||||
self._unbind_keyboard()
|
||||
|
||||
|
||||
class CompoundSelectionBehavior(object):
|
||||
'''Selection behavior implements the logic behind keyboard and touch
|
||||
|
|
|
@ -151,6 +151,7 @@ from kivy.compat import PY2
|
|||
from kivy.logger import Logger
|
||||
from kivy.metrics import inch
|
||||
from kivy.utils import boundary, platform
|
||||
from kivy.uix.behaviors import FocusBehavior
|
||||
|
||||
from kivy.core.text import Label
|
||||
from kivy.graphics import Color, Rectangle
|
||||
|
@ -221,6 +222,8 @@ class Selector(ButtonBehavior, Image):
|
|||
touch.push()
|
||||
touch.apply_transform_2d(self.to_widget)
|
||||
self._touch_diff = self.top - touch.y
|
||||
if self.collide_point(*touch.pos):
|
||||
FocusBehavior.ignored_touch.append(touch)
|
||||
return super(Selector, self).on_touch_down(touch)
|
||||
finally:
|
||||
touch.pop()
|
||||
|
@ -244,6 +247,11 @@ class TextInputCutCopyPaste(Bubble):
|
|||
super(TextInputCutCopyPaste, self).__init__(**kwargs)
|
||||
Clock.schedule_interval(self._check_parent, .5)
|
||||
|
||||
def on_touch_down(self, touch):
|
||||
if self.collide_point(*touch.pos):
|
||||
FocusBehavior.ignored_touch.append(touch)
|
||||
return super(TextInputCutCopyPaste, self).on_touch_down(touch)
|
||||
|
||||
def on_textinput(self, instance, value):
|
||||
global Clipboard
|
||||
if value and not Clipboard and not _is_desktop:
|
||||
|
@ -314,7 +322,7 @@ class TextInputCutCopyPaste(Bubble):
|
|||
anim.start(self)
|
||||
|
||||
|
||||
class TextInput(Widget):
|
||||
class TextInput(FocusBehavior, Widget):
|
||||
'''TextInput class. See module documentation for more information.
|
||||
|
||||
:Events:
|
||||
|
@ -346,6 +354,18 @@ class TextInput(Widget):
|
|||
on the next clock cycle using
|
||||
:meth:`~kivy.clock.ClockBase.schedule_once`.
|
||||
|
||||
.. note::
|
||||
:attr:`~kivy.uix.behaviors.FocusBehavior.keyboard_mode`,
|
||||
:meth:`~kivy.uix.behaviors.FocusBehavior.show_keyboard`,
|
||||
:meth:`~kivy.uix.behaviors.FocusBehavior.hide_keyboard`,
|
||||
and :attr:`~kivy.uix.behaviors.FocusBehavior.input_type`,
|
||||
have been removed from :class:`TextInput` since they are now inherited
|
||||
from :class:`~kivy.uix.behaviors.FocusBehavior`.
|
||||
|
||||
.. versionchanged:: 1.8.1
|
||||
:class:`TextInput` now inherits from
|
||||
:class:`~kivy.uix.behaviors.FocusBehavior`.
|
||||
|
||||
.. versionchanged:: 1.7.0
|
||||
`on_double_tap`, `on_triple_tap` and `on_quad_touch` events added.
|
||||
'''
|
||||
|
@ -354,6 +374,7 @@ class TextInput(Widget):
|
|||
'on_quad_touch')
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.is_focusable = kwargs.get('is_focusable', True)
|
||||
self._win = None
|
||||
self._cursor_blink_time = Clock.get_time()
|
||||
self._cursor = [0, 0]
|
||||
|
@ -375,7 +396,6 @@ class TextInput(Widget):
|
|||
self._hint_text_rects = []
|
||||
self._label_cached = None
|
||||
self._line_options = None
|
||||
self._keyboard = None
|
||||
self._keyboard_mode = Config.get('kivy', 'keyboard_mode')
|
||||
self._command_mode = False
|
||||
self._command = ''
|
||||
|
@ -402,6 +422,13 @@ class TextInput(Widget):
|
|||
self.bind(font_size=self._trigger_refresh_line_options,
|
||||
font_name=self._trigger_refresh_line_options)
|
||||
|
||||
def set_focused(instance, value):
|
||||
self.focused = value
|
||||
|
||||
def handle_readonly(instance, value):
|
||||
if value and (not _is_desktop or not self.allow_copy):
|
||||
self.is_focusable = False
|
||||
|
||||
self.bind(padding=self._update_text_options,
|
||||
tab_width=self._update_text_options,
|
||||
font_size=self._update_text_options,
|
||||
|
@ -409,7 +436,9 @@ class TextInput(Widget):
|
|||
size=self._update_text_options,
|
||||
password=self._update_text_options)
|
||||
|
||||
self.bind(pos=self._trigger_update_graphics)
|
||||
self.bind(pos=self._trigger_update_graphics, focus=set_focused,
|
||||
readonly=handle_readonly)
|
||||
handle_readonly(self, self.readonly)
|
||||
|
||||
self._trigger_position_handles = Clock.create_trigger(
|
||||
self._position_handles)
|
||||
|
@ -424,10 +453,6 @@ class TextInput(Widget):
|
|||
# when the gl context is reloaded, trigger the text rendering again.
|
||||
_textinput_list.append(ref(self, TextInput._reload_remove_observer))
|
||||
|
||||
def on_disabled(self, instance, value):
|
||||
if value:
|
||||
self.focus = False
|
||||
|
||||
def on_text_validate(self):
|
||||
pass
|
||||
|
||||
|
@ -961,14 +986,9 @@ class TextInput(Widget):
|
|||
|
||||
touch_pos = touch.pos
|
||||
if not self.collide_point(*touch_pos):
|
||||
if self._keyboard_mode == 'multi':
|
||||
if self.readonly:
|
||||
self.focus = False
|
||||
else:
|
||||
self.focus = False
|
||||
return False
|
||||
if not self.focus:
|
||||
self.focus = True
|
||||
if super(TextInput, self).on_touch_down(touch):
|
||||
return True
|
||||
|
||||
# Check for scroll wheel
|
||||
if 'button' in touch.profile and touch.button.startswith('scroll'):
|
||||
|
@ -1298,76 +1318,29 @@ class TextInput(Widget):
|
|||
if wr in _textinput_list:
|
||||
_textinput_list.remove(wr)
|
||||
|
||||
def _set_window(self, *largs):
|
||||
def on_focused(self, instance, value, *largs):
|
||||
self.focus = value
|
||||
|
||||
win = self._win
|
||||
if not win:
|
||||
self._win = win = EventLoop.window
|
||||
if not win:
|
||||
# we got argument, it could be the previous schedule
|
||||
# cancel focus.
|
||||
if len(largs):
|
||||
Logger.warning('Textinput: '
|
||||
'Cannot focus the element, unable to get '
|
||||
'root window')
|
||||
return
|
||||
else:
|
||||
#XXX where do `value` comes from?
|
||||
Clock.schedule_once(partial(self.on_focus, self, largs), 0)
|
||||
Logger.warning('Textinput: unable to get root window')
|
||||
return
|
||||
|
||||
def on_focus(self, instance, value, *largs):
|
||||
self._set_window(*largs)
|
||||
self.cancel_selection()
|
||||
self._hide_cut_copy_paste(win)
|
||||
|
||||
if value:
|
||||
if self.keyboard_mode != 'managed':
|
||||
self._bind_keyboard()
|
||||
if (not (self.readonly or self.disabled) or _is_desktop and
|
||||
self._keyboard_mode == 'system'):
|
||||
Clock.schedule_interval(self._do_blink_cursor, 1 / 2.)
|
||||
self._editable = True
|
||||
else:
|
||||
self._editable = False
|
||||
else:
|
||||
if self.keyboard_mode != 'managed':
|
||||
self._unbind_keyboard()
|
||||
|
||||
def _unbind_keyboard(self):
|
||||
self._set_window()
|
||||
win = self._win
|
||||
if self._keyboard:
|
||||
keyboard = self._keyboard
|
||||
keyboard.unbind(
|
||||
on_key_down=self._keyboard_on_key_down,
|
||||
on_key_up=self._keyboard_on_key_up)
|
||||
keyboard.release()
|
||||
self._keyboard = None
|
||||
|
||||
self.cancel_selection()
|
||||
Clock.unschedule(self._do_blink_cursor)
|
||||
self._hide_cut_copy_paste(win)
|
||||
self._hide_handles(win)
|
||||
self._win = None
|
||||
|
||||
def _bind_keyboard(self):
|
||||
self._set_window()
|
||||
win = self._win
|
||||
self._editable = editable = (
|
||||
not (self.readonly or self.disabled) or
|
||||
_is_desktop and self._keyboard_mode == 'system')
|
||||
|
||||
if not _is_desktop and not editable:
|
||||
return
|
||||
|
||||
keyboard = win.request_keyboard(
|
||||
self._keyboard_released, self, input_type=self.input_type)
|
||||
self._keyboard = keyboard
|
||||
if editable:
|
||||
keyboard.bind(
|
||||
on_key_down=self._keyboard_on_key_down,
|
||||
on_key_up=self._keyboard_on_key_up)
|
||||
Clock.schedule_interval(self._do_blink_cursor, 1 / 2.)
|
||||
else:
|
||||
# in non-editable mode, we still want shortcut (as copy)
|
||||
keyboard.bind(
|
||||
on_key_down=self._keyboard_on_key_down)
|
||||
|
||||
def on_readonly(self, instance, value):
|
||||
if not value:
|
||||
self.focus = False
|
||||
Clock.unschedule(self._do_blink_cursor)
|
||||
self._hide_handles(win)
|
||||
self._win = None
|
||||
|
||||
def _ensure_clipboard(self):
|
||||
global Clipboard
|
||||
|
@ -1414,12 +1387,6 @@ class TextInput(Widget):
|
|||
self.delete_selection()
|
||||
self.insert_text(data)
|
||||
|
||||
def _keyboard_released(self):
|
||||
# Callback called when the real keyboard is taken by someone else
|
||||
# called by the window if the keyboard is taken by somebody else
|
||||
# FIXME: handle virtual keyboard.
|
||||
self.focus = False
|
||||
|
||||
def _get_text_width(self, text, tab_width, _label_cached):
|
||||
# Return the width of a text, according to the current line options
|
||||
kw = self._get_line_options()
|
||||
|
@ -1962,7 +1929,7 @@ class TextInput(Widget):
|
|||
if self._selection:
|
||||
self._update_selection(True)
|
||||
|
||||
def _keyboard_on_key_down(self, window, keycode, text, modifiers):
|
||||
def keyboard_on_key_down(self, window, keycode, text, modifiers):
|
||||
# Keycodes on OSX:
|
||||
ctrl, cmd = 64, 1024
|
||||
key, key_str = keycode
|
||||
|
@ -1973,13 +1940,17 @@ class TextInput(Widget):
|
|||
_is_osx and modifiers == ['meta']))
|
||||
is_interesting_key = key in (list(self.interesting_keys.keys()) + [27])
|
||||
|
||||
if not self.write_tab and super(TextInput,
|
||||
self).keyboard_on_key_down(window, keycode, text, modifiers):
|
||||
return True
|
||||
|
||||
if not self._editable:
|
||||
# duplicated but faster testing for non-editable keys
|
||||
if text and not is_interesting_key:
|
||||
if is_shortcut and key == ord('c'):
|
||||
self.copy()
|
||||
elif key == 27:
|
||||
self.focus = False
|
||||
self.focused = False
|
||||
return True
|
||||
|
||||
if text and not is_interesting_key:
|
||||
|
@ -2060,7 +2031,7 @@ class TextInput(Widget):
|
|||
self._hide_handles(win)
|
||||
|
||||
if key == 27: # escape
|
||||
self.focus = False
|
||||
self.focused = False
|
||||
return True
|
||||
elif key == 9: # tab
|
||||
self.insert_text(u'\t')
|
||||
|
@ -2071,7 +2042,7 @@ class TextInput(Widget):
|
|||
key = (None, None, k, 1)
|
||||
self._key_down(key)
|
||||
|
||||
def _keyboard_on_key_up(self, window, keycode):
|
||||
def keyboard_on_key_up(self, window, keycode):
|
||||
key, key_str = keycode
|
||||
k = self.interesting_keys.get(key)
|
||||
if k:
|
||||
|
@ -2496,6 +2467,12 @@ class TextInput(Widget):
|
|||
show selection when TextInput is focused, you should delay
|
||||
(use Clock.schedule) the call to the functions for selecting
|
||||
text (select_all, select_text).
|
||||
|
||||
..versionchanged:: 1.8.1
|
||||
:class:`TextInput` now inherits from
|
||||
:class:`~kivy.uix.behaviors.FocusBehavior` and :attr:`focus` is now
|
||||
an alias for :attr:`focused`. Setting either one will also set the
|
||||
other.
|
||||
'''
|
||||
|
||||
def _get_text(self, encode=True):
|
||||
|
@ -2629,18 +2606,6 @@ class TextInput(Widget):
|
|||
defaults to 0.
|
||||
'''
|
||||
|
||||
input_type = OptionProperty('text', options=('text', 'number', 'url',
|
||||
'mail', 'datetime', 'tel',
|
||||
'address'))
|
||||
'''The kind of input, keyboard to request
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
|
||||
:attr:`input_type` is an :class:`~kivy.properties.OptionsProperty` and
|
||||
defaults to 'text'. Can be one of 'text', 'number', 'url', 'mail',
|
||||
'datetime', 'tel', 'address'.
|
||||
'''
|
||||
|
||||
input_filter = ObjectProperty(None, allownone=True)
|
||||
''' Filters the input according to the specified mode, if not None. If
|
||||
None, no filtering is applied.
|
||||
|
@ -2700,32 +2665,17 @@ class TextInput(Widget):
|
|||
if self._handle_right:
|
||||
self._handle_right.source = value
|
||||
|
||||
keyboard_mode = OptionProperty('auto', options=('auto', 'managed'))
|
||||
'''How the keyboard visibility should be managed (auto will have standard
|
||||
behaviour to show/hide on focus, managed requires setting keyboard_visible
|
||||
manually, or calling the helper functions ``show_keyboard()``
|
||||
and ``hide_keyboard()``.
|
||||
write_tab = BooleanProperty(True)
|
||||
'''Whether the tab key should move focus to the next widget or if it should
|
||||
enter a tab in the :class:`TextInput`. If `True` a tab will be written,
|
||||
otherwise, focus will move to the next widget.
|
||||
|
||||
.. versionadded:: 1.8.0
|
||||
.. versionadded:: 1.8.1
|
||||
|
||||
:attr:`keyboard_mode` is an :class:`~kivy.properties.OptionsProperty` and
|
||||
defaults to 'auto'. Can be one of 'auto' or 'managed'.
|
||||
:attr:`write_tab` is a :class:`~kivy.properties.BooleanProperty` and
|
||||
defaults to `True`.
|
||||
'''
|
||||
|
||||
def show_keyboard(self):
|
||||
"""
|
||||
Convenience function to show the keyboard in managed mode
|
||||
"""
|
||||
if self.keyboard_mode == "managed":
|
||||
self._bind_keyboard()
|
||||
|
||||
def hide_keyboard(self):
|
||||
"""
|
||||
Convenience function to hide the keyboard in managed mode
|
||||
"""
|
||||
if self.keyboard_mode == "managed":
|
||||
self._unbind_keyboard()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from kivy.app import App
|
||||
|
|
Loading…
Reference in New Issue