2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
Themes/Theming
|
|
|
|
==============
|
|
|
|
|
|
|
|
.. seealso::
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
`Material Design spec, Dynamic color <https://m3.material.io/styles/color/dynamic-color/overview>`_
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
Material App
|
|
|
|
------------
|
|
|
|
|
|
|
|
The main class of your application, which in `Kivy` inherits from the
|
|
|
|
:class:`~kivy.app.App` class, in `KivyMD` must inherit from the
|
|
|
|
:class:`~kivymd.app.MDApp` class. The :class:`~kivymd.app.MDApp` class has
|
|
|
|
properties that allow you to control application properties such as
|
|
|
|
:attr:`color/style/font` of interface elements and much more.
|
|
|
|
|
|
|
|
Control material properties
|
|
|
|
---------------------------
|
|
|
|
|
|
|
|
The main application class inherited from the :class:`~kivymd.app.MDApp` class
|
|
|
|
has the :attr:`~kivymd.app.MDApp.theme_cls` attribute, with which you control
|
|
|
|
the material properties of your application.
|
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
import os.path
|
|
|
|
from timeit import default_timer
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivy.app import App
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.logger import Logger
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivy.core.window import Window
|
|
|
|
from kivy.event import EventDispatcher
|
|
|
|
from kivy.properties import (
|
|
|
|
AliasProperty,
|
|
|
|
BooleanProperty,
|
|
|
|
DictProperty,
|
|
|
|
NumericProperty,
|
|
|
|
ObjectProperty,
|
|
|
|
OptionProperty,
|
|
|
|
StringProperty,
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy import platform
|
|
|
|
from kivy.utils import get_color_from_hex, rgba, hex_colormap
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.dynamic_color import DynamicColor
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivymd.font_definitions import theme_font_styles
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.material_resources import DEVICE_IOS
|
|
|
|
|
|
|
|
from materialyoucolor.utils.color_utils import argb_from_rgba_01
|
|
|
|
from materialyoucolor.dynamiccolor.material_dynamic_colors import (
|
|
|
|
MaterialDynamicColors,
|
|
|
|
)
|
|
|
|
from materialyoucolor.utils.platform_utils import SCHEMES, get_dynamic_scheme
|
|
|
|
from materialyoucolor.hct import Hct
|
|
|
|
from materialyoucolor.dislike.dislike_analyzer import DislikeAnalyzer
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class ThemeManager(EventDispatcher, DynamicColor):
|
|
|
|
primary_palette = OptionProperty(
|
|
|
|
None,
|
|
|
|
options=[name_color.capitalize() for name_color in hex_colormap.keys()],
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
The name of the color scheme that the application will use.
|
|
|
|
All major `material` components will have the color
|
|
|
|
of the specified color theme.
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
See :attr:`kivy.utils.hex_colormap` keys for available values.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
To change the color scheme of an application:
|
|
|
|
|
|
|
|
.. tabs::
|
|
|
|
|
|
|
|
.. tab:: Imperative python style with KV
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from kivy.lang import Builder
|
|
|
|
|
|
|
|
from kivymd.app import MDApp
|
|
|
|
|
|
|
|
KV = '''
|
|
|
|
MDScreen:
|
2024-09-15 17:57:02 +00:00
|
|
|
md_bg_color: self.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButton:
|
|
|
|
style: "elevated"
|
2024-09-15 12:12:16 +00:00
|
|
|
pos_hint: {"center_x": .5, "center_y": .5}
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
MDButtonIcon:
|
|
|
|
icon: "plus"
|
|
|
|
|
|
|
|
MDButtonText:
|
|
|
|
text: "Button"
|
2024-09-15 12:12:16 +00:00
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style = "Dark"
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.primary_palette = "Olive" # "Purple", "Red"
|
2024-09-15 12:12:16 +00:00
|
|
|
return Builder.load_string(KV)
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
|
|
|
|
|
|
|
.. tab:: Declarative python style
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from kivymd.app import MDApp
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.uix.button import MDButton, MDButtonIcon, MDButtonText
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivymd.uix.screen import MDScreen
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style = "Dark"
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.primary_palette = "Olive" # "Purple", "Red"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
return (
|
|
|
|
MDScreen(
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButton(
|
|
|
|
MDButtonIcon(
|
|
|
|
icon="plus",
|
|
|
|
),
|
|
|
|
MDButtonText(
|
|
|
|
text="Button",
|
|
|
|
),
|
|
|
|
style="elevated",
|
2024-09-15 12:12:16 +00:00
|
|
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
2024-09-15 17:57:02 +00:00
|
|
|
),
|
|
|
|
md_bg_color=self.theme_cls.backgroundColor,
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/primary-palette-m3.png
|
2024-09-15 12:12:16 +00:00
|
|
|
:align: center
|
|
|
|
|
|
|
|
:attr:`primary_palette` is an :class:`~kivy.properties.OptionProperty`
|
2024-09-15 17:57:02 +00:00
|
|
|
and defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
dynamic_color_quality = NumericProperty(1 if platform == "android" else 10)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
The quality of the generated color scheme from the system wallpaper.
|
|
|
|
It is equal to or higher than `1`, with `1` representing the maximum quality.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. warning::
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Remember that by increasing the quality value, you also increase the
|
|
|
|
generation time of the color scheme.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`dynamic_color_quality` is an :class:`~kivy.properties.NumericProperty`
|
|
|
|
and defaults to `10` if platform is not Android else `1`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
dynamic_color = BooleanProperty(False)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Enables or disables dynamic color.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. seealso::
|
|
|
|
|
|
|
|
`Material Design spec, Dynamic color <https://m3.material.io/styles/color/dynamic-color/overview>`_
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
To build the color scheme of your application from user wallpapers, you
|
|
|
|
must enable the `READ_EXTERNAL_STORAGE
|
|
|
|
<https://github.com/Android-for-Python/Android-for-Python-Users?tab=readme-ov-file#storage-permissions>`_
|
|
|
|
permission if your android version is below 8.1:
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. code-block:: python
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy import platform
|
|
|
|
from kivy.lang import Builder
|
|
|
|
from kivy.clock import Clock
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.app import MDApp
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
KV = '''
|
|
|
|
MDScreen:
|
|
|
|
md_bg_color: app.theme_cls.surfaceColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButton:
|
|
|
|
style: "elevated"
|
|
|
|
pos_hint: {"center_x": .5, "center_y": .5}
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButtonIcon:
|
|
|
|
icon: "plus"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButtonText:
|
|
|
|
text: "Elevated"
|
|
|
|
'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
return Builder.load_string(KV)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_resume(self, *args):
|
|
|
|
'''Updating the color scheme when the application resumes.'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.set_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def set_dynamic_color(self, *args) -> None:
|
|
|
|
'''
|
|
|
|
When sets the `dynamic_color` value, the self method will be
|
|
|
|
`called.theme_cls.set_colors()` which will generate a color
|
|
|
|
scheme from a custom wallpaper if `dynamic_color` is `True`.
|
2024-09-15 12:12:16 +00:00
|
|
|
'''
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.dynamic_color = True
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_start(self) -> None:
|
|
|
|
'''
|
|
|
|
It is fired at the start of the application and requests the
|
|
|
|
necessary permissions.
|
|
|
|
'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def callback(permission, results):
|
|
|
|
if all([res for res in results]):
|
|
|
|
Clock.schedule_once(self.set_dynamic_color)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
if platform == "android":
|
|
|
|
from android.permissions import Permission, request_permissions
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
permissions = [Permission.READ_EXTERNAL_STORAGE]
|
|
|
|
request_permissions(permissions, callback)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`dynamic_color` is an :class:`~kivy.properties.BooleanProperty`
|
|
|
|
and defaults to `False`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
dynamic_scheme_name = OptionProperty("TONAL_SPOT", options=SCHEMES.keys())
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Name of the dynamic scheme. Availabe schemes `TONAL_SPOT`, `SPRITZ`
|
|
|
|
`VIBRANT`, `EXPRESSIVE`, `FRUIT_SALAD`, `RAINBOW`, `MONOCHROME`, `FIDELITY`
|
|
|
|
and `CONTENT`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`dynamic_scheme_name` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'TONAL_SPOT'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
dynamic_scheme_contrast = NumericProperty(0.0)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
The contrast of the generated color scheme.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`dynamic_scheme_contrast` is an :class:`~kivy.properties.NumericProperty`
|
|
|
|
and defaults to `0.0`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
path_to_wallpaper = StringProperty()
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
The path to the image to set the color scheme. You can use this option
|
|
|
|
if you want to use dynamic color on platforms other than the Android
|
|
|
|
platform.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`path_to_wallpaper` is an :class:`~kivy.properties.StringProperty`
|
|
|
|
and defaults to `''`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_style_switch_animation = BooleanProperty(True)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
Animate app colors when switching app color scheme ('Dark/light').
|
|
|
|
|
|
|
|
.. versionadded:: 1.1.0
|
|
|
|
|
|
|
|
.. tabs::
|
|
|
|
|
|
|
|
.. tab:: Declarative KV style
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
from kivy.lang import Builder
|
|
|
|
|
|
|
|
from kivymd.app import MDApp
|
|
|
|
|
|
|
|
KV = '''
|
|
|
|
MDScreen:
|
2024-09-15 17:57:02 +00:00
|
|
|
md_bg_color: self.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
MDCard:
|
|
|
|
orientation: "vertical"
|
|
|
|
padding: 0, 0, 0 , "36dp"
|
|
|
|
size_hint: .5, .5
|
2024-09-15 17:57:02 +00:00
|
|
|
style: "elevated"
|
2024-09-15 12:12:16 +00:00
|
|
|
pos_hint: {"center_x": .5, "center_y": .5}
|
|
|
|
|
|
|
|
MDLabel:
|
|
|
|
text: "Theme style - {}".format(app.theme_cls.theme_style)
|
|
|
|
halign: "center"
|
|
|
|
valign: "center"
|
|
|
|
bold: True
|
2024-09-15 17:57:02 +00:00
|
|
|
font_style: "Display"
|
|
|
|
role: "small"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButton:
|
2024-09-15 12:12:16 +00:00
|
|
|
on_release: app.switch_theme_style()
|
|
|
|
pos_hint: {"center_x": .5}
|
2024-09-15 17:57:02 +00:00
|
|
|
|
|
|
|
MDButtonText:
|
|
|
|
text: "Set theme"
|
2024-09-15 12:12:16 +00:00
|
|
|
'''
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style_switch_animation = True
|
|
|
|
self.theme_cls.theme_style = "Dark"
|
|
|
|
self.theme_cls.primary_palette = "Orange"
|
|
|
|
return Builder.load_string(KV)
|
|
|
|
|
|
|
|
def switch_theme_style(self):
|
|
|
|
self.theme_cls.primary_palette = (
|
|
|
|
"Orange" if self.theme_cls.primary_palette == "Red" else "Red"
|
|
|
|
)
|
|
|
|
self.theme_cls.theme_style = (
|
|
|
|
"Dark" if self.theme_cls.theme_style == "Light" else "Light"
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
|
|
|
|
|
|
|
.. tab:: Declarative python style
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.clock import Clock
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivymd.app import MDApp
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.uix.button import MDButton, MDButtonText
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivymd.uix.card import MDCard
|
|
|
|
from kivymd.uix.label import MDLabel
|
|
|
|
from kivymd.uix.screen import MDScreen
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style_switch_animation = True
|
|
|
|
self.theme_cls.theme_style = "Dark"
|
|
|
|
self.theme_cls.primary_palette = "Orange"
|
|
|
|
return (
|
|
|
|
MDScreen(
|
|
|
|
MDCard(
|
|
|
|
MDLabel(
|
|
|
|
id="label",
|
2024-09-15 17:57:02 +00:00
|
|
|
text="Theme style - {}".format(
|
|
|
|
self.theme_cls.theme_style),
|
2024-09-15 12:12:16 +00:00
|
|
|
halign="center",
|
|
|
|
valign="center",
|
|
|
|
bold=True,
|
2024-09-15 17:57:02 +00:00
|
|
|
font_style="Display",
|
|
|
|
role="small",
|
2024-09-15 12:12:16 +00:00
|
|
|
),
|
2024-09-15 17:57:02 +00:00
|
|
|
MDButton(
|
|
|
|
MDButtonText(
|
|
|
|
text="Set theme",
|
|
|
|
),
|
2024-09-15 12:12:16 +00:00
|
|
|
on_release=self.switch_theme_style,
|
|
|
|
pos_hint={"center_x": 0.5},
|
|
|
|
),
|
|
|
|
id="card",
|
|
|
|
orientation="vertical",
|
|
|
|
padding=(0, 0, 0, "36dp"),
|
|
|
|
size_hint=(0.5, 0.5),
|
|
|
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
2024-09-15 17:57:02 +00:00
|
|
|
style="elevated",
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
)
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_start(self):
|
|
|
|
def on_start(*args):
|
|
|
|
self.root.md_bg_color = self.theme_cls.backgroundColor
|
|
|
|
|
|
|
|
Clock.schedule_once(on_start)
|
|
|
|
|
2024-09-15 12:12:16 +00:00
|
|
|
def switch_theme_style(self, *args):
|
|
|
|
self.theme_cls.primary_palette = (
|
|
|
|
"Orange" if self.theme_cls.primary_palette == "Red" else "Red"
|
|
|
|
)
|
|
|
|
self.theme_cls.theme_style = (
|
|
|
|
"Dark" if self.theme_cls.theme_style == "Light" else "Light"
|
|
|
|
)
|
2024-09-15 17:57:02 +00:00
|
|
|
self.root.get_ids().label.text = (
|
2024-09-15 12:12:16 +00:00
|
|
|
"Theme style - {}".format(self.theme_cls.theme_style)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/theme-style-switch-animation.gif
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
:attr:`theme_style_switch_animation` is an :class:`~kivy.properties.BooleanProperty`
|
2024-09-15 17:57:02 +00:00
|
|
|
and defaults to `True`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
theme_style_switch_animation_duration = NumericProperty(0.2)
|
|
|
|
"""
|
|
|
|
Duration of the animation of switching the color scheme of the application
|
|
|
|
("Dark/light").
|
|
|
|
|
|
|
|
.. versionadded:: 1.1.0
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style_switch_animation = True
|
|
|
|
self.theme_cls.theme_style_switch_animation_duration = 0.8
|
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/theme-style-switch-animation-duration.gif
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
:attr:`theme_style_switch_animation_duration` is an :class:`~kivy.properties.NumericProperty`
|
|
|
|
and defaults to `0.2`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
theme_style = OptionProperty("Light", options=["Light", "Dark"])
|
|
|
|
"""
|
|
|
|
App theme style.
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. code-block:: python
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.clock import Clock
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivymd.app import MDApp
|
|
|
|
from kivymd.uix.screen import MDScreen
|
|
|
|
from kivymd.uix.button import MDButton, MDButtonText
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.primary_palette = "Orange"
|
|
|
|
self.theme_cls.theme_style = "Light" # "Dark"
|
|
|
|
return MDScreen(
|
|
|
|
MDButton(
|
|
|
|
MDButtonText(
|
|
|
|
text="Hello, World",
|
|
|
|
),
|
|
|
|
style="outlined",
|
|
|
|
pos_hint={"center_x": 0.5, "center_y": 0.5},
|
|
|
|
)
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_start(self):
|
|
|
|
def on_start(*args):
|
|
|
|
self.root.md_bg_color = self.theme_cls.backgroundColor
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Clock.schedule_once(on_start)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/theme-style.png
|
|
|
|
:align: center
|
|
|
|
|
|
|
|
:attr:`theme_style` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Light'`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def _get_theme_style(self, opposite: bool) -> str:
|
|
|
|
if opposite:
|
|
|
|
return "Light" if self.theme_style == "Dark" else "Dark"
|
|
|
|
else:
|
|
|
|
return self.theme_style
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def _get_disabled_hint_text_color(self, opposite: bool = False) -> list:
|
2024-09-15 12:12:16 +00:00
|
|
|
theme_style = self._get_theme_style(opposite)
|
|
|
|
if theme_style == "Light":
|
2024-09-15 17:57:02 +00:00
|
|
|
color = get_color_from_hex("000000")
|
|
|
|
color[3] = 0.38
|
2024-09-15 12:12:16 +00:00
|
|
|
elif theme_style == "Dark":
|
2024-09-15 17:57:02 +00:00
|
|
|
color = get_color_from_hex("FFFFFF")
|
|
|
|
color[3] = 0.50
|
|
|
|
return color
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
disabled_hint_text_color = AliasProperty(
|
|
|
|
_get_disabled_hint_text_color, bind=["theme_style"]
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Color of the disabled text used in the :class:`~kivymd.uix.textfield.MDTextField`.
|
|
|
|
|
|
|
|
:attr:`disabled_hint_text_color`
|
|
|
|
is an :class:`~kivy.properties.AliasProperty` that returns the value
|
|
|
|
in ``rgba`` format for :attr:`disabled_hint_text_color`,
|
|
|
|
property is readonly.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def _determine_device_orientation(self, _, window_size) -> None:
|
|
|
|
if window_size[0] > window_size[1]:
|
|
|
|
self.device_orientation = "landscape"
|
|
|
|
elif window_size[1] >= window_size[0]:
|
|
|
|
self.device_orientation = "portrait"
|
|
|
|
|
|
|
|
device_orientation = StringProperty()
|
|
|
|
"""
|
|
|
|
Device orientation.
|
|
|
|
|
|
|
|
:attr:`device_orientation` is an :class:`~kivy.properties.StringProperty`
|
|
|
|
and defaults to `''`.
|
|
|
|
"""
|
|
|
|
|
|
|
|
# Font name, size (sp), always caps, letter spacing (sp).
|
|
|
|
font_styles = DictProperty(theme_font_styles)
|
|
|
|
"""
|
|
|
|
Data of default font styles.
|
|
|
|
|
|
|
|
Add custom font
|
|
|
|
---------------
|
|
|
|
|
|
|
|
.. tabs::
|
|
|
|
|
|
|
|
.. tab:: Declarative style with KV
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.core.text import LabelBase
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivy.lang import Builder
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.metrics import sp
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
from kivymd.app import MDApp
|
|
|
|
|
|
|
|
KV = '''
|
2024-09-15 17:57:02 +00:00
|
|
|
MDScreen:
|
|
|
|
md_bg_color: self.theme_cls.backgroundColor
|
|
|
|
|
|
|
|
MDLabel:
|
|
|
|
text: "MDLabel"
|
|
|
|
halign: "center"
|
|
|
|
font_style: "nasalization"
|
|
|
|
'''
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
|
|
|
self.theme_cls.theme_style = "Dark"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
LabelBase.register(
|
|
|
|
name="nasalization",
|
|
|
|
fn_regular="nasalization.ttf",
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.font_styles["nasalization"] = {
|
|
|
|
"large": {
|
|
|
|
"line-height": 1.64,
|
|
|
|
"font-name": "nasalization",
|
|
|
|
"font-size": sp(57),
|
|
|
|
},
|
|
|
|
"medium": {
|
|
|
|
"line-height": 1.52,
|
|
|
|
"font-name": "nasalization",
|
|
|
|
"font-size": sp(45),
|
|
|
|
},
|
|
|
|
"small": {
|
|
|
|
"line-height": 1.44,
|
|
|
|
"font-name": "nasalization",
|
|
|
|
"font-size": sp(36),
|
|
|
|
},
|
|
|
|
}
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
return Builder.load_string(KV)
|
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Example().run()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
.. tab:: Declarative python style
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
from kivy.core.text import LabelBase
|
|
|
|
from kivy.metrics import sp
|
|
|
|
|
|
|
|
from kivymd.uix.label import MDLabel
|
|
|
|
from kivymd.uix.screen import MDScreen
|
2024-09-15 12:12:16 +00:00
|
|
|
from kivymd.app import MDApp
|
|
|
|
|
|
|
|
|
|
|
|
class Example(MDApp):
|
|
|
|
def build(self):
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_cls.theme_style = "Dark"
|
|
|
|
|
|
|
|
LabelBase.register(
|
|
|
|
name="nasalization",
|
|
|
|
fn_regular="/Users/urijivanov/Projects/Dev/MyGithub/Articles/StarTest/data/font/nasalization-rg.ttf",
|
|
|
|
)
|
|
|
|
|
|
|
|
self.theme_cls.font_styles["nasalization"] = {
|
|
|
|
"large": {
|
|
|
|
"line-height": 1.64,
|
|
|
|
"font-name": "nasalization",
|
|
|
|
"font-size": sp(57),
|
|
|
|
},
|
|
|
|
"medium": {
|
|
|
|
"line-height": 1.52,
|
|
|
|
"font-name": "nasalization",
|
|
|
|
"font-size": sp(45),
|
|
|
|
},
|
|
|
|
"small": {
|
|
|
|
"line-height": 1.44,
|
|
|
|
"font-name": "nasalization",
|
|
|
|
"font-size": sp(36),
|
|
|
|
},
|
|
|
|
}
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
return (
|
2024-09-15 17:57:02 +00:00
|
|
|
MDScreen(
|
|
|
|
MDLabel(
|
|
|
|
text="JetBrainsMono",
|
|
|
|
halign="center",
|
|
|
|
font_style="nasalization",
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
Example().run()
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/custom-font-styles.png
|
2024-09-15 12:12:16 +00:00
|
|
|
:align: center
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`font_styles` is an :class:`~kivy.properties.DictProperty`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
on_colors = None
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
A Helper function called when colors are changed.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr: `on_colors` defaults to `None`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
_size_current_wallpaper = NumericProperty(0)
|
|
|
|
_dark_mode = lambda self : False if self.theme_style == "Light" else True
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def __init__(self, **kwargs):
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
self._determine_device_orientation(None, Window.size)
|
|
|
|
Window.bind(size=self._determine_device_orientation)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def set_colors(self, *args) -> None:
|
|
|
|
"""Fired methods for setting a new color scheme."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
if not self.dynamic_color:
|
|
|
|
if not self.primary_palette:
|
|
|
|
self._set_application_scheme()
|
|
|
|
else:
|
|
|
|
self._set_palette_color()
|
|
|
|
else:
|
|
|
|
system_scheme = get_dynamic_scheme(
|
|
|
|
dark_mode=self._dark_mode(),
|
|
|
|
contrast=self.dynamic_scheme_contrast,
|
|
|
|
dynamic_color_quality=self.dynamic_color_quality,
|
|
|
|
fallback_wallpaper_path=self.path_to_wallpaper,
|
|
|
|
fallback_scheme_name=self.dynamic_scheme_name,
|
|
|
|
message_logger=Logger.info,
|
|
|
|
logger_head="KivyMD"
|
|
|
|
)
|
|
|
|
if system_scheme:
|
|
|
|
self._set_color_names(system_scheme)
|
|
|
|
else:
|
|
|
|
self._set_application_scheme()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def update_theme_colors(self, *args) -> None:
|
|
|
|
"""Fired when the `theme_style` value changes."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
self.set_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_dynamic_scheme_name(self, *args):
|
|
|
|
self.set_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_dynamic_scheme_contrast(self, *args):
|
|
|
|
self.set_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def on_path_to_wallpaper(self, *args):
|
|
|
|
self.set_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def switch_theme(self) -> None:
|
|
|
|
"""Switches the theme from light to dark."""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
self.theme_style = "Dark" if self.theme_style == "Light" else "Light"
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def sync_theme_styles(self, *args) -> None:
|
|
|
|
# Syncs the values from self.font_styles to theme_font_styles
|
|
|
|
# this will ensure continuity when someone registers a new font_style.
|
|
|
|
for num, style in enumerate(theme_font_styles):
|
|
|
|
if style not in self.font_styles:
|
|
|
|
theme_font_styles.pop(num)
|
|
|
|
for style in self.font_styles.keys():
|
|
|
|
theme_font_styles.append(style)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def _set_application_scheme(
|
|
|
|
self,
|
|
|
|
color = "blue", # Google default
|
|
|
|
) -> None:
|
|
|
|
if not color:
|
|
|
|
color = "blue"
|
|
|
|
|
|
|
|
color = get_color_from_hex(hex_colormap[color.lower()])
|
|
|
|
color = Hct.from_int(argb_from_rgba_01(color))
|
|
|
|
color = DislikeAnalyzer.fix_if_disliked(color).to_int()
|
|
|
|
|
|
|
|
self._set_color_names(
|
|
|
|
SCHEMES[self.dynamic_scheme_name](
|
|
|
|
Hct.from_int(color),
|
|
|
|
self._dark_mode(),
|
|
|
|
self.dynamic_scheme_contrast,
|
|
|
|
)
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def _set_color_names(self, scheme) -> None:
|
|
|
|
for color_name in vars(MaterialDynamicColors).keys():
|
|
|
|
attr = getattr(MaterialDynamicColors, color_name)
|
|
|
|
if hasattr(attr, "get_hct"):
|
|
|
|
color_value = rgba(attr.get_hct(scheme).to_rgba())
|
|
|
|
exec(f"self.{color_name}Color = {color_value}")
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
self.disabledTextColor = self._get_disabled_hint_text_color()
|
|
|
|
if self.on_colors:
|
|
|
|
self.on_colors()
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
def _set_palette_color(self) -> None:
|
|
|
|
if not self.primary_palette:
|
|
|
|
self.primary_palette = "Blue"
|
|
|
|
self._set_application_scheme(self.primary_palette)
|
2024-09-15 12:12:16 +00:00
|
|
|
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
class ThemableBehavior(EventDispatcher):
|
|
|
|
theme_cls = ObjectProperty()
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Instance of :class:`~ThemeManager` class.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_cls` is an :class:`~kivy.properties.ObjectProperty`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
device_ios = BooleanProperty(DEVICE_IOS)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
``True`` if device is ``iOS``.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`device_ios` is an :class:`~kivy.properties.BooleanProperty`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_line_color = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Line color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_line_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_bg_color = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Background color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_bg_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_shadow_color = OptionProperty(
|
|
|
|
"Primary", options=["Primary", "Custom"]
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Elevation color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_shadow_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_shadow_offset = OptionProperty(
|
|
|
|
"Primary", options=["Primary", "Custom"]
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Elevation offset scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_shadow_offset` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_elevation_level = OptionProperty(
|
|
|
|
"Primary", options=["Primary", "Custom"]
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Elevation level scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_elevation_level` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_font_size = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Font size scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_font_size` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_width = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Widget width scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_width` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_height = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Widget width scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
|
|
|
|
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_height` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_line_height = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Line height scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
|
|
|
|
|
|
|
:attr:`theme_line_height` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_font_name = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Font name scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_font_name` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_shadow_softness = OptionProperty(
|
|
|
|
"Primary", options=["Primary", "Custom"]
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Elevation softness scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_shadow_softness` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_focus_color = OptionProperty("Primary", options=["Primary", "Custom"])
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Focus color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_focus_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_divider_color = OptionProperty(
|
|
|
|
"Primary", options=["Primary", "Custom"]
|
2024-09-15 12:12:16 +00:00
|
|
|
)
|
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Divider color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
.. versionadded:: 2.0.0
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_divider_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_text_color = OptionProperty(
|
|
|
|
"Primary",
|
|
|
|
options=[
|
|
|
|
"Primary",
|
|
|
|
"Secondary",
|
|
|
|
"Hint",
|
|
|
|
"Error",
|
|
|
|
"Custom",
|
|
|
|
],
|
|
|
|
)
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
2024-09-15 17:57:02 +00:00
|
|
|
Label color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Secondary'`, `'Hint'`, `'Error'`,
|
|
|
|
`'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_text_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
|
|
|
"""
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
theme_icon_color = OptionProperty(
|
|
|
|
"Primary",
|
|
|
|
options=[
|
|
|
|
"Primary",
|
|
|
|
"Secondary",
|
|
|
|
"Hint",
|
|
|
|
"Error",
|
|
|
|
"Custom",
|
|
|
|
],
|
|
|
|
)
|
|
|
|
"""
|
|
|
|
Label color scheme name.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
Available options are: `'Primary'`, `'Secondary'`, `'Hint'`, `'Error'`,
|
|
|
|
`'Custom'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
|
2024-09-15 17:57:02 +00:00
|
|
|
:attr:`theme_icon_color` is an :class:`~kivy.properties.OptionProperty`
|
|
|
|
and defaults to `'Primary'`.
|
2024-09-15 12:12:16 +00:00
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self, **kwargs):
|
2024-09-15 17:57:02 +00:00
|
|
|
if self.theme_cls is None:
|
2024-09-15 12:12:16 +00:00
|
|
|
try:
|
|
|
|
if not isinstance(
|
|
|
|
App.get_running_app().property("theme_cls", True),
|
|
|
|
ObjectProperty,
|
|
|
|
):
|
|
|
|
raise ValueError(
|
|
|
|
"KivyMD: App object must be inherited from "
|
|
|
|
"`kivymd.app.MDApp`"
|
|
|
|
)
|
|
|
|
except AttributeError:
|
|
|
|
raise ValueError(
|
|
|
|
"KivyMD: App object must be initialized before loading "
|
|
|
|
"root widget. See "
|
|
|
|
"https://github.com/kivymd/KivyMD/wiki/Modules-Material-App#exceptions"
|
|
|
|
)
|
|
|
|
self.theme_cls = App.get_running_app().theme_cls
|
|
|
|
|
|
|
|
super().__init__(**kwargs)
|
|
|
|
|
|
|
|
# Fix circular imports.
|
|
|
|
from kivymd.uix.behaviors import CommonElevationBehavior
|
|
|
|
from kivymd.uix.label import MDLabel
|
|
|
|
from kivymd.uix.textfield import MDTextField
|
|
|
|
|
|
|
|
self.common_elevation_behavior = CommonElevationBehavior
|
|
|
|
self.md_label = MDLabel
|
|
|
|
self.md_textfield = MDTextField
|
|
|
|
|
|
|
|
def remove_widget(self, widget) -> None:
|
|
|
|
if not hasattr(widget, "theme_cls"):
|
|
|
|
super().remove_widget(widget)
|
|
|
|
return
|
|
|
|
|
|
|
|
callbacks = widget.theme_cls.get_property_observers("theme_style")
|
|
|
|
|
|
|
|
for callback in callbacks:
|
|
|
|
try:
|
|
|
|
if hasattr(callback, "proxy") and hasattr(
|
|
|
|
callback.proxy, "theme_cls"
|
|
|
|
):
|
2024-09-15 17:57:02 +00:00
|
|
|
for property_name in ["theme_style", "primary_palette"]:
|
2024-09-15 12:12:16 +00:00
|
|
|
if widget == callback.proxy:
|
|
|
|
widget.theme_cls.unbind(
|
|
|
|
**{
|
|
|
|
property_name: getattr(
|
|
|
|
callback.proxy, callback.method_name
|
|
|
|
)
|
|
|
|
}
|
|
|
|
)
|
|
|
|
except ReferenceError:
|
|
|
|
pass
|
|
|
|
|
|
|
|
# Canceling a scheduled method call on_window_touch for MDLabel
|
|
|
|
# objects.
|
|
|
|
if (
|
|
|
|
issubclass(widget.__class__, self.md_label)
|
|
|
|
and self.md_label.allow_selection
|
|
|
|
):
|
|
|
|
Window.unbind(on_touch_down=widget.on_window_touch)
|
|
|
|
|
|
|
|
super().remove_widget(widget)
|