Updated build system for Kivy 2.2.1

This commit is contained in:
Mark Qvist 2023-07-10 02:49:58 +02:00
parent 23e6b6e0c6
commit 67a8f61af8
126 changed files with 9967 additions and 4279 deletions

View file

@ -18,32 +18,58 @@ Class :class:`MDLabel` inherited from the :class:`~kivy.uix.label.Label` class
but for :class:`MDLabel` the ``text_size`` parameter is ``(self.width, None)``
and default is positioned on the left:
.. code-block:: python
.. tabs::
from kivy.lang import Builder
.. tab:: Declarative KV style
from kivymd.app import MDApp
.. code-block:: python
KV = '''
MDScreen:
from kivy.lang import Builder
MDBoxLayout:
orientation: "vertical"
from kivymd.app import MDApp
MDTopAppBar:
title: "MDLabel"
KV = '''
MDScreen:
MDLabel:
text: "MDLabel"
'''
MDLabel:
text: "MDLabel"
'''
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
class Test(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV)
Test().run()
Test().run()
.. tab:: Declarative Python style
.. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.screen import MDScreen
from kivymd.uix.label import MDLabel
class Test(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return (
MDScreen(
MDLabel(
text="MDLabel"
)
)
)
Test().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-label-to-left.png
:align: center
@ -74,20 +100,16 @@ and default is positioned on the left:
from kivymd.uix.label import MDLabel
KV = '''
MDScreen:
MDBoxLayout:
id: box
orientation: "vertical"
MDTopAppBar:
title: "MDLabel"
MDBoxLayout:
orientation: "vertical"
'''
class Test(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
screen = Builder.load_string(KV)
# Names of standard color themes.
for name_theme in [
"Primary",
@ -96,7 +118,7 @@ and default is positioned on the left:
"Error",
"ContrastParentBackground",
]:
screen.ids.box.add_widget(
screen.add_widget(
MDLabel(
text=name_theme,
halign="center",
@ -121,7 +143,7 @@ in the ``text_color`` parameter:
text: "Custom color"
halign: "center"
theme_text_color: "Custom"
text_color: 0, 0, 1, 1
text_color: "blue"
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-label-custom-color.png
:align: center
@ -138,26 +160,20 @@ parameter:
from kivymd.uix.label import MDLabel
from kivymd.font_definitions import theme_font_styles
KV = '''
MDScreen:
MDScrollView:
MDBoxLayout:
orientation: "vertical"
MDTopAppBar:
title: "MDLabel"
ScrollView:
MDList:
id: box
MDList:
id: box
spacing: "8dp"
'''
class Test(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
screen = Builder.load_string(KV)
# Names of standard font styles.
for name_style in theme_font_styles[:-1]:
screen.ids.box.add_widget(
@ -165,6 +181,7 @@ parameter:
text=f"{name_style} style",
halign="center",
font_style=name_style,
adaptive_height=True,
)
)
return screen
@ -172,7 +189,273 @@ parameter:
Test().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-label-font-style.gif
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-label-font-style.png
:align: center
Highlighting and copying labels
===============================
You can highlight labels by double tap on the label:
----------------------------------------------------
.. tabs::
.. tab:: Declarative KV style
.. code-block:: python
from kivy.lang.builder import Builder
from kivymd.app import MDApp
KV = '''
MDScreen:
MDLabel:
adaptive_size: True
pos_hint: {"center_x": .5, "center_y": .5}
text: "MDLabel"
allow_selection: True
padding: "4dp", "4dp"
'''
class Example(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV)
Example().run()
.. tab:: Declarative Python style
.. code-block:: python
from kivy.lang.builder import Builder
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import MDScreen
class Example(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return (
MDScreen(
MDLabel(
adaptive_size=True,
pos_hint={"center_x": .5, "center_y": .5},
text="MDLabel",
allow_selection=True,
padding=("4dp", "4dp"),
)
)
)
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-label-allow-selection.gif
:align: center
You can copy the label text by double clicking on it:
-----------------------------------------------------
.. tabs::
.. tab:: Declarative KV style
.. code-block:: python
from kivy.lang.builder import Builder
from kivymd.app import MDApp
KV = '''
MDScreen:
MDLabel:
adaptive_size: True
pos_hint: {"center_x": .5, "center_y": .5}
text: "MDLabel"
padding: "4dp", "4dp"
allow_selection: True
allow_copy: True
on_copy: print("The text is copied to the clipboard")
'''
class Example(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV)
Example().run()
.. tab:: Declarative Python style
.. code-block:: python
from kivy.lang.builder import Builder
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import MDScreen
class Example(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return (
MDScreen(
MDLabel(
id="label",
adaptive_size=True,
pos_hint={"center_x": .5, "center_y": .5},
text="MDLabel",
allow_selection=True,
allow_copy=True,
padding=("4dp", "4dp"),
)
)
)
def on_start(self):
self.root.ids.label.bind(on_copy=self.on_copy)
def on_copy(self, instance_label: MDLabel):
print("The text is copied to the clipboard")
Example().run()
Example of copying/cutting labels using the context menu
--------------------------------------------------------
.. code-block:: python
from kivy.core.clipboard import Clipboard
from kivy.lang.builder import Builder
from kivy.metrics import dp
from kivymd.app import MDApp
from kivymd.uix.label import MDLabel
from kivymd.uix.menu import MDDropdownMenu
from kivymd.toast import toast
KV = '''
MDBoxLayout:
orientation: "vertical"
spacing: "12dp"
padding: "24dp"
MDScrollView:
MDBoxLayout:
id: box
orientation: "vertical"
padding: "24dp"
spacing: "12dp"
adaptive_height: True
MDTextField:
max_height: "200dp"
mode: "fill"
multiline: True
MDWidget:
'''
data = [
"Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
"Sed blandit libero volutpat sed cras ornare arcu. Nisl vel pretium "
"lectus quam id leo in. Tincidunt arcu non sodales neque sodales ut etiam.",
"Elit scelerisque mauris pellentesque pulvinar pellentesque habitant. "
"Nisl rhoncus mattis rhoncus urna neque. Orci nulla pellentesque "
"dignissim enim. Ac auctor augue mauris augue neque gravida in fermentum. "
"Lacus suspendisse faucibus interdum posuere."
]
class CopyLabel(MDLabel):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.allow_selection = True
self.adaptive_height = True
self.theme_text_color = "Custom"
self.text_color = self.theme_cls.text_color
class Example(MDApp):
context_menu = None
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV)
def on_start(self):
for text in data:
copy_label = CopyLabel(text=text)
copy_label.bind(
on_selection=self.open_context_menu,
on_cancel_selection=self.restore_text_color,
)
self.root.ids.box.add_widget(copy_label)
def click_item_context_menu(
self, type_click: str, instance_label: CopyLabel
) -> None:
Clipboard.copy(instance_label.text)
if type_click == "copy":
toast("Copied")
elif type_click == "cut":
self.root.ids.box.remove_widget(instance_label)
toast("Cut")
if self.context_menu:
self.context_menu.dismiss()
def restore_text_color(self, instance_label: CopyLabel) -> None:
instance_label.text_color = self.theme_cls.text_color
def open_context_menu(self, instance_label: CopyLabel) -> None:
instance_label.text_color = "black"
menu_items = [
{
"text": "Copy text",
"viewclass": "OneLineListItem",
"height": dp(48),
"on_release": lambda: self.click_item_context_menu(
"copy", instance_label
),
},
{
"text": "Cut text",
"viewclass": "OneLineListItem",
"height": dp(48),
"on_release": lambda: self.click_item_context_menu(
"cut", instance_label
),
},
]
self.context_menu = MDDropdownMenu(
caller=instance_label, items=menu_items, width_mult=3
)
self.context_menu.open()
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/copying-cutting-labels-using-context-menu.gif
:align: center
.. MDIcon:
@ -217,6 +500,8 @@ MDIcon with badge icon
:align: center
"""
from __future__ import annotations
__all__ = ("MDLabel", "MDIcon")
import os
@ -224,6 +509,8 @@ from typing import Union
from kivy.animation import Animation
from kivy.clock import Clock
from kivy.core.clipboard import Clipboard
from kivy.core.window import Window
from kivy.graphics import Color, Rectangle
from kivy.lang import Builder
from kivy.metrics import sp
@ -243,7 +530,7 @@ from kivymd import uix_path
from kivymd.theming import ThemableBehavior
from kivymd.theming_dynamic_text import get_contrast_text_color
from kivymd.uix import MDAdaptiveWidget
from kivymd.uix.behaviors import DeclarativeBehavior
from kivymd.uix.behaviors import DeclarativeBehavior, TouchBehavior
from kivymd.uix.floatlayout import MDFloatLayout
__MDLabel_colors__ = {
@ -264,7 +551,36 @@ with open(
Builder.load_string(kv_file.read())
class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
class MDLabel(
DeclarativeBehavior,
ThemableBehavior,
Label,
MDAdaptiveWidget,
TouchBehavior,
):
"""
Label class.
For more information, see in the
:class:`~kivymd.uix.behaviors.DeclarativeBehavior` and
:class:`~kivymd.theming.ThemableBehavior` and
:class:`~kivy.uix.label.Label` and
:class:`~kivymd.uix.MDAdaptiveWidget` and
:class:`~kivymd.uix.behaviors.TouchBehavior`
classes documentation.
:Events:
`on_ref_press`
Called when the user clicks on a word referenced with a
``[ref]`` tag in a text markup.
`on_copy`
Called when double-tapping on the label.
`on_selection`
Called when double-tapping on the label.
`on_cancel_selection`
Called when the highlighting is removed from the label text.
"""
font_style = StringProperty("Body1")
"""
Label font style.
@ -316,29 +632,84 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
text_color = ColorProperty(None)
"""
Label text color in (r, g, b, a) format.
Label text color in (r, g, b, a) or string format.
:attr:`text_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
allow_copy = BooleanProperty(False)
"""
Allows you to copy text to the clipboard by double-clicking on the label.
.. versionadded:: 1.2.0
:attr:`allow_copy` is an :class:`~kivy.properties.BooleanProperty`
and defaults to `False`.
"""
allow_selection = BooleanProperty(False)
"""
Allows to highlight text by double-clicking on the label.
.. versionadded:: 1.2.0
:attr:`allow_selection` is an :class:`~kivy.properties.BooleanProperty`
and defaults to `False`.
"""
color_selection = ColorProperty(None)
"""
The color in (r, g, b, a) or string format of the text selection when the
value of the :attr:`allow_selection` attribute is True.
.. versionadded:: 1.2.0
:attr:`color_selection` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
color_deselection = ColorProperty(None)
"""
The color in (r, g, b, a) or string format of the text deselection when the
value of the :attr:`allow_selection` attribute is True.
.. versionadded:: 1.2.0
:attr:`color_deselection` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
is_selected = BooleanProperty(False)
"""
Is the label text highlighted.
.. versionadded:: 1.2.0
:attr:`is_selected` is an :class:`~kivy.properties.BooleanProperty`
and defaults to `False`.
"""
_text_color_str = StringProperty()
parent_background = ColorProperty(None)
can_capitalize = BooleanProperty(True)
canvas_bg = ObjectProperty()
def __init__(self, **kwargs):
super().__init__(**kwargs)
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.bind(
font_style=self.update_font_style,
can_capitalize=self.update_font_style,
)
self.theme_cls.bind(theme_style=self._do_update_theme_color)
self.register_event_type("on_copy")
self.register_event_type("on_selection")
self.register_event_type("on_cancel_selection")
self.on_theme_text_color(None, self.theme_text_color)
self.update_font_style(None, "")
self.on_opposite_colors(None, self.opposite_colors)
Clock.schedule_once(self.check_font_styles)
self.theme_cls.bind(theme_style=self._do_update_theme_color)
def check_font_styles(self, interval: Union[int, float] = 0) -> bool:
if self.font_style not in list(self.theme_cls.font_styles.keys()):
@ -353,7 +724,8 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
if self.check_font_styles() is True:
font_info = self.theme_cls.font_styles[self.font_style]
self.font_name = font_info[0]
self.font_size = sp(font_info[1])
if self.font_style in list(self.theme_cls.font_styles.keys())[0:14]:
self.font_size = sp(font_info[1])
if font_info[2] and self.can_capitalize:
self._capitalizing = True
@ -363,6 +735,64 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
# TODO: Add letter spacing change
# self.letter_spacing = font_info[3]
def do_selection(self) -> None:
if not self.is_selected:
self.md_bg_color = (
self.theme_cls.primary_light
if not self.color_selection
else self.color_selection
)
def cancel_selection(self) -> None:
if self.is_selected:
self.md_bg_color = (
self.theme_cls.bg_normal
if not self.color_deselection
else self.color_deselection
)
self.dispatch("on_cancel_selection")
self.is_selected = False
def on_double_tap(self, touch, *args) -> None:
if self.allow_copy and self.collide_point(*touch.pos):
Clipboard.copy(self.text)
self.dispatch("on_copy")
if self.allow_selection and self.collide_point(*touch.pos):
self.do_selection()
self.dispatch("on_selection")
self.is_selected = True
def on_window_touch(self, *args):
if self.is_selected:
self.cancel_selection()
def on_copy(self, *args) -> None:
"""
Called when double-tapping on the label.
.. versionadded:: 1.2.0
"""
def on_selection(self, *args) -> None:
"""
Called when double-tapping on the label.
.. versionadded:: 1.2.0
"""
def on_cancel_selection(self, *args) -> None:
"""
Called when the highlighting is removed from the label text.
.. versionadded:: 1.2.0
"""
def on_allow_selection(self, instance_label, selection: bool) -> None:
if selection:
Window.bind(on_touch_down=self.on_window_touch)
else:
Window.unbind(on_touch_down=self.on_window_touch)
def on_theme_text_color(
self, instance_label, theme_text_color: str
) -> None:
@ -414,6 +844,7 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
def on_md_bg_color(self, instance_label, color: Union[list, str]) -> None:
self.canvas.remove_group("Background_instruction")
self.canvas.before.clear()
with self.canvas.before:
Color(rgba=color)
self.canvas_bg = Rectangle(pos=self.pos, size=self.size)
@ -445,6 +876,13 @@ class MDLabel(DeclarativeBehavior, ThemableBehavior, Label, MDAdaptiveWidget):
class MDIcon(MDFloatLayout, MDLabel):
"""
Icon class.
For more information, see in the :class:`~MDLabel` and
:class:`~kivymd.uix.floatlayout.MDFloatLayout` classes documentation.
"""
icon = StringProperty("android")
"""
Label icon name.
@ -465,7 +903,7 @@ class MDIcon(MDFloatLayout, MDLabel):
badge_icon_color = ColorProperty([1, 1, 1, 1])
"""
Badge icon color in (r, g, b, a) format.
Badge icon color in (r, g, b, a) or string format.
.. versionadded:: 1.0.0
@ -475,7 +913,7 @@ class MDIcon(MDFloatLayout, MDLabel):
badge_bg_color = ColorProperty(None)
"""
Badge icon background color in (r, g, b, a) format.
Badge icon background color in (r, g, b, a) or string format.
.. versionadded:: 1.0.0