kvex.behaviors
Home of XThemed
and XFocusBehavior
.
1"""Home of `XThemed` and `XFocusBehavior`.""" 2 3from typing import Optional 4from . import kivy as kv 5from .util import schedule_once 6from .colors import SubTheme 7 8 9class XThemed(kv.EventDispatcher): 10 """A mixin for theming widgets. 11 12 Each widget is configured to follow a particular subtheme by setting 13 `XThemed.subtheme_name` (defaults to `kvex.app.XApp.subtheme_name`). 14 15 Theming can be disabled by passing False to `enable_theming` on initialization. 16 17 The `on_subtheme` event will be triggered whenever `kvex.app.XApp.theme` changes or 18 when `XThemed.subtheme_name` is set. 19 """ 20 21 def __init__( 22 self, 23 *args, 24 subtheme_name: Optional[str] = None, 25 enable_theming: bool = True, 26 **kwargs, 27 ): 28 """See class documentation for details. 29 30 Args: 31 subtheme_name: Set `XThemed.subtheme_name`. 32 enable_theming: Enable the `on_subtheme` event. 33 """ 34 super().__init__(*args, **kwargs) 35 self._subtheme_name = subtheme_name or kv.App.get_running_app().subtheme_name 36 self._subtheme = None 37 # The reason for using events instead of properties is due to initialization 38 # order: some use cases require that all classes in the MRO are initialized 39 # before an `on_subtheme` event is triggered. For this reason also, an initial 40 # `on_subtheme` event is scheduled for the next frame after initialization. 41 self._refresh_subtheme(trigger_event=False) 42 self.register_event_type("on_subtheme") 43 if enable_theming: 44 schedule_once(self.trigger_subtheme) 45 kv.App.get_running_app().bind(on_theme=self._refresh_subtheme) 46 47 def on_subtheme(self, subtheme: SubTheme): 48 """Called when the subtheme changes. 49 50 Use the `kvex.colors.SubTheme` object to configure relevant colors. 51 """ 52 pass 53 54 @property 55 def subtheme_name(self) -> str: 56 """Current subtheme name. See also: `kvex.colors.SUBTHEME_NAMES`.""" 57 return self._subtheme_name 58 59 @subtheme_name.setter 60 def subtheme_name(self, subtheme_name: str, /): 61 """Set `subtheme_name`.""" 62 self._subtheme_name = subtheme_name 63 self._refresh_subtheme() 64 65 @property 66 def subtheme(self) -> SubTheme: 67 """Current subtheme.""" 68 return self._subtheme 69 70 def trigger_subtheme(self, *args): 71 """Force the `on_subtheme` event to trigger.""" 72 self.dispatch("on_subtheme", self._subtheme) 73 74 def _refresh_subtheme(self, *args, trigger_event: bool = True): 75 old_subtheme = self._subtheme 76 new_subtheme = getattr(kv.App.get_running_app().theme, self._subtheme_name) 77 self._subtheme = new_subtheme 78 if new_subtheme is not old_subtheme and trigger_event: 79 self.dispatch("on_subtheme", new_subtheme) 80 81 82class XFocusBehavior(kv.FocusBehavior): 83 """Like Kivy's `FocusBehavior` with option to disable defocusing on escape key.""" 84 85 escape_unfocuses = kv.BooleanProperty(False) 86 """Enables defocusing when pressing escape. Defaults to False.""" 87 88 def keyboard_on_key_up(self, w, key_pair): 89 """Overrides base method to manually defocus on escape.""" 90 keycode, key = key_pair 91 if self.escape_unfocuses and key == "escape": 92 self.focus = False 93 return True 94 return False 95 96 97__all__ = ( 98 "XThemed", 99 "XFocusBehavior", 100)
class
XThemed(kivy._event.EventDispatcher):
10class XThemed(kv.EventDispatcher): 11 """A mixin for theming widgets. 12 13 Each widget is configured to follow a particular subtheme by setting 14 `XThemed.subtheme_name` (defaults to `kvex.app.XApp.subtheme_name`). 15 16 Theming can be disabled by passing False to `enable_theming` on initialization. 17 18 The `on_subtheme` event will be triggered whenever `kvex.app.XApp.theme` changes or 19 when `XThemed.subtheme_name` is set. 20 """ 21 22 def __init__( 23 self, 24 *args, 25 subtheme_name: Optional[str] = None, 26 enable_theming: bool = True, 27 **kwargs, 28 ): 29 """See class documentation for details. 30 31 Args: 32 subtheme_name: Set `XThemed.subtheme_name`. 33 enable_theming: Enable the `on_subtheme` event. 34 """ 35 super().__init__(*args, **kwargs) 36 self._subtheme_name = subtheme_name or kv.App.get_running_app().subtheme_name 37 self._subtheme = None 38 # The reason for using events instead of properties is due to initialization 39 # order: some use cases require that all classes in the MRO are initialized 40 # before an `on_subtheme` event is triggered. For this reason also, an initial 41 # `on_subtheme` event is scheduled for the next frame after initialization. 42 self._refresh_subtheme(trigger_event=False) 43 self.register_event_type("on_subtheme") 44 if enable_theming: 45 schedule_once(self.trigger_subtheme) 46 kv.App.get_running_app().bind(on_theme=self._refresh_subtheme) 47 48 def on_subtheme(self, subtheme: SubTheme): 49 """Called when the subtheme changes. 50 51 Use the `kvex.colors.SubTheme` object to configure relevant colors. 52 """ 53 pass 54 55 @property 56 def subtheme_name(self) -> str: 57 """Current subtheme name. See also: `kvex.colors.SUBTHEME_NAMES`.""" 58 return self._subtheme_name 59 60 @subtheme_name.setter 61 def subtheme_name(self, subtheme_name: str, /): 62 """Set `subtheme_name`.""" 63 self._subtheme_name = subtheme_name 64 self._refresh_subtheme() 65 66 @property 67 def subtheme(self) -> SubTheme: 68 """Current subtheme.""" 69 return self._subtheme 70 71 def trigger_subtheme(self, *args): 72 """Force the `on_subtheme` event to trigger.""" 73 self.dispatch("on_subtheme", self._subtheme) 74 75 def _refresh_subtheme(self, *args, trigger_event: bool = True): 76 old_subtheme = self._subtheme 77 new_subtheme = getattr(kv.App.get_running_app().theme, self._subtheme_name) 78 self._subtheme = new_subtheme 79 if new_subtheme is not old_subtheme and trigger_event: 80 self.dispatch("on_subtheme", new_subtheme)
A mixin for theming widgets.
Each widget is configured to follow a particular subtheme by setting
XThemed.subtheme_name
(defaults to kvex.app.XApp.subtheme_name
).
Theming can be disabled by passing False to enable_theming
on initialization.
The on_subtheme
event will be triggered whenever kvex.app.XApp.theme
changes or
when XThemed.subtheme_name
is set.
XThemed( *args, subtheme_name: Optional[str] = None, enable_theming: bool = True, **kwargs)
22 def __init__( 23 self, 24 *args, 25 subtheme_name: Optional[str] = None, 26 enable_theming: bool = True, 27 **kwargs, 28 ): 29 """See class documentation for details. 30 31 Args: 32 subtheme_name: Set `XThemed.subtheme_name`. 33 enable_theming: Enable the `on_subtheme` event. 34 """ 35 super().__init__(*args, **kwargs) 36 self._subtheme_name = subtheme_name or kv.App.get_running_app().subtheme_name 37 self._subtheme = None 38 # The reason for using events instead of properties is due to initialization 39 # order: some use cases require that all classes in the MRO are initialized 40 # before an `on_subtheme` event is triggered. For this reason also, an initial 41 # `on_subtheme` event is scheduled for the next frame after initialization. 42 self._refresh_subtheme(trigger_event=False) 43 self.register_event_type("on_subtheme") 44 if enable_theming: 45 schedule_once(self.trigger_subtheme) 46 kv.App.get_running_app().bind(on_theme=self._refresh_subtheme)
See class documentation for details.
Arguments:
- subtheme_name: Set
XThemed.subtheme_name
. - enable_theming: Enable the
on_subtheme
event.
48 def on_subtheme(self, subtheme: SubTheme): 49 """Called when the subtheme changes. 50 51 Use the `kvex.colors.SubTheme` object to configure relevant colors. 52 """ 53 pass
Called when the subtheme changes.
Use the kvex.colors.SubTheme
object to configure relevant colors.
def
trigger_subtheme(self, *args):
71 def trigger_subtheme(self, *args): 72 """Force the `on_subtheme` event to trigger.""" 73 self.dispatch("on_subtheme", self._subtheme)
Force the on_subtheme
event to trigger.
Inherited Members
- kivy._event.EventDispatcher
- register_event_type
- unregister_event_types
- unregister_event_type
- is_event_type
- bind
- unbind
- fbind
- funbind
- unbind_uid
- get_property_observers
- events
- dispatch
- dispatch_generic
- dispatch_children
- setter
- getter
- property
- properties
- create_property
- apply_property
- proxy_ref
class
XFocusBehavior(kivy.uix.behaviors.focus.FocusBehavior):
83class XFocusBehavior(kv.FocusBehavior): 84 """Like Kivy's `FocusBehavior` with option to disable defocusing on escape key.""" 85 86 escape_unfocuses = kv.BooleanProperty(False) 87 """Enables defocusing when pressing escape. Defaults to False.""" 88 89 def keyboard_on_key_up(self, w, key_pair): 90 """Overrides base method to manually defocus on escape.""" 91 keycode, key = key_pair 92 if self.escape_unfocuses and key == "escape": 93 self.focus = False 94 return True 95 return False
Like Kivy's FocusBehavior
with option to disable defocusing on escape key.
def
keyboard_on_key_up(self, w, key_pair):
89 def keyboard_on_key_up(self, w, key_pair): 90 """Overrides base method to manually defocus on escape.""" 91 keycode, key = key_pair 92 if self.escape_unfocuses and key == "escape": 93 self.focus = False 94 return True 95 return False
Overrides base method to manually defocus on escape.
Inherited Members
- kivy.uix.behaviors.focus.FocusBehavior
- FocusBehavior
- ignored_touch
- keyboard
- is_focusable
- focus
- focused
- keyboard_suggestions
- focus_next
- focus_previous
- keyboard_mode
- input_type
- unfocus_on_touch
- keyboard_on_textinput
- on_touch_down
- get_focus_next
- get_focus_previous
- keyboard_on_key_down
- show_keyboard
- hide_keyboard