Updated kivymd

This commit is contained in:
Mark Qvist 2022-10-02 17:16:59 +02:00
parent c6df8b851b
commit abcf173cc8
160 changed files with 11617 additions and 6545 deletions

View File

@ -9,23 +9,16 @@ Is a collection of Material Design compliant widgets for use with,
a framework for cross-platform, touch-enabled graphical applications. a framework for cross-platform, touch-enabled graphical applications.
The project's goal is to approximate Google's `Material Design spec The project's goal is to approximate Google's `Material Design spec
<https://material.io/design/introduction>`_ as close as possible without <https://material.io/design/introduction>`_ as close as possible without
sacrificing ease of use or application performance. sacrificing ease of use.
This library is a fork of the `KivyMD project This library is a fork of the `KivyMD project
<https://gitlab.com/kivymd/KivyMD>`_ the author of which stopped supporting <https://gitlab.com/kivymd/KivyMD>`_. We found the strength and brought this
this project three years ago. We found the strength and brought this project project to a new level.
to a new level. Currently we're in **beta** status, so things are changing
all the time and we cannot promise any kind of API stability.
However it is safe to vendor now and make use of what's currently available.
Join the project! Just fork the project, branch out and submit a pull request If you wish to become a project developer (permission to create branches on the
when your patch is ready. If any changes are necessary, we'll guide you project without forking for easier collaboration), have at least one PR
through the steps that need to be done via PR comments or access to your for approved and ask for it. If you contribute regularly to the project the role
may be requested to outright submit them. If you wish to become a project may be offered to you without asking too.
developer (permission to create branches on the project without forking for
easier collaboration), have at least one PR approved and ask for it.
If you contribute regularly to the project the role may be offered to you
without asking too.
""" """
import os import os
@ -33,7 +26,7 @@ import os
import kivy import kivy
from kivy.logger import Logger from kivy.logger import Logger
__version__ = "1.0.0.dev0" __version__ = "1.1.0.dev0"
"""KivyMD version.""" """KivyMD version."""
release = False release = False
@ -56,6 +49,9 @@ images_path = os.path.join(path, f"images{os.sep}")
uix_path = os.path.join(path, "uix") uix_path = os.path.join(path, "uix")
"""Path to uix directory.""" """Path to uix directory."""
glsl_path = os.path.join(path, "data", "glsl")
"""Path to glsl directory."""
_log_message = ( _log_message = (
"KivyMD:" "KivyMD:"
+ (" Release" if release else "") + (" Release" if release else "")

View File

@ -1,5 +0,0 @@
# THIS FILE IS GENERATED FROM KIVYMD SETUP.PY
__version__ = '1.0.0.dev0'
__hash__ = '68ec8626a93b0e7f69e48d9755c4af70028f66a2'
__short_hash__ = '68ec862'
__date__ = '2022-07-07'

View File

@ -45,7 +45,7 @@ import os
from kivy.app import App from kivy.app import App
from kivy.lang import Builder from kivy.lang import Builder
from kivy.logger import Logger from kivy.logger import Logger
from kivy.properties import ObjectProperty from kivy.properties import ObjectProperty, StringProperty
from kivymd.theming import ThemeManager from kivymd.theming import ThemeManager
@ -71,6 +71,16 @@ class MDApp(App, FpsMonitoring):
information. information.
""" """
icon = StringProperty("kivymd/images/logo/kivymd-icon-512.png")
"""
See :attr:`~kivy.app.App.icon` attribute for more information.
.. versionadded:: 1.1.0
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
adn default to `kivymd/images/logo/kivymd-icon-512.png`.
"""
theme_cls = ObjectProperty() theme_cls = ObjectProperty()
""" """
Instance of :class:`~ThemeManager` class. Instance of :class:`~ThemeManager` class.

View File

@ -412,7 +412,7 @@ To demonstrate the shades of the palette, you can run the following code:
self.screen = Factory.Root() self.screen = Factory.Root()
for name_tab in colors.keys(): for name_tab in colors.keys():
tab = Tab(text=name_tab) tab = Tab(title=name_tab)
self.screen.ids.android_tabs.add_widget(tab) self.screen.ids.android_tabs.add_widget(tab)
return self.screen return self.screen
@ -427,7 +427,7 @@ To demonstrate the shades of the palette, you can run the following code:
{ {
"viewclass": "ItemColor", "viewclass": "ItemColor",
"md_bg_color": colors[tab_text][value_color], "md_bg_color": colors[tab_text][value_color],
"text": value_color, "title": value_color,
} }
) )

View File

@ -0,0 +1,44 @@
/*
The shader code has been refactored for the KivyMD library.
You can find the original code of this shaders at the links:
https://www.shadertoy.com/view/WtdSDs
https://www.shadertoy.com/view/fsdyzB
Additional thanks to iq for optimizing conditional block for individual
corner radius:
https://iquilezles.org/articles/distfunctions
*/
float roundedBoxSDF(vec2 centerPosition, vec2 size, vec4 radius) {
radius.xy = (centerPosition.x > 0.0) ? radius.xy : radius.zw;
radius.x = (centerPosition.y > 0.0) ? radius.x : radius.y;
vec2 q = abs(centerPosition) - (size - shadow_softness) + radius.x;
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - radius.x;
}
void mainImage(out vec4 fragColor, in vec2 fragCoord) {
// Smooth the result (free antialiasing).
float edge0 = 0.0;
float smoothedAlpha = 1.0 - smoothstep(0.0, edge0, 1.0);
// Get the resultant shape.
vec4 quadColor = mix(
vec4(
shadow_color[0],
shadow_color[1],
shadow_color[2],
0.0
),
shadow_color,
smoothedAlpha
);
// Apply a drop shadow effect.
float shadowDistance = roundedBoxSDF(
fragCoord.xy - mouse.xy - (size / 2.0), size / 2.0, shadow_radius
);
float shadowAlpha = 1.0 - smoothstep(
-shadow_softness, shadow_softness, shadowDistance
);
fragColor = mix(quadColor, shadow_color, shadowAlpha - smoothedAlpha);
}

View File

@ -0,0 +1,10 @@
#ifdef GL_ES
precision highp float;
#endif
uniform vec4 resolution;
uniform vec4 mouse;
uniform vec2 size;
uniform vec4 shadow_radius;
uniform float shadow_softness;
uniform vec4 shadow_color;

View File

@ -0,0 +1,10 @@
vec2 gfc(in vec4 fc) {
vec2 canvas_pos = resolution.zw;
vec2 uv = fc.xy;
uv.y -= canvas_pos.y;
return uv;
}
void main(void) {
mainImage(gl_FragColor, gfc(gl_FragCoord));
}

View File

@ -5,11 +5,15 @@ Register KivyMD widgets to use without import.
from kivy.factory import Factory from kivy.factory import Factory
register = Factory.register register = Factory.register
register("MDScrollView", module="kivymd.uix.scrollview")
register("MDRecycleView", module="kivymd.uix.recycleview")
register("MDResponsiveLayout", module="kivymd.uix.responsivelayout")
register("MDSegmentedControl", module="kivymd.uix.segmentedcontrol") register("MDSegmentedControl", module="kivymd.uix.segmentedcontrol")
register("MDSegmentedControlItem", module="kivymd.uix.segmentedcontrol") register("MDSegmentedControlItem", module="kivymd.uix.segmentedcontrol")
register("MDSliverAppbar", module="kivymd.uix.sliverappbar") register("MDSliverAppbar", module="kivymd.uix.sliverappbar")
register("MDSliverAppbarContent", module="kivymd.uix.sliverappbar") register("MDSliverAppbarContent", module="kivymd.uix.sliverappbar")
register("MDSliverAppbarHeader", module="kivymd.uix.sliverappbar") register("MDSliverAppbarHeader", module="kivymd.uix.sliverappbar")
register("MDNavigationRailItem", module="kivymd.uix.navigationrail")
register("MDNavigationRail", module="kivymd.uix.navigationrail") register("MDNavigationRail", module="kivymd.uix.navigationrail")
register("MDNavigationRailFabButton", module="kivymd.uix.navigationrail") register("MDNavigationRailFabButton", module="kivymd.uix.navigationrail")
register("MDNavigationRailMenuButton", module="kivymd.uix.navigationrail") register("MDNavigationRailMenuButton", module="kivymd.uix.navigationrail")
@ -29,7 +33,7 @@ register("MDExpansionPanel", module="kivymd.uix.expansionpanel")
register("MDExpansionPanelOneLine", module="kivymd.uix.expansionpanel") register("MDExpansionPanelOneLine", module="kivymd.uix.expansionpanel")
register("MDExpansionPanelTwoLine", module="kivymd.uix.expansionpanel") register("MDExpansionPanelTwoLine", module="kivymd.uix.expansionpanel")
register("MDExpansionPanelThreeLine", module="kivymd.uix.expansionpanel") register("MDExpansionPanelThreeLine", module="kivymd.uix.expansionpanel")
register("FitImage", module="kivymd.utils.fitimage") register("FitImage", module="kivymd.uix.fitimage")
register("MDBackdrop", module="kivymd.uix.backdrop") register("MDBackdrop", module="kivymd.uix.backdrop")
register("MDBanner", module="kivymd.uix.banner") register("MDBanner", module="kivymd.uix.banner")
register("MDTooltip", module="kivymd.uix.tooltip") register("MDTooltip", module="kivymd.uix.tooltip")
@ -54,10 +58,7 @@ register("MDCard", module="kivymd.uix.card")
register("MDSeparator", module="kivymd.uix.card") register("MDSeparator", module="kivymd.uix.card")
register("MDSelectionList", module="kivymd.uix.selection") register("MDSelectionList", module="kivymd.uix.selection")
register("MDChip", module="kivymd.uix.chip") register("MDChip", module="kivymd.uix.chip")
register("MDChooseChip", module="kivymd.uix.chip")
register("MDSmartTile", module="kivymd.uix.imagelist") register("MDSmartTile", module="kivymd.uix.imagelist")
register("SmartTileWithLabel", module="kivymd.uix.imagelist")
register("SmartTileWithStar", module="kivymd.uix.imagelist")
register("MDLabel", module="kivymd.uix.label") register("MDLabel", module="kivymd.uix.label")
register("MDIcon", module="kivymd.uix.label") register("MDIcon", module="kivymd.uix.label")
register("MDList", module="kivymd.uix.list") register("MDList", module="kivymd.uix.list")
@ -65,7 +66,6 @@ register("ILeftBody", module="kivymd.uix.list")
register("ILeftBodyTouch", module="kivymd.uix.list") register("ILeftBodyTouch", module="kivymd.uix.list")
register("IRightBody", module="kivymd.uix.list") register("IRightBody", module="kivymd.uix.list")
register("IRightBodyTouch", module="kivymd.uix.list") register("IRightBodyTouch", module="kivymd.uix.list")
register("ContainerSupport", module="kivymd.uix.list")
register("OneLineListItem", module="kivymd.uix.list") register("OneLineListItem", module="kivymd.uix.list")
register("TwoLineListItem", module="kivymd.uix.list") register("TwoLineListItem", module="kivymd.uix.list")
register("ThreeLineListItem", module="kivymd.uix.list") register("ThreeLineListItem", module="kivymd.uix.list")
@ -99,9 +99,7 @@ register("MDSlider", module="kivymd.uix.slider")
register("MDSpinner", module="kivymd.uix.spinner") register("MDSpinner", module="kivymd.uix.spinner")
register("MDTabs", module="kivymd.uix.tab") register("MDTabs", module="kivymd.uix.tab")
register("MDTextField", module="kivymd.uix.textfield") register("MDTextField", module="kivymd.uix.textfield")
register("MDTextFieldRound", module="kivymd.uix.textfield")
register("MDTextFieldRect", module="kivymd.uix.textfield") register("MDTextFieldRect", module="kivymd.uix.textfield")
register("MDToolbar", module="kivymd.uix.toolbar")
register("MDTopAppBar", module="kivymd.uix.toolbar") register("MDTopAppBar", module="kivymd.uix.toolbar")
register("MDBottomAppBar", module="kivymd.uix.toolbar") register("MDBottomAppBar", module="kivymd.uix.toolbar")
register("MDDropDownItem", module="kivymd.uix.dropdownitem") register("MDDropDownItem", module="kivymd.uix.dropdownitem")

View File

@ -12,7 +12,7 @@ Themes/Icon Definitions
List of icons from materialdesignicons.com. These expanded material design List of icons from materialdesignicons.com. These expanded material design
icons are maintained by Austin Andrews (Templarian on Github). icons are maintained by Austin Andrews (Templarian on Github).
LAST UPDATED: Version 6.9.96 LAST UPDATED: Version 7.0.96
To preview the icons and their names, you can use the following application: To preview the icons and their names, you can use the following application:
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
@ -154,6 +154,8 @@ md_icons = {
"account-box-outline": "\U000F0007", "account-box-outline": "\U000F0007",
"account-cancel": "\U000F12DF", "account-cancel": "\U000F12DF",
"account-cancel-outline": "\U000F12E0", "account-cancel-outline": "\U000F12E0",
"account-card": "\U000F1BA4",
"account-card-outline": "\U000F1BA5",
"account-cash": "\U000F1097", "account-cash": "\U000F1097",
"account-cash-outline": "\U000F1098", "account-cash-outline": "\U000F1098",
"account-check": "\U000F0008", "account-check": "\U000F0008",
@ -171,6 +173,8 @@ md_icons = {
"account-convert-outline": "\U000F1301", "account-convert-outline": "\U000F1301",
"account-cowboy-hat": "\U000F0E9B", "account-cowboy-hat": "\U000F0E9B",
"account-cowboy-hat-outline": "\U000F17F3", "account-cowboy-hat-outline": "\U000F17F3",
"account-credit-card": "\U000F1BA6",
"account-credit-card-outline": "\U000F1BA7",
"account-details": "\U000F0631", "account-details": "\U000F0631",
"account-details-outline": "\U000F1372", "account-details-outline": "\U000F1372",
"account-edit": "\U000F06BC", "account-edit": "\U000F06BC",
@ -260,6 +264,7 @@ md_icons = {
"air-humidifier": "\U000F1099", "air-humidifier": "\U000F1099",
"air-humidifier-off": "\U000F1466", "air-humidifier-off": "\U000F1466",
"air-purifier": "\U000F0D44", "air-purifier": "\U000F0D44",
"air-purifier-off": "\U000F1B57",
"airbag": "\U000F0BE9", "airbag": "\U000F0BE9",
"airballoon": "\U000F001C", "airballoon": "\U000F001C",
"airballoon-outline": "\U000F100B", "airballoon-outline": "\U000F100B",
@ -480,7 +485,6 @@ md_icons = {
"amplifier-off": "\U000F11B5", "amplifier-off": "\U000F11B5",
"anchor": "\U000F0031", "anchor": "\U000F0031",
"android": "\U000F0032", "android": "\U000F0032",
"android-messages": "\U000F0D45",
"android-studio": "\U000F0034", "android-studio": "\U000F0034",
"angle-acute": "\U000F0937", "angle-acute": "\U000F0937",
"angle-obtuse": "\U000F0938", "angle-obtuse": "\U000F0938",
@ -745,6 +749,7 @@ md_icons = {
"arrow-up-thin": "\U000F19B2", "arrow-up-thin": "\U000F19B2",
"arrow-up-thin-circle-outline": "\U000F1597", "arrow-up-thin-circle-outline": "\U000F1597",
"arrow-vertical-lock": "\U000F115C", "arrow-vertical-lock": "\U000F115C",
"artboard": "\U000F1B9A",
"artstation": "\U000F0B5B", "artstation": "\U000F0B5B",
"aspect-ratio": "\U000F0A24", "aspect-ratio": "\U000F0A24",
"assistant": "\U000F0064", "assistant": "\U000F0064",
@ -762,6 +767,7 @@ md_icons = {
"attachment-off": "\U000F1AC3", "attachment-off": "\U000F1AC3",
"attachment-plus": "\U000F1AC4", "attachment-plus": "\U000F1AC4",
"attachment-remove": "\U000F1AC5", "attachment-remove": "\U000F1AC5",
"atv": "\U000F1B70",
"audio-input-rca": "\U000F186B", "audio-input-rca": "\U000F186B",
"audio-input-stereo-minijack": "\U000F186C", "audio-input-stereo-minijack": "\U000F186C",
"audio-input-xlr": "\U000F186D", "audio-input-xlr": "\U000F186D",
@ -774,6 +780,8 @@ md_icons = {
"autorenew": "\U000F006A", "autorenew": "\U000F006A",
"autorenew-off": "\U000F19E7", "autorenew-off": "\U000F19E7",
"av-timer": "\U000F006B", "av-timer": "\U000F006B",
"awning": "\U000F1B87",
"awning-outline": "\U000F1B88",
"aws": "\U000F0E0F", "aws": "\U000F0E0F",
"axe": "\U000F08C8", "axe": "\U000F08C8",
"axe-battle": "\U000F1842", "axe-battle": "\U000F1842",
@ -987,6 +995,7 @@ md_icons = {
"beaker-remove": "\U000F1233", "beaker-remove": "\U000F1233",
"beaker-remove-outline": "\U000F1234", "beaker-remove-outline": "\U000F1234",
"bed": "\U000F02E3", "bed": "\U000F02E3",
"bed-clock": "\U000F1B94",
"bed-double": "\U000F0FD4", "bed-double": "\U000F0FD4",
"bed-double-outline": "\U000F0FD3", "bed-double-outline": "\U000F0FD3",
"bed-empty": "\U000F08A0", "bed-empty": "\U000F08A0",
@ -1148,10 +1157,11 @@ md_icons = {
"book-sync": "\U000F169C", "book-sync": "\U000F169C",
"book-sync-outline": "\U000F16C8", "book-sync-outline": "\U000F16C8",
"book-variant": "\U000F00BF", "book-variant": "\U000F00BF",
"book-variant-multiple": "\U000F00BC",
"bookmark": "\U000F00C0", "bookmark": "\U000F00C0",
"bookmark-box": "\U000F1B75",
"bookmark-box-multiple": "\U000F196C", "bookmark-box-multiple": "\U000F196C",
"bookmark-box-multiple-outline": "\U000F196D", "bookmark-box-multiple-outline": "\U000F196D",
"bookmark-box-outline": "\U000F1B76",
"bookmark-check": "\U000F00C1", "bookmark-check": "\U000F00C1",
"bookmark-check-outline": "\U000F137B", "bookmark-check-outline": "\U000F137B",
"bookmark-minus": "\U000F09CC", "bookmark-minus": "\U000F09CC",
@ -1339,8 +1349,11 @@ md_icons = {
"calendar-account": "\U000F0ED7", "calendar-account": "\U000F0ED7",
"calendar-account-outline": "\U000F0ED8", "calendar-account-outline": "\U000F0ED8",
"calendar-alert": "\U000F0A31", "calendar-alert": "\U000F0A31",
"calendar-alert-outline": "\U000F1B62",
"calendar-arrow-left": "\U000F1134", "calendar-arrow-left": "\U000F1134",
"calendar-arrow-right": "\U000F1135", "calendar-arrow-right": "\U000F1135",
"calendar-badge": "\U000F1B9D",
"calendar-badge-outline": "\U000F1B9E",
"calendar-blank": "\U000F00EE", "calendar-blank": "\U000F00EE",
"calendar-blank-multiple": "\U000F1073", "calendar-blank-multiple": "\U000F1073",
"calendar-blank-outline": "\U000F0B66", "calendar-blank-outline": "\U000F0B66",
@ -1349,26 +1362,40 @@ md_icons = {
"calendar-clock": "\U000F00F0", "calendar-clock": "\U000F00F0",
"calendar-clock-outline": "\U000F16E1", "calendar-clock-outline": "\U000F16E1",
"calendar-collapse-horizontal": "\U000F189D", "calendar-collapse-horizontal": "\U000F189D",
"calendar-collapse-horizontal-outline": "\U000F1B63",
"calendar-cursor": "\U000F157B", "calendar-cursor": "\U000F157B",
"calendar-cursor-outline": "\U000F1B64",
"calendar-edit": "\U000F08A7", "calendar-edit": "\U000F08A7",
"calendar-edit-outline": "\U000F1B65",
"calendar-end": "\U000F166C", "calendar-end": "\U000F166C",
"calendar-end-outline": "\U000F1B66",
"calendar-expand-horizontal": "\U000F189E", "calendar-expand-horizontal": "\U000F189E",
"calendar-expand-horizontal-outline": "\U000F1B67",
"calendar-export": "\U000F0B24", "calendar-export": "\U000F0B24",
"calendar-export-outline": "\U000F1B68",
"calendar-filter": "\U000F1A32", "calendar-filter": "\U000F1A32",
"calendar-filter-outline": "\U000F1A33", "calendar-filter-outline": "\U000F1A33",
"calendar-heart": "\U000F09D2", "calendar-heart": "\U000F09D2",
"calendar-heart-outline": "\U000F1B69",
"calendar-import": "\U000F0B25", "calendar-import": "\U000F0B25",
"calendar-import-outline": "\U000F1B6A",
"calendar-lock": "\U000F1641", "calendar-lock": "\U000F1641",
"calendar-lock-open": "\U000F1B5B",
"calendar-lock-open-outline": "\U000F1B5C",
"calendar-lock-outline": "\U000F1642", "calendar-lock-outline": "\U000F1642",
"calendar-minus": "\U000F0D5C", "calendar-minus": "\U000F0D5C",
"calendar-minus-outline": "\U000F1B6B",
"calendar-month": "\U000F0E17", "calendar-month": "\U000F0E17",
"calendar-month-outline": "\U000F0E18", "calendar-month-outline": "\U000F0E18",
"calendar-multiple": "\U000F00F1", "calendar-multiple": "\U000F00F1",
"calendar-multiple-check": "\U000F00F2", "calendar-multiple-check": "\U000F00F2",
"calendar-multiselect": "\U000F0A32", "calendar-multiselect": "\U000F0A32",
"calendar-multiselect-outline": "\U000F1B55",
"calendar-outline": "\U000F0B67", "calendar-outline": "\U000F0B67",
"calendar-plus": "\U000F00F3", "calendar-plus": "\U000F00F3",
"calendar-plus-outline": "\U000F1B6C",
"calendar-question": "\U000F0692", "calendar-question": "\U000F0692",
"calendar-question-outline": "\U000F1B6D",
"calendar-range": "\U000F0679", "calendar-range": "\U000F0679",
"calendar-range-outline": "\U000F0B68", "calendar-range-outline": "\U000F0B68",
"calendar-refresh": "\U000F01E1", "calendar-refresh": "\U000F01E1",
@ -1376,9 +1403,11 @@ md_icons = {
"calendar-remove": "\U000F00F4", "calendar-remove": "\U000F00F4",
"calendar-remove-outline": "\U000F0C45", "calendar-remove-outline": "\U000F0C45",
"calendar-search": "\U000F094C", "calendar-search": "\U000F094C",
"calendar-search-outline": "\U000F1B6E",
"calendar-star": "\U000F09D3", "calendar-star": "\U000F09D3",
"calendar-star-outline": "\U000F1B53", "calendar-star-outline": "\U000F1B53",
"calendar-start": "\U000F166D", "calendar-start": "\U000F166D",
"calendar-start-outline": "\U000F1B6F",
"calendar-sync": "\U000F0E8E", "calendar-sync": "\U000F0E8E",
"calendar-sync-outline": "\U000F0E8F", "calendar-sync-outline": "\U000F0E8F",
"calendar-text": "\U000F00F5", "calendar-text": "\U000F00F5",
@ -1496,6 +1525,8 @@ md_icons = {
"car-outline": "\U000F14ED", "car-outline": "\U000F14ED",
"car-parking-lights": "\U000F0D63", "car-parking-lights": "\U000F0D63",
"car-pickup": "\U000F07AA", "car-pickup": "\U000F07AA",
"car-search": "\U000F1B8D",
"car-search-outline": "\U000F1B8E",
"car-seat": "\U000F0FA4", "car-seat": "\U000F0FA4",
"car-seat-cooler": "\U000F0FA5", "car-seat-cooler": "\U000F0FA5",
"car-seat-heater": "\U000F0FA6", "car-seat-heater": "\U000F0FA6",
@ -1584,6 +1615,7 @@ md_icons = {
"cart-minus": "\U000F0D68", "cart-minus": "\U000F0D68",
"cart-off": "\U000F066B", "cart-off": "\U000F066B",
"cart-outline": "\U000F0111", "cart-outline": "\U000F0111",
"cart-percent": "\U000F1BAE",
"cart-plus": "\U000F0112", "cart-plus": "\U000F0112",
"cart-remove": "\U000F0D69", "cart-remove": "\U000F0D69",
"cart-variant": "\U000F15EB", "cart-variant": "\U000F15EB",
@ -1969,6 +2001,7 @@ md_icons = {
"cloud-tags": "\U000F07B6", "cloud-tags": "\U000F07B6",
"cloud-upload": "\U000F0167", "cloud-upload": "\U000F0167",
"cloud-upload-outline": "\U000F0B7E", "cloud-upload-outline": "\U000F0B7E",
"clouds": "\U000F1B95",
"clover": "\U000F0816", "clover": "\U000F0816",
"coach-lamp": "\U000F1020", "coach-lamp": "\U000F1020",
"coach-lamp-variant": "\U000F1A37", "coach-lamp-variant": "\U000F1A37",
@ -2128,8 +2161,10 @@ md_icons = {
"contrast": "\U000F0195", "contrast": "\U000F0195",
"contrast-box": "\U000F0196", "contrast-box": "\U000F0196",
"contrast-circle": "\U000F0197", "contrast-circle": "\U000F0197",
"controller": "\U000F02B4",
"controller-classic": "\U000F0B82", "controller-classic": "\U000F0B82",
"controller-classic-outline": "\U000F0B83", "controller-classic-outline": "\U000F0B83",
"controller-off": "\U000F02B5",
"cookie": "\U000F0198", "cookie": "\U000F0198",
"cookie-alert": "\U000F16D0", "cookie-alert": "\U000F16D0",
"cookie-alert-outline": "\U000F16D1", "cookie-alert-outline": "\U000F16D1",
@ -2278,6 +2313,7 @@ md_icons = {
"currency-sign": "\U000F07BE", "currency-sign": "\U000F07BE",
"currency-try": "\U000F01B2", "currency-try": "\U000F01B2",
"currency-twd": "\U000F07BF", "currency-twd": "\U000F07BF",
"currency-uah": "\U000F1B9B",
"currency-usd": "\U000F01C1", "currency-usd": "\U000F01C1",
"currency-usd-off": "\U000F067A", "currency-usd-off": "\U000F067A",
"current-ac": "\U000F1480", "current-ac": "\U000F1480",
@ -2391,8 +2427,6 @@ md_icons = {
"desk-lamp-on": "\U000F1B20", "desk-lamp-on": "\U000F1B20",
"deskphone": "\U000F01C3", "deskphone": "\U000F01C3",
"desktop-classic": "\U000F07C0", "desktop-classic": "\U000F07C0",
"desktop-mac": "\U000F01C4",
"desktop-mac-dashboard": "\U000F09E8",
"desktop-tower": "\U000F01C5", "desktop-tower": "\U000F01C5",
"desktop-tower-monitor": "\U000F0AAB", "desktop-tower-monitor": "\U000F0AAB",
"details": "\U000F01C6", "details": "\U000F01C6",
@ -2442,7 +2476,6 @@ md_icons = {
"disc": "\U000F05EE", "disc": "\U000F05EE",
"disc-alert": "\U000F01D1", "disc-alert": "\U000F01D1",
"disc-player": "\U000F0960", "disc-player": "\U000F0960",
"discord": "\U000F066F",
"dishwasher": "\U000F0AAC", "dishwasher": "\U000F0AAC",
"dishwasher-alert": "\U000F11B8", "dishwasher-alert": "\U000F11B8",
"dishwasher-off": "\U000F11B9", "dishwasher-off": "\U000F11B9",
@ -2457,8 +2490,9 @@ md_icons = {
"diving": "\U000F1977", "diving": "\U000F1977",
"diving-flippers": "\U000F0DBF", "diving-flippers": "\U000F0DBF",
"diving-helmet": "\U000F0DC0", "diving-helmet": "\U000F0DC0",
"diving-scuba": "\U000F0DC1", "diving-scuba": "\U000F1B77",
"diving-scuba-flag": "\U000F0DC2", "diving-scuba-flag": "\U000F0DC2",
"diving-scuba-mask": "\U000F0DC1",
"diving-scuba-tank": "\U000F0DC3", "diving-scuba-tank": "\U000F0DC3",
"diving-scuba-tank-multiple": "\U000F0DC4", "diving-scuba-tank-multiple": "\U000F0DC4",
"diving-snorkel": "\U000F0DC5", "diving-snorkel": "\U000F0DC5",
@ -2590,6 +2624,10 @@ md_icons = {
"email": "\U000F01EE", "email": "\U000F01EE",
"email-alert": "\U000F06CF", "email-alert": "\U000F06CF",
"email-alert-outline": "\U000F0D42", "email-alert-outline": "\U000F0D42",
"email-arrow-left": "\U000F10DA",
"email-arrow-left-outline": "\U000F10DB",
"email-arrow-right": "\U000F10DC",
"email-arrow-right-outline": "\U000F10DD",
"email-box": "\U000F0D03", "email-box": "\U000F0D03",
"email-check": "\U000F0AB1", "email-check": "\U000F0AB1",
"email-check-outline": "\U000F0AB2", "email-check-outline": "\U000F0AB2",
@ -2598,6 +2636,7 @@ md_icons = {
"email-fast": "\U000F186F", "email-fast": "\U000F186F",
"email-fast-outline": "\U000F1870", "email-fast-outline": "\U000F1870",
"email-lock": "\U000F01F1", "email-lock": "\U000F01F1",
"email-lock-outline": "\U000F1B61",
"email-mark-as-unread": "\U000F0B92", "email-mark-as-unread": "\U000F0B92",
"email-minus": "\U000F0EE5", "email-minus": "\U000F0EE5",
"email-minus-outline": "\U000F0EE6", "email-minus-outline": "\U000F0EE6",
@ -2613,16 +2652,12 @@ md_icons = {
"email-outline": "\U000F01F0", "email-outline": "\U000F01F0",
"email-plus": "\U000F09EB", "email-plus": "\U000F09EB",
"email-plus-outline": "\U000F09EC", "email-plus-outline": "\U000F09EC",
"email-receive": "\U000F10DA",
"email-receive-outline": "\U000F10DB",
"email-remove": "\U000F1661", "email-remove": "\U000F1661",
"email-remove-outline": "\U000F1662", "email-remove-outline": "\U000F1662",
"email-seal": "\U000F195B", "email-seal": "\U000F195B",
"email-seal-outline": "\U000F195C", "email-seal-outline": "\U000F195C",
"email-search": "\U000F0961", "email-search": "\U000F0961",
"email-search-outline": "\U000F0962", "email-search-outline": "\U000F0962",
"email-send": "\U000F10DC",
"email-send-outline": "\U000F10DD",
"email-sync": "\U000F12C7", "email-sync": "\U000F12C7",
"email-sync-outline": "\U000F12C8", "email-sync-outline": "\U000F12C8",
"email-variant": "\U000F05F0", "email-variant": "\U000F05F0",
@ -3013,7 +3048,15 @@ md_icons = {
"flag-remove-outline": "\U000F10B4", "flag-remove-outline": "\U000F10B4",
"flag-triangle": "\U000F023F", "flag-triangle": "\U000F023F",
"flag-variant": "\U000F0240", "flag-variant": "\U000F0240",
"flag-variant-minus": "\U000F1BB4",
"flag-variant-minus-outline": "\U000F1BB5",
"flag-variant-off": "\U000F1BB0",
"flag-variant-off-outline": "\U000F1BB1",
"flag-variant-outline": "\U000F023E", "flag-variant-outline": "\U000F023E",
"flag-variant-plus": "\U000F1BB2",
"flag-variant-plus-outline": "\U000F1BB3",
"flag-variant-remove": "\U000F1BB6",
"flag-variant-remove-outline": "\U000F1BB7",
"flare": "\U000F0D72", "flare": "\U000F0D72",
"flash": "\U000F0241", "flash": "\U000F0241",
"flash-alert": "\U000F0EF7", "flash-alert": "\U000F0EF7",
@ -3275,6 +3318,7 @@ md_icons = {
"format-list-checkbox": "\U000F096A", "format-list-checkbox": "\U000F096A",
"format-list-checks": "\U000F0756", "format-list-checks": "\U000F0756",
"format-list-group": "\U000F1860", "format-list-group": "\U000F1860",
"format-list-group-plus": "\U000F1B56",
"format-list-numbered": "\U000F027B", "format-list-numbered": "\U000F027B",
"format-list-numbered-rtl": "\U000F0D0D", "format-list-numbered-rtl": "\U000F0D0D",
"format-list-text": "\U000F126F", "format-list-text": "\U000F126F",
@ -3285,6 +3329,8 @@ md_icons = {
"format-paragraph": "\U000F027D", "format-paragraph": "\U000F027D",
"format-paragraph-spacing": "\U000F1AFD", "format-paragraph-spacing": "\U000F1AFD",
"format-pilcrow": "\U000F06D8", "format-pilcrow": "\U000F06D8",
"format-pilcrow-arrow-left": "\U000F0286",
"format-pilcrow-arrow-right": "\U000F0285",
"format-quote-close": "\U000F027E", "format-quote-close": "\U000F027E",
"format-quote-close-outline": "\U000F11A8", "format-quote-close-outline": "\U000F11A8",
"format-quote-open": "\U000F0757", "format-quote-open": "\U000F0757",
@ -3310,8 +3356,6 @@ md_icons = {
"format-text-wrapping-overflow": "\U000F0D0F", "format-text-wrapping-overflow": "\U000F0D0F",
"format-text-wrapping-wrap": "\U000F0D10", "format-text-wrapping-wrap": "\U000F0D10",
"format-textbox": "\U000F0D11", "format-textbox": "\U000F0D11",
"format-textdirection-l-to-r": "\U000F0285",
"format-textdirection-r-to-l": "\U000F0286",
"format-title": "\U000F05F4", "format-title": "\U000F05F4",
"format-underline": "\U000F0287", "format-underline": "\U000F0287",
"format-underline-wavy": "\U000F18E9", "format-underline-wavy": "\U000F18E9",
@ -3487,7 +3531,8 @@ md_icons = {
"glass-tulip": "\U000F02A8", "glass-tulip": "\U000F02A8",
"glass-wine": "\U000F0876", "glass-wine": "\U000F0876",
"glasses": "\U000F02AA", "glasses": "\U000F02AA",
"globe-light": "\U000F12D7", "globe-light": "\U000F066F",
"globe-light-outline": "\U000F12D7",
"globe-model": "\U000F08E9", "globe-model": "\U000F08E9",
"gmail": "\U000F02AB", "gmail": "\U000F02AB",
"gnome": "\U000F02AC", "gnome": "\U000F02AC",
@ -3512,15 +3557,12 @@ md_icons = {
"google-circles-group": "\U000F02B3", "google-circles-group": "\U000F02B3",
"google-classroom": "\U000F02C0", "google-classroom": "\U000F02C0",
"google-cloud": "\U000F11F6", "google-cloud": "\U000F11F6",
"google-controller": "\U000F02B4",
"google-controller-off": "\U000F02B5",
"google-downasaur": "\U000F1362", "google-downasaur": "\U000F1362",
"google-drive": "\U000F02B6", "google-drive": "\U000F02B6",
"google-earth": "\U000F02B7", "google-earth": "\U000F02B7",
"google-fit": "\U000F096C", "google-fit": "\U000F096C",
"google-glass": "\U000F02B8", "google-glass": "\U000F02B8",
"google-hangouts": "\U000F02C9", "google-hangouts": "\U000F02C9",
"google-home": "\U000F0824",
"google-keep": "\U000F06DC", "google-keep": "\U000F06DC",
"google-lens": "\U000F09F6", "google-lens": "\U000F09F6",
"google-maps": "\U000F05F5", "google-maps": "\U000F05F5",
@ -3582,6 +3624,7 @@ md_icons = {
"hand-clap-off": "\U000F1A42", "hand-clap-off": "\U000F1A42",
"hand-coin": "\U000F188F", "hand-coin": "\U000F188F",
"hand-coin-outline": "\U000F1890", "hand-coin-outline": "\U000F1890",
"hand-cycle": "\U000F1B9C",
"hand-extended": "\U000F18B6", "hand-extended": "\U000F18B6",
"hand-extended-outline": "\U000F18B7", "hand-extended-outline": "\U000F18B7",
"hand-front-left": "\U000F182B", "hand-front-left": "\U000F182B",
@ -3615,6 +3658,7 @@ md_icons = {
"harddisk-remove": "\U000F104C", "harddisk-remove": "\U000F104C",
"hat-fedora": "\U000F0BA4", "hat-fedora": "\U000F0BA4",
"hazard-lights": "\U000F0C89", "hazard-lights": "\U000F0C89",
"hdmi-port": "\U000F1BB8",
"hdr": "\U000F0D7D", "hdr": "\U000F0D7D",
"hdr-off": "\U000F0D7E", "hdr-off": "\U000F0D7E",
"head": "\U000F135E", "head": "\U000F135E",
@ -3768,6 +3812,8 @@ md_icons = {
"home-roof": "\U000F112B", "home-roof": "\U000F112B",
"home-search": "\U000F13B0", "home-search": "\U000F13B0",
"home-search-outline": "\U000F13B1", "home-search-outline": "\U000F13B1",
"home-silo": "\U000F1BA0",
"home-silo-outline": "\U000F1BA1",
"home-switch": "\U000F1794", "home-switch": "\U000F1794",
"home-switch-outline": "\U000F1795", "home-switch-outline": "\U000F1795",
"home-thermometer": "\U000F0F54", "home-thermometer": "\U000F0F54",
@ -3827,6 +3873,7 @@ md_icons = {
"human-pregnant": "\U000F05CF", "human-pregnant": "\U000F05CF",
"human-queue": "\U000F1571", "human-queue": "\U000F1571",
"human-scooter": "\U000F11E9", "human-scooter": "\U000F11E9",
"human-walker": "\U000F1B71",
"human-wheelchair": "\U000F138D", "human-wheelchair": "\U000F138D",
"human-white-cane": "\U000F1981", "human-white-cane": "\U000F1981",
"humble-bundle": "\U000F0744", "humble-bundle": "\U000F0744",
@ -4005,6 +4052,7 @@ md_icons = {
"klingon": "\U000F135B", "klingon": "\U000F135B",
"knife": "\U000F09FB", "knife": "\U000F09FB",
"knife-military": "\U000F09FC", "knife-military": "\U000F09FC",
"knob": "\U000F1B96",
"koala": "\U000F173F", "koala": "\U000F173F",
"kodi": "\U000F0314", "kodi": "\U000F0314",
"kubernetes": "\U000F10FE", "kubernetes": "\U000F10FE",
@ -4092,7 +4140,7 @@ md_icons = {
"leaf-off": "\U000F12D9", "leaf-off": "\U000F12D9",
"leak": "\U000F0DD7", "leak": "\U000F0DD7",
"leak-off": "\U000F0DD8", "leak-off": "\U000F0DD8",
"lecturn": "\U000F1AF0", "lectern": "\U000F1AF0",
"led-off": "\U000F032B", "led-off": "\U000F032B",
"led-on": "\U000F032C", "led-on": "\U000F032C",
"led-outline": "\U000F032D", "led-outline": "\U000F032D",
@ -4182,6 +4230,8 @@ md_icons = {
"lipstick": "\U000F13B5", "lipstick": "\U000F13B5",
"liquid-spot": "\U000F1826", "liquid-spot": "\U000F1826",
"liquor": "\U000F191E", "liquor": "\U000F191E",
"list-box": "\U000F1B7B",
"list-box-outline": "\U000F1B7C",
"list-status": "\U000F15AB", "list-status": "\U000F15AB",
"litecoin": "\U000F0A61", "litecoin": "\U000F0A61",
"loading": "\U000F0772", "loading": "\U000F0772",
@ -4362,6 +4412,8 @@ md_icons = {
"message-bookmark-outline": "\U000F15AD", "message-bookmark-outline": "\U000F15AD",
"message-bulleted": "\U000F06A2", "message-bulleted": "\U000F06A2",
"message-bulleted-off": "\U000F06A3", "message-bulleted-off": "\U000F06A3",
"message-check": "\U000F1B8A",
"message-check-outline": "\U000F1B8B",
"message-cog": "\U000F06F1", "message-cog": "\U000F06F1",
"message-cog-outline": "\U000F1172", "message-cog-outline": "\U000F1172",
"message-draw": "\U000F0363", "message-draw": "\U000F0363",
@ -4410,6 +4462,8 @@ md_icons = {
"metronome-tick": "\U000F07DB", "metronome-tick": "\U000F07DB",
"micro-sd": "\U000F07DC", "micro-sd": "\U000F07DC",
"microphone": "\U000F036C", "microphone": "\U000F036C",
"microphone-message": "\U000F050A",
"microphone-message-off": "\U000F050B",
"microphone-minus": "\U000F08B3", "microphone-minus": "\U000F08B3",
"microphone-off": "\U000F036D", "microphone-off": "\U000F036D",
"microphone-outline": "\U000F036E", "microphone-outline": "\U000F036E",
@ -4519,7 +4573,8 @@ md_icons = {
"more": "\U000F037B", "more": "\U000F037B",
"mortar-pestle": "\U000F1748", "mortar-pestle": "\U000F1748",
"mortar-pestle-plus": "\U000F03F1", "mortar-pestle-plus": "\U000F03F1",
"mosque": "\U000F1827", "mosque": "\U000F0D45",
"mosque-outline": "\U000F1827",
"mother-heart": "\U000F1314", "mother-heart": "\U000F1314",
"mother-nurse": "\U000F0D21", "mother-nurse": "\U000F0D21",
"motion": "\U000F15B2", "motion": "\U000F15B2",
@ -4594,8 +4649,11 @@ md_icons = {
"movie-star-outline": "\U000F1718", "movie-star-outline": "\U000F1718",
"mower": "\U000F166F", "mower": "\U000F166F",
"mower-bag": "\U000F1670", "mower-bag": "\U000F1670",
"mower-bag-on": "\U000F1B60",
"mower-on": "\U000F1B5F",
"muffin": "\U000F098C", "muffin": "\U000F098C",
"multicast": "\U000F1893", "multicast": "\U000F1893",
"multimedia": "\U000F1B97",
"multiplication": "\U000F0382", "multiplication": "\U000F0382",
"multiplication-box": "\U000F0383", "multiplication-box": "\U000F0383",
"mushroom": "\U000F07DF", "mushroom": "\U000F07DF",
@ -4624,6 +4682,7 @@ md_icons = {
"music-note-eighth-dotted": "\U000F0F71", "music-note-eighth-dotted": "\U000F0F71",
"music-note-half": "\U000F0389", "music-note-half": "\U000F0389",
"music-note-half-dotted": "\U000F0F72", "music-note-half-dotted": "\U000F0F72",
"music-note-minus": "\U000F1B89",
"music-note-off": "\U000F038A", "music-note-off": "\U000F038A",
"music-note-off-outline": "\U000F0F73", "music-note-off-outline": "\U000F0F73",
"music-note-outline": "\U000F0F74", "music-note-outline": "\U000F0F74",
@ -4846,7 +4905,13 @@ md_icons = {
"office-building-cog-outline": "\U000F194A", "office-building-cog-outline": "\U000F194A",
"office-building-marker": "\U000F1520", "office-building-marker": "\U000F1520",
"office-building-marker-outline": "\U000F1521", "office-building-marker-outline": "\U000F1521",
"office-building-minus": "\U000F1BAA",
"office-building-minus-outline": "\U000F1BAB",
"office-building-outline": "\U000F151F", "office-building-outline": "\U000F151F",
"office-building-plus": "\U000F1BA8",
"office-building-plus-outline": "\U000F1BA9",
"office-building-remove": "\U000F1BAC",
"office-building-remove-outline": "\U000F1BAD",
"oil": "\U000F03C7", "oil": "\U000F03C7",
"oil-lamp": "\U000F0F19", "oil-lamp": "\U000F0F19",
"oil-level": "\U000F1053", "oil-level": "\U000F1053",
@ -4967,6 +5032,8 @@ md_icons = {
"patio-heater": "\U000F0F80", "patio-heater": "\U000F0F80",
"patreon": "\U000F0882", "patreon": "\U000F0882",
"pause": "\U000F03E4", "pause": "\U000F03E4",
"pause-box": "\U000F00BC",
"pause-box-outline": "\U000F1B7A",
"pause-circle": "\U000F03E5", "pause-circle": "\U000F03E5",
"pause-circle-outline": "\U000F03E6", "pause-circle-outline": "\U000F03E6",
"pause-octagon": "\U000F03E7", "pause-octagon": "\U000F03E7",
@ -5253,6 +5320,7 @@ md_icons = {
"progress-clock": "\U000F0996", "progress-clock": "\U000F0996",
"progress-close": "\U000F110A", "progress-close": "\U000F110A",
"progress-download": "\U000F0997", "progress-download": "\U000F0997",
"progress-helper": "\U000F1BA2",
"progress-pencil": "\U000F1787", "progress-pencil": "\U000F1787",
"progress-question": "\U000F1522", "progress-question": "\U000F1522",
"progress-star": "\U000F1788", "progress-star": "\U000F1788",
@ -5351,12 +5419,14 @@ md_icons = {
"razor-single-edge": "\U000F1998", "razor-single-edge": "\U000F1998",
"react": "\U000F0708", "react": "\U000F0708",
"read": "\U000F0447", "read": "\U000F0447",
"receipt": "\U000F0449", "receipt": "\U000F0824",
"receipt-outline": "\U000F19DC", "receipt-outline": "\U000F04F7",
"receipt-text": "\U000F0449",
"receipt-text-check": "\U000F1A63", "receipt-text-check": "\U000F1A63",
"receipt-text-check-outline": "\U000F1A64", "receipt-text-check-outline": "\U000F1A64",
"receipt-text-minus": "\U000F1A65", "receipt-text-minus": "\U000F1A65",
"receipt-text-minus-outline": "\U000F1A66", "receipt-text-minus-outline": "\U000F1A66",
"receipt-text-outline": "\U000F19DC",
"receipt-text-plus": "\U000F1A67", "receipt-text-plus": "\U000F1A67",
"receipt-text-plus-outline": "\U000F1A68", "receipt-text-plus-outline": "\U000F1A68",
"receipt-text-remove": "\U000F1A69", "receipt-text-remove": "\U000F1A69",
@ -5495,7 +5565,9 @@ md_icons = {
"robot-off-outline": "\U000F167B", "robot-off-outline": "\U000F167B",
"robot-outline": "\U000F167A", "robot-outline": "\U000F167A",
"robot-vacuum": "\U000F070D", "robot-vacuum": "\U000F070D",
"robot-vacuum-alert": "\U000F1B5D",
"robot-vacuum-variant": "\U000F0908", "robot-vacuum-variant": "\U000F0908",
"robot-vacuum-variant-alert": "\U000F1B5E",
"rocket": "\U000F0463", "rocket": "\U000F0463",
"rocket-launch": "\U000F14DE", "rocket-launch": "\U000F14DE",
"rocket-launch-outline": "\U000F14DF", "rocket-launch-outline": "\U000F14DF",
@ -5633,6 +5705,8 @@ md_icons = {
"segment": "\U000F0ECB", "segment": "\U000F0ECB",
"select": "\U000F0485", "select": "\U000F0485",
"select-all": "\U000F0486", "select-all": "\U000F0486",
"select-arrow-down": "\U000F1B59",
"select-arrow-up": "\U000F1B58",
"select-color": "\U000F0D31", "select-color": "\U000F0D31",
"select-compare": "\U000F0AD9", "select-compare": "\U000F0AD9",
"select-drag": "\U000F0A6C", "select-drag": "\U000F0A6C",
@ -5803,6 +5877,7 @@ md_icons = {
"sign-pole": "\U000F14F8", "sign-pole": "\U000F14F8",
"sign-real-estate": "\U000F1118", "sign-real-estate": "\U000F1118",
"sign-text": "\U000F0782", "sign-text": "\U000F0782",
"sign-yield": "\U000F1BAF",
"signal": "\U000F04A2", "signal": "\U000F04A2",
"signal-2g": "\U000F0712", "signal-2g": "\U000F0712",
"signal-3g": "\U000F0713", "signal-3g": "\U000F0713",
@ -5821,7 +5896,8 @@ md_icons = {
"signature-freehand": "\U000F0DFC", "signature-freehand": "\U000F0DFC",
"signature-image": "\U000F0DFD", "signature-image": "\U000F0DFD",
"signature-text": "\U000F0DFE", "signature-text": "\U000F0DFE",
"silo": "\U000F0B49", "silo": "\U000F1B9F",
"silo-outline": "\U000F0B49",
"silverware": "\U000F04A3", "silverware": "\U000F04A3",
"silverware-clean": "\U000F0FDE", "silverware-clean": "\U000F0FDE",
"silverware-fork": "\U000F04A4", "silverware-fork": "\U000F04A4",
@ -6000,6 +6076,9 @@ md_icons = {
"speaker-message": "\U000F1B11", "speaker-message": "\U000F1B11",
"speaker-multiple": "\U000F0D38", "speaker-multiple": "\U000F0D38",
"speaker-off": "\U000F04C4", "speaker-off": "\U000F04C4",
"speaker-pause": "\U000F1B73",
"speaker-play": "\U000F1B72",
"speaker-stop": "\U000F1B74",
"speaker-wireless": "\U000F071F", "speaker-wireless": "\U000F071F",
"spear": "\U000F1845", "spear": "\U000F1845",
"speedometer": "\U000F04C5", "speedometer": "\U000F04C5",
@ -6149,7 +6228,17 @@ md_icons = {
"store-settings": "\U000F18D4", "store-settings": "\U000F18D4",
"store-settings-outline": "\U000F18D5", "store-settings-outline": "\U000F18D5",
"storefront": "\U000F07C7", "storefront": "\U000F07C7",
"storefront-check": "\U000F1B7D",
"storefront-check-outline": "\U000F1B7E",
"storefront-edit": "\U000F1B7F",
"storefront-edit-outline": "\U000F1B80",
"storefront-minus": "\U000F1B83",
"storefront-minus-outline": "\U000F1B84",
"storefront-outline": "\U000F10C1", "storefront-outline": "\U000F10C1",
"storefront-plus": "\U000F1B81",
"storefront-plus-outline": "\U000F1B82",
"storefront-remove": "\U000F1B85",
"storefront-remove-outline": "\U000F1B86",
"stove": "\U000F04DE", "stove": "\U000F04DE",
"strategy": "\U000F11D6", "strategy": "\U000F11D6",
"stretch-to-page": "\U000F0F2B", "stretch-to-page": "\U000F0F2B",
@ -6239,6 +6328,7 @@ md_icons = {
"table-edit": "\U000F04F0", "table-edit": "\U000F04F0",
"table-eye": "\U000F1094", "table-eye": "\U000F1094",
"table-eye-off": "\U000F13C3", "table-eye-off": "\U000F13C3",
"table-filter": "\U000F1B8C",
"table-furniture": "\U000F05BC", "table-furniture": "\U000F05BC",
"table-headers-eye": "\U000F121D", "table-headers-eye": "\U000F121D",
"table-headers-eye-off": "\U000F121E", "table-headers-eye-off": "\U000F121E",
@ -6272,7 +6362,6 @@ md_icons = {
"table-sync": "\U000F13A1", "table-sync": "\U000F13A1",
"table-tennis": "\U000F0E68", "table-tennis": "\U000F0E68",
"tablet": "\U000F04F6", "tablet": "\U000F04F6",
"tablet-android": "\U000F04F7",
"tablet-cellphone": "\U000F09A7", "tablet-cellphone": "\U000F09A7",
"tablet-dashboard": "\U000F0ECE", "tablet-dashboard": "\U000F0ECE",
"taco": "\U000F0762", "taco": "\U000F0762",
@ -6377,8 +6466,6 @@ md_icons = {
"text-search-variant": "\U000F1A7E", "text-search-variant": "\U000F1A7E",
"text-shadow": "\U000F0669", "text-shadow": "\U000F0669",
"text-short": "\U000F09A9", "text-short": "\U000F09A9",
"text-to-speech": "\U000F050A",
"text-to-speech-off": "\U000F050B",
"texture": "\U000F050C", "texture": "\U000F050C",
"texture-box": "\U000F0FE6", "texture-box": "\U000F0FE6",
"theater": "\U000F050D", "theater": "\U000F050D",
@ -6429,13 +6516,13 @@ md_icons = {
"timeline-check-outline": "\U000F1533", "timeline-check-outline": "\U000F1533",
"timeline-clock": "\U000F11FB", "timeline-clock": "\U000F11FB",
"timeline-clock-outline": "\U000F11FC", "timeline-clock-outline": "\U000F11FC",
"timeline-help": "\U000F0F99",
"timeline-help-outline": "\U000F0F9A",
"timeline-minus": "\U000F1534", "timeline-minus": "\U000F1534",
"timeline-minus-outline": "\U000F1535", "timeline-minus-outline": "\U000F1535",
"timeline-outline": "\U000F0BD2", "timeline-outline": "\U000F0BD2",
"timeline-plus": "\U000F0F96", "timeline-plus": "\U000F0F96",
"timeline-plus-outline": "\U000F0F97", "timeline-plus-outline": "\U000F0F97",
"timeline-question": "\U000F0F99",
"timeline-question-outline": "\U000F0F9A",
"timeline-remove": "\U000F1536", "timeline-remove": "\U000F1536",
"timeline-remove-outline": "\U000F1537", "timeline-remove-outline": "\U000F1537",
"timeline-text": "\U000F0BD3", "timeline-text": "\U000F0BD3",
@ -6601,6 +6688,7 @@ md_icons = {
"transition-masked": "\U000F0916", "transition-masked": "\U000F0916",
"translate": "\U000F05CA", "translate": "\U000F05CA",
"translate-off": "\U000F0E06", "translate-off": "\U000F0E06",
"translate-variant": "\U000F1B99",
"transmission-tower": "\U000F0D3E", "transmission-tower": "\U000F0D3E",
"transmission-tower-export": "\U000F192C", "transmission-tower-export": "\U000F192C",
"transmission-tower-import": "\U000F192D", "transmission-tower-import": "\U000F192D",
@ -6744,7 +6832,11 @@ md_icons = {
"vector-intersection": "\U000F055D", "vector-intersection": "\U000F055D",
"vector-line": "\U000F055E", "vector-line": "\U000F055E",
"vector-link": "\U000F0FE8", "vector-link": "\U000F0FE8",
"vector-point": "\U000F055F", "vector-point": "\U000F01C4",
"vector-point-edit": "\U000F09E8",
"vector-point-minus": "\U000F1B78",
"vector-point-plus": "\U000F1B79",
"vector-point-select": "\U000F055F",
"vector-polygon": "\U000F0560", "vector-polygon": "\U000F0560",
"vector-polygon-variant": "\U000F1856", "vector-polygon-variant": "\U000F1856",
"vector-polyline": "\U000F0561", "vector-polyline": "\U000F0561",
@ -6912,6 +7004,7 @@ md_icons = {
"water-alert-outline": "\U000F1503", "water-alert-outline": "\U000F1503",
"water-boiler": "\U000F0F92", "water-boiler": "\U000F0F92",
"water-boiler-alert": "\U000F11B3", "water-boiler-alert": "\U000F11B3",
"water-boiler-auto": "\U000F1B98",
"water-boiler-off": "\U000F11B4", "water-boiler-off": "\U000F11B4",
"water-check": "\U000F1504", "water-check": "\U000F1504",
"water-check-outline": "\U000F1505", "water-check-outline": "\U000F1505",
@ -6951,6 +7044,7 @@ md_icons = {
"weather-cloudy-alert": "\U000F0F2F", "weather-cloudy-alert": "\U000F0F2F",
"weather-cloudy-arrow-right": "\U000F0E6E", "weather-cloudy-arrow-right": "\U000F0E6E",
"weather-cloudy-clock": "\U000F18F6", "weather-cloudy-clock": "\U000F18F6",
"weather-dust": "\U000F1B5A",
"weather-fog": "\U000F0591", "weather-fog": "\U000F0591",
"weather-hail": "\U000F0592", "weather-hail": "\U000F0592",
"weather-hazy": "\U000F0F30", "weather-hazy": "\U000F0F30",
@ -7072,6 +7166,7 @@ md_icons = {
"window-restore": "\U000F05B2", "window-restore": "\U000F05B2",
"window-shutter": "\U000F111C", "window-shutter": "\U000F111C",
"window-shutter-alert": "\U000F111D", "window-shutter-alert": "\U000F111D",
"window-shutter-auto": "\U000F1BA3",
"window-shutter-cog": "\U000F1A8A", "window-shutter-cog": "\U000F1A8A",
"window-shutter-open": "\U000F111E", "window-shutter-open": "\U000F111E",
"window-shutter-settings": "\U000F1A8B", "window-shutter-settings": "\U000F1A8B",
@ -7084,7 +7179,12 @@ md_icons = {
"wrap": "\U000F05B6", "wrap": "\U000F05B6",
"wrap-disabled": "\U000F0BDF", "wrap-disabled": "\U000F0BDF",
"wrench": "\U000F05B7", "wrench": "\U000F05B7",
"wrench-check": "\U000F1B8F",
"wrench-check-outline": "\U000F1B90",
"wrench-clock": "\U000F19A3", "wrench-clock": "\U000F19A3",
"wrench-clock-outline": "\U000F1B93",
"wrench-cog": "\U000F1B91",
"wrench-cog-outline": "\U000F1B92",
"wrench-outline": "\U000F0BE0", "wrench-outline": "\U000F0BE0",
"xamarin": "\U000F0845", "xamarin": "\U000F0845",
"xml": "\U000F05C0", "xml": "\U000F05C0",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 29 KiB

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

View File

@ -1 +0,0 @@
{"quad_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "quad_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "quad_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 43 KiB

View File

@ -1 +0,0 @@
{"rec_shadow-1.png": {"20": [2, 266, 256, 128], "21": [260, 266, 256, 128], "22": [518, 266, 256, 128], "23": [776, 266, 256, 128], "3": [260, 136, 256, 128], "2": [2, 136, 256, 128], "5": [776, 136, 256, 128], "4": [518, 136, 256, 128], "7": [260, 6, 256, 128], "6": [2, 6, 256, 128], "9": [776, 6, 256, 128], "8": [518, 6, 256, 128]}, "rec_shadow-0.png": {"11": [518, 266, 256, 128], "10": [260, 266, 256, 128], "13": [2, 136, 256, 128], "12": [776, 266, 256, 128], "15": [518, 136, 256, 128], "14": [260, 136, 256, 128], "17": [2, 6, 256, 128], "16": [776, 136, 256, 128], "19": [518, 6, 256, 128], "18": [260, 6, 256, 128], "1": [776, 6, 256, 128], "0": [2, 266, 256, 128]}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 28 KiB

View File

@ -1 +0,0 @@
{"rec_st_shadow-0.png": {"11": [262, 138, 128, 256], "10": [132, 138, 128, 256], "13": [522, 138, 128, 256], "12": [392, 138, 128, 256], "15": [782, 138, 128, 256], "14": [652, 138, 128, 256], "16": [912, 138, 128, 256], "0": [2, 138, 128, 256]}, "rec_st_shadow-1.png": {"20": [522, 138, 128, 256], "21": [652, 138, 128, 256], "17": [2, 138, 128, 256], "23": [912, 138, 128, 256], "19": [262, 138, 128, 256], "18": [132, 138, 128, 256], "22": [782, 138, 128, 256], "1": [392, 138, 128, 256]}, "rec_st_shadow-2.png": {"3": [132, 138, 128, 256], "2": [2, 138, 128, 256], "5": [392, 138, 128, 256], "4": [262, 138, 128, 256], "7": [652, 138, 128, 256], "6": [522, 138, 128, 256], "9": [912, 138, 128, 256], "8": [782, 138, 128, 256]}}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

View File

@ -1 +0,0 @@
{"round_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "round_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "round_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}}

View File

@ -0,0 +1,9 @@
from kivy.tests.common import GraphicUnitTest
from kivymd.app import MDApp
class BaseTest(GraphicUnitTest):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.app = MDApp() # NOQA

View File

@ -35,8 +35,15 @@ assert "Icons" in LabelBase._fonts.keys() # NOQA
images = os.listdir(kivymd.images_path) images = os.listdir(kivymd.images_path)
print(images) print(images)
assert "logo" in images
assert "alpha_layer.png" in images
assert "black.png" in images
assert "blue.png" in images
assert "red.png" in images
assert "green.png" in images
assert "yellow.png" in images
assert "folder.png" in images assert "folder.png" in images
assert "rec_shadow.atlas" in images assert "transparent.png" in images
""" """
) )
pyi_main.run( pyi_main.run(

View File

@ -0,0 +1,24 @@
from kivymd.tests.base_test import BaseTest
class BackdropTest(BaseTest):
def test_backdrop_raw_app(self):
from kivymd.uix.backdrop import MDBackdrop
from kivymd.uix.backdrop.backdrop import (
MDBackdropBackLayer,
MDBackdropFrontLayer,
)
from kivymd.uix.screen import MDScreen
from kivymd.uix.widget import MDWidget
self.render(
MDScreen(
MDBackdrop(
MDBackdropBackLayer(MDWidget()),
MDBackdropFrontLayer(MDWidget()),
id="backdrop",
title="Example Backdrop",
header_text="Menu:",
)
)
)

View File

@ -0,0 +1,32 @@
from kivymd.tests.base_test import BaseTest
class BottomNavigationTest(BaseTest):
def test_bottom_navigation_m3_style_raw_app(self):
from kivymd.uix.bottomnavigation import (
MDBottomNavigation,
MDBottomNavigationItem,
)
from kivymd.uix.screen import MDScreen
self.app.theme_cls.material_style = "M3"
self.render(
MDScreen(
MDBottomNavigation(
MDBottomNavigationItem(
name="screen 1",
text="Mail",
icon="gmail",
),
MDBottomNavigationItem(
name="screen 2",
text="Twitter",
icon="twitter",
badge_icon="numeric-10",
),
panel_color="#eeeaea",
selected_color_background="#97ecf8",
text_color_active="red",
)
)
)

View File

@ -0,0 +1,25 @@
from kivymd.tests.base_test import BaseTest
class CardTest(BaseTest):
def test_card_m3_style_raw_app(self):
from kivymd.uix.behaviors import RoundedRectangularElevationBehavior
from kivymd.uix.card import MDCard
from kivymd.uix.screen import MDScreen
class MD3Card(MDCard, RoundedRectangularElevationBehavior):
pass
self.app.theme_cls.material_style = "M3"
self.render(
MDScreen(
MD3Card(
size_hint=(None, None),
pos_hint={"center_x": 0.5, "center_y": 0.5},
size=("200dp", "100dp"),
line_color=(0.2, 0.2, 0.2, 0.8),
style="elevated",
md_bg_color="lightblue",
)
)
)

View File

@ -0,0 +1,16 @@
from kivymd.tests.base_test import BaseTest
class ChipTest(BaseTest):
def test_chip_raw_app(self):
from kivymd.uix.chip import MDChip
from kivymd.uix.screen import MDScreen
self.render(
MDScreen(
MDChip(
text="Portland",
pos_hint={"center_x": 0.5, "center_y": 0.5},
)
)
)

View File

@ -1,14 +1,13 @@
def test_create_project(): def test_create_project():
import os import os
import sys
os.system( os.system(
f"{sys.executable} -m kivymd.tools.patterns.create_project " f"python3.10 -m kivymd.tools.patterns.create_project "
f"MVC " f"MVC "
f"{os.path.expanduser('~')} " f"{os.path.expanduser('~')} "
f"TestProject " f"TestProject "
f"{sys.executable} " f"python3.10 "
f"master " f"stable "
f"--name_screen TestProjectScreen " f"--name_screen TestProjectScreen "
f"--name_database restdb " f"--name_database restdb "
f"--use_hotreload yes" f"--use_hotreload yes"

View File

@ -0,0 +1,24 @@
from kivymd.tests.base_test import BaseTest
class FitImageTest(BaseTest):
def test_fitimage_raw_app(self):
import os
from kivymd import images_path
from kivymd.uix.fitimage import FitImage
from kivymd.uix.screen import MDScreen
self.render(
MDScreen(
FitImage(
source=os.path.join(
images_path, "logo", "kivymd-icon-512.png"
),
size_hint=(0.5, 0.5),
pos_hint={"center_x": 0.5, "center_y": 0.5},
radius=[36, 36, 0, 0],
mipmap=True,
)
)
)

View File

@ -0,0 +1,39 @@
from kivymd.tests.base_test import BaseTest
class ImageListTest(BaseTest):
def test_imagelist_raw_app(self):
import os
from kivymd import images_path
from kivymd.uix.button import MDIconButton
from kivymd.uix.imagelist import MDSmartTile
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import MDScreen
self.render(
MDScreen(
MDSmartTile(
MDIconButton(
icon="heart-outline",
theme_icon_color="Custom",
icon_color="red",
pos_hint={"center_y": 0.5},
),
MDLabel(
text="Julia and Julie",
bold=True,
color="white",
),
radius=24,
box_radius=[0, 0, 24, 24],
box_color="grey",
source=os.path.join(
images_path, "logo", "kivymd-icon-512.png"
),
pos_hint={"center_x": 0.5, "center_y": 0.5},
size_hint=(None, None),
size=("320dp", "320dp"),
)
)
)

View File

@ -0,0 +1,67 @@
from kivymd.tests.base_test import BaseTest
class ListTest(BaseTest):
def test_list_raw_app(self):
import os
from kivymd import images_path
from kivymd.uix.list import (
IconLeftWidget,
IconRightWidget,
ImageLeftWidget,
IRightBodyTouch,
MDList,
OneLineAvatarIconListItem,
OneLineAvatarListItem,
OneLineIconListItem,
OneLineListItem,
ThreeLineListItem,
TwoLineListItem,
)
from kivymd.uix.screen import MDScreen
from kivymd.uix.scrollview import MDScrollView
from kivymd.uix.selectioncontrol import MDCheckbox
class RightCheckbox(IRightBodyTouch, MDCheckbox):
pass
self.render(
MDScreen(
MDScrollView(
MDList(
OneLineListItem(text="Text"),
TwoLineListItem(
text="Text", secondary_text="secondary text"
),
ThreeLineListItem(
text="Text",
secondary_text="secondary text",
tertiary_text="tertiary text",
),
OneLineAvatarListItem(
ImageLeftWidget(
source=os.path.join(
images_path, "logo", "kivymd-icon-512.png"
)
),
text="Text",
),
OneLineIconListItem(
IconLeftWidget(icon="plus"),
text="Text",
),
OneLineAvatarIconListItem(
IconLeftWidget(icon="plus"),
IconRightWidget(icon="minus"),
text="Text",
),
OneLineAvatarIconListItem(
IconLeftWidget(icon="plus"),
RightCheckbox(),
text="Text",
),
)
)
)
)

View File

@ -0,0 +1,94 @@
from kivymd.tests.base_test import BaseTest
class NavigationDrawerTest(BaseTest):
def test_navigationdrawer_raw_app(self):
from kivymd.uix.navigationdrawer import (
MDNavigationDrawer,
MDNavigationDrawerDivider,
MDNavigationDrawerHeader,
MDNavigationDrawerItem,
MDNavigationDrawerLabel,
MDNavigationDrawerMenu,
MDNavigationLayout,
)
from kivymd.uix.screen import MDScreen
from kivymd.uix.screenmanager import MDScreenManager
from kivymd.uix.toolbar import MDTopAppBar
class DrawerClickableItem(MDNavigationDrawerItem):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.focus_color = "#e7e4c0"
self.unfocus_color = "#f7f4e7"
self.text_color = "#4a4939"
self.icon_color = "#4a4939"
self.ripple_color = "#c5bdd2"
self.selected_color = "#0c6c4d"
class DrawerLabelItem(MDNavigationDrawerItem):
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.bg_color = "#f7f4e7"
self.text_color = "#4a4939"
self.icon_color = "#4a4939"
_no_ripple_effect = True # NOQA
self.app.theme_cls.material_style = "M3"
self.render(
MDNavigationLayout(
MDScreenManager(
MDScreen(
MDTopAppBar(
title="Navigation Drawer",
elevation=10,
pos_hint={"top": 1},
md_bg_color="#e7e4c0",
specific_text_color="#4a4939",
left_action_items=[
["menu", lambda x: self.nav_drawer_open()]
],
)
)
),
MDNavigationDrawer(
MDNavigationDrawerMenu(
MDNavigationDrawerHeader(
title="Header title",
title_color="#4a4939",
text="Header text",
spacing="4dp",
padding=("12dp", 0, 0, "56dp"),
),
MDNavigationDrawerLabel(
text="Mail",
),
DrawerClickableItem(
icon="gmail",
right_text="+99",
text_right_color="#4a4939",
text="Inbox",
radius=24,
),
DrawerClickableItem(
icon="send",
text="Outbox",
radius=24,
),
MDNavigationDrawerDivider(),
MDNavigationDrawerLabel(
text="Labels",
),
DrawerLabelItem(
icon="information-outline",
text="Label",
),
DrawerLabelItem(
icon="information-outline",
text="Label",
),
),
id="nav_drawer",
),
)
)

View File

@ -0,0 +1,14 @@
from kivymd.tests.base_test import BaseTest
class TabTest(BaseTest):
def test_tab_raw_app(self):
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.tab import MDTabs, MDTabsBase
class Tab(MDFloatLayout, MDTabsBase):
pass
tab = MDTabs()
tab.add_widget(Tab(title="Tab"))
self.render(tab)

View File

@ -0,0 +1,72 @@
# from kivy.clock import Clock
# from kivy.uix.textinput import TextInput
from kivymd.tests.base_test import BaseTest
class TextFieldTest(BaseTest):
def test_textfield_raw_app(self):
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.screen import MDScreen
from kivymd.uix.textfield import MDTextField
# def set_text():
# for widget in self.screen.ids.box.children:
# if issubclass(widget.__class__, TextInput):
# widget.text = "Input text"
self.render(
MDScreen(
MDBoxLayout(
MDTextField(
hint_text="Label",
helper_text="Error massage",
mode="rectangle",
max_text_length=5,
),
MDTextField(
icon_left="git",
hint_text="Label",
helper_text="Error massage",
mode="rectangle",
),
MDTextField(
icon_left="git",
hint_text="Label",
helper_text="Error massage",
mode="fill",
),
MDTextField(
hint_text="Label",
helper_text="Error massage",
mode="fill",
),
MDTextField(
hint_text="Label",
helper_text="Error massage",
),
MDTextField(
icon_left="git",
hint_text="Label",
helper_text="Error massage",
),
MDTextField(
hint_text="Round mode",
mode="round",
max_text_length=15,
helper_text="Massage",
),
MDFlatButton(
text="SET TEXT",
pos_hint={"center_x": 0.5},
),
id="box",
orientation="vertical",
spacing="20dp",
adaptive_height=True,
size_hint_x=0.8,
pos_hint={"center_x": 0.5, "center_y": 0.5},
)
)
)

File diff suppressed because it is too large Load Diff

View File

@ -298,8 +298,9 @@ class MDApp(BaseApp):
from kivy.core.window import Window from kivy.core.window import Window
from kivy.utils import get_color_from_hex from kivy.utils import get_color_from_hex
Window.clearcolor = get_color_from_hex("#e50000") scroll = Factory.MDScrollView(
scroll = Factory.ScrollView(scroll_y=0) scroll_y=0, md_bg_color=get_color_from_hex("#e50000")
)
lbl = Factory.Label( lbl = Factory.Label(
text_size=(Window.width - 100, None), text_size=(Window.width - 100, None),
size_hint_y=None, size_hint_y=None,

View File

@ -13,6 +13,18 @@ from pathlib import Path
import kivymd import kivymd
datas = [ datas = [
# Add `.frag` files from the `kivymd/data/glsl/elevation` directory.
(
str(Path(kivymd.glsl_path).joinpath("elevation")) + os.sep,
str(
Path("kivymd").joinpath(
str(Path(kivymd.glsl_path)).split(str(Path("kivymd")) + os.sep)[
1
]
+ f"{os.sep}elevation"
)
),
),
# Add `.ttf` files from the `kivymd/fonts` directory. # Add `.ttf` files from the `kivymd/fonts` directory.
( (
kivymd.fonts_path, kivymd.fonts_path,

View File

@ -1,3 +0,0 @@
%s
def get_view(self) -> %s:
return self.view

View File

@ -1,26 +0,0 @@
# FILE TO FIND AND CREATE LOCALIZATION FILES FOR YOUR APPLICATION. \
\
In this file, you can specify in which files of your project to search for \
localization strings. \
These files should be listed in the below command: \
\
\
xgettext -Lpython --output=messages.pot --from-code=utf-8 \
path/to/file-1 \
path/to/file-2 \
...
.PHONY: po mo
po:
xgettext -Lpython --output=messages.pot --from-code=utf-8 \
View/%s/%s.kv \
View/%s/%s.py
msgmerge --update --no-fuzzy-matching --backup=off data/locales/po/en.po messages.pot
msgmerge --update --no-fuzzy-matching --backup=off data/locales/po/ru.po messages.pot
mo:
mkdir -p data/locales/en/LC_MESSAGES
mkdir -p data/locales/ru/LC_MESSAGES
msgfmt -c -o data/locales/en/LC_MESSAGES/%s.mo data/locales/po/en.po
msgfmt -c -o data/locales/ru/LC_MESSAGES/%s.mo data/locales/po/ru.po

View File

@ -1,33 +0,0 @@
# The model implements the observer pattern. This means that the class must
# support adding, removing, and alerting observers. In this case, the model is
# completely independent of controllers and views. It is important that all
# registered observers implement a specific method that will be called by the
# model when they are notified (in this case, it is the `model_is_changed`
# method). For this, observers must be descendants of an abstract class,
# inheriting which, the `model_is_changed` method must be overridden.
class BaseScreenModel:
"""Implements a base class for model modules."""
_observers = []
def add_observer(self, observer) -> None:
self._observers.append(observer)
def remove_observer(self, observer) -> None:
self._observers.remove(observer)
def notify_observers(self, name_screen: str) -> None:
"""
Method that will be called by the observer when the model data changes.
:param name_screen:
name of the view for which the method should be called
:meth:`model_is_changed`.
"""
for observer in self._observers:
if observer.name == name_screen:
observer.model_is_changed()
break

View File

@ -1,16 +0,0 @@
# Of course, "very flexible Python" allows you to do without an abstract
# superclass at all or use the clever exception `NotImplementedError`. In my
# opinion, this can negatively affect the architecture of the application.
# I would like to point out that using Kivy, one could use the on-signaling
# model. In this case, when the state changes, the model will send a signal
# that can be received by all attached observers. This approach seems less
# universal - you may want to use a different library in the future.
class Observer:
"""Abstract superclass for all observers."""
def model_is_changed(self):
"""
The method that will be called on the observer when the model changes.
"""

View File

@ -1,72 +0,0 @@
#:import images_path kivymd.images_path
#:import colors kivymd.color_definitions.colors
#:import get_color_from_hex kivy.utils.get_color_from_hex
<%s>
FitImage:
source:
( \
f"{images_path}restdb-logo.png" \
if root.model.database.name == "RestDB" else \
f"{images_path}firebase-logo.png" \
) \
if hasattr(root.model, "database") else \
f"{images_path}transparent.png"
MDBoxLayout:
orientation: "vertical"
MDToolbar:
id: toolbar
title: "%s"
right_action_items: [["web", lambda x: %s]]
md_bg_color:
( \
get_color_from_hex(colors["Yellow"]["700"]) \
if root.model.database.name == "Firebase" else \
get_color_from_hex(colors["Blue"]["300"]) \
) \
if hasattr(root.model, "database") else \
app.theme_cls.primary_color
MDFloatLayout:
MDBoxLayout:
orientation: "vertical"
adaptive_height: True
size_hint_x: None
width: root.width - dp(72)
radius: 12
padding: "12dp"
md_bg_color: 1, 1, 1, .5
pos_hint: {"center_x": .5, "center_y": .5}
MDLabel:
id: prev_label
text: %s
font_style: "H6"
adaptive_height: True
halign: "center"
color: 1, 1, 1, 1
MDBoxLayout:
orientation: "vertical"
adaptive_height: True
padding: "50dp"
spacing: "20dp"
MDTextField:
hint_text: %s
on_text: root.controller.set_user_data("login", self.text)
MDTextField:
hint_text: %s
on_text: root.controller.set_user_data("password", self.text)
MDFillRoundFlatButton:
text: %s
on_release: root.controller.on_tap_button_login()
pos_hint: {"center_x": .5, "center_y": .1}
md_bg_color: toolbar.md_bg_color

View File

@ -1,15 +0,0 @@
%s
from View.base_screen import BaseScreenView
class %s(BaseScreenView):
"""Implements the login start screen in the user application."""
%s
def model_is_changed(self) -> None:
"""
Called whenever any change has occurred in the data model.
The view in this method tracks these changes and updates the UI
according to these changes.
"""
%s

View File

@ -1,47 +0,0 @@
from kivy.properties import ObjectProperty
from kivymd.app import MDApp
from kivymd.theming import ThemableBehavior
from kivymd.uix.screen import MDScreen
from Utility.observer import Observer
class BaseScreenView(ThemableBehavior, MDScreen, Observer):
"""
A base class that implements a visual representation of the model data
:class:`~Model.%s.%s`.
The view class must be inherited from this class.
"""
controller = ObjectProperty()
"""
Controller object - :class:`~Controller.%s.%s`.
:attr:`controller` is an :class:`~kivy.properties.ObjectProperty`
and defaults to `None`.
"""
model = ObjectProperty()
"""
Model object - :class:`~Model.%s.%s`.
:attr:`model` is an :class:`~kivy.properties.ObjectProperty`
and defaults to `None`.
"""
manager_screens = ObjectProperty()
"""
Screen manager object - :class:`~kivy.uix.screenmanager.ScreenManager`.
:attr:`manager_screens` is an :class:`~kivy.properties.ObjectProperty`
and defaults to `None`.
"""
def __init__(self, **kw):
super().__init__(**kw)
# Often you need to get access to the application object from the view
# class. You can do this using this attribute.
self.app = MDApp.get_running_app()
# Adding a view class as observer.
self.model.add_observer(self)

View File

@ -1,13 +0,0 @@
# The screens dictionary contains the objects of the models and controllers
# of the screens of the application.
from Model.%s import %s
from Controller.%s import %s
screens = {
%s: {
"model": %s,
"controller": %s,
},
}

View File

@ -1,54 +0,0 @@
"""
The entry point to the application.
The application uses the MVC template. Adhering to the principles of clean
architecture means ensuring that your application is easy to test, maintain,
and modernize.
You can read more about this template at the links below:
https://github.com/HeaTTheatR/LoginAppMVC
https://en.wikipedia.org/wiki/Modelviewcontroller
"""
from typing import NoReturn
from kivy.uix.screenmanager import ScreenManager%s
from kivymd.app import MDApp
from View.screens import screens%s
%s
class %s(MDApp):%s
def __init__(self, **kwargs):
super().__init__(**kwargs)%s
self.load_all_kv_files(self.directory)
# This is the screen manager that will contain all the screens of your
# application.
self.manager_screens = ScreenManager()
%s
def build(self) -> ScreenManager:
self.generate_application_screens()
return self.manager_screens
def generate_application_screens(self) -> NoReturn:
"""
Creating and adding screens to the screen manager.
You should not change this cycle unnecessarily. He is self-sufficient.
If you need to add any screen, open the `View.screens.py` module and
see how new screens are added according to the given application
architecture.
"""
for i, name_screen in enumerate(screens.keys()):
model = screens[name_screen]["model"](%s)
controller = screens[name_screen]["controller"](model)
view = controller.get_view()
view.manager_screens = self.manager_screens
view.name = name_screen
self.manager_screens.add_widget(view)
%s%s
%s().run()

View File

@ -0,0 +1,210 @@
"""
The script creates a new View package
=====================================
The script creates a new View package in an existing project with an MVC
template created using the create_project utility.
.. versionadded:: 1.0.0
.. seealso::
`Utility create_project <https://kivymd.readthedocs.io/en/latest/api/kivymd/tools/patterns/create_project/>`_
.. rubric:: Use a clean architecture for your applications.
To add a new view to an existing project that was created using the
`create_project` utility, use the following command::
kivymd.add_view \\
name_pattern \\
path_to_project \\
name_view
Example command::
kivymd.add_view \\
MVC \\
/Users/macbookair/Projects \\
NewScreen
You can also add new views with responsive behavior to an existing project::
kivymd.add_view \\
MVC \\
/Users/macbookair/Projects \\
NewScreen \\
--use_responsive yes
For more information about adaptive design,
`see here <https://kivymd.readthedocs.io/en/latest/components/responsivelayout/>`_.
"""
__all__ = [
"main",
]
import os
import re
from kivy import Logger
from kivymd.tools.argument_parser import ArgumentParserWithHelp
from kivymd.tools.patterns.create_project import (
chek_camel_case_name_project,
create_common_responsive_module,
create_controller,
create_model,
create_view,
)
screens_data = """%s
screens = {%s
}"""
screns_comment = """# The screen's dictionary contains the objects of the models and controllers
# of the screens of the application.
"""
def main():
"""The function of adding a new view to the project."""
global screens_data
parser = create_argument_parser()
args = parser.parse_args()
# pattern_name isn't used currently, will be used if new patterns is added in future
pattern_name = args.pattern # noqa F841
path_to_project = args.directory
name_view = args.name
use_responsive = args.use_responsive
if not os.path.exists(path_to_project):
parser.error(f"Project <{path_to_project}> does not exist...")
if name_view[-6:] != "Screen":
parser.error(
f"The name of the <{name_view}> screen should contain the word "
f"'Screen' at the end.\n"
"For example - '--name_screen MyFirstScreen ...'"
)
if name_view in os.listdir(os.path.join(path_to_project, "View")):
parser.error(
f"The <{name_view}> view also exists in the <{path_to_project}> project..."
)
# Create model.
name_database = (
"yes"
if "database.py" in os.listdir(os.path.join(path_to_project, "Model"))
else "no"
)
module_name = chek_camel_case_name_project(name_view)
if not module_name:
parser.error(
"The name of the screen should be written in camel case style. "
"\nFor example - 'MyFirstScreen'"
)
module_name = "_".join([name.lower() for name in module_name])
path_to_project = path_to_project
create_model(name_view, module_name, name_database, path_to_project)
# Create controller.
# FIXME: This is not a very good solution in order to understand whether
# a project uses a hot reload or not. Because the string
# 'from kivymd.tools.hotreload.app import MDApp' in the project can just
# be commented out and the project does not actually use hot reload.
with open(os.path.join(path_to_project, "main.py")) as main_module:
if "from kivymd.tools.hotreload.app import MDApp" in main_module.read():
use_hotreload = "yes"
else:
use_hotreload = "no"
create_controller(
name_view, module_name, use_hotreload, path_to_project
)
# Create View.
if use_responsive == "no":
create_view(name_view, module_name, [], path_to_project)
else:
create_view(name_view, module_name, [name_view], path_to_project)
create_common_responsive_module([name_view], path_to_project)
# Create 'View.screens.py module'.
create_screens_data(name_view, module_name, path_to_project)
Logger.info(
f"KivyMD: The {name_view} view has been added to the project..."
)
def create_screens_data(
name_view: str, module_name: str, path_to_project: str
) -> None:
with open(
os.path.join(path_to_project, "View", "screens.py")
) as screen_module:
screen_module = screen_module.read()
imports = re.findall(
"from Model.*Model|from Controller.*Controller", screen_module
)
screens = ""
path_to_view = os.path.join(path_to_project, "View")
for name in os.listdir(path_to_view):
if os.path.isdir(os.path.join(path_to_view, name)):
res = re.findall("[A-Z][a-z]*", name)
if res and len(res) == 2 and res[-1] == "Screen":
screens += (
"\n '%s': {"
"\n 'model': %s,"
"\n 'controller': %s,"
"\n },"
% (
f"{res[0].lower()} {res[1].lower()}",
f'{"".join(res)}Model',
f'{"".join(res)}Controller',
)
)
imports.append(f"from Model.{module_name} import {name_view}Model")
imports.append(
f"from Controller.{module_name} import {name_view}Controller"
)
imports.insert(0, screns_comment)
screens = screens_data % ("\n".join(imports), screens)
with open(
os.path.join(path_to_project, "View", "screens.py"), "w"
) as screen_module:
screen_module.write(screens)
def create_argument_parser() -> ArgumentParserWithHelp:
parser = ArgumentParserWithHelp(
prog="create_project.py",
allow_abbrev=False,
)
parser.add_argument(
"pattern",
help="the name of the pattern with which the project will be created.",
)
parser.add_argument(
"directory",
help="the directory of the project to which you want to add a new view.",
)
parser.add_argument(
"name",
help="the name of the view to add to an existing project.",
)
parser.add_argument(
"--use_responsive",
default="no",
help="whether to create a view with responsive behavior.",
)
return parser
if __name__ == "__main__":
main()

File diff suppressed because it is too large Load Diff

View File

@ -1,4 +1,4 @@
# Copyright (c) 2019-2021 Artem Bulgakov # Copyright (c) 2019-2022 Artem Bulgakov
# #
# This file is distributed under the terms of the same license, # This file is distributed under the terms of the same license,
# as the Kivy framework. # as the Kivy framework.

View File

@ -1,4 +1,4 @@
# Copyright (c) 2019-2021 Artem Bulgakov # Copyright (c) 2019-2022 Artem Bulgakov
# #
# This file is distributed under the terms of the same license, # This file is distributed under the terms of the same license,
# as the Kivy framework. # as the Kivy framework.

View File

@ -1,4 +1,4 @@
# Copyright (c) 2019-2021 Artem Bulgakov # Copyright (c) 2019-2022 Artem Bulgakov
# #
# This file is distributed under the terms of the same license, # This file is distributed under the terms of the same license,
# as the Kivy framework. # as the Kivy framework.

View File

@ -10,7 +10,7 @@ with some widget properties. For example:
AnchorLayout AnchorLayout
------------ ------------
.. code-block:: .. code-block:: kv
AnchorLayout: AnchorLayout:
canvas: canvas:
@ -20,65 +20,13 @@ AnchorLayout
pos: self.pos pos: self.pos
size: self.size size: self.size
AnchorLayout MDAnchorLayout
------------
.. code-block::
MDBoxLayout:
md_bg_color: app.theme_cls.primary_color
Available options are:
----------------------
- adaptive_height_
- adaptive_width_
- adaptive_size_
.. adaptive_height:
adaptive_height
---------------
.. code-block:: kv
adaptive_height: True
Equivalent
.. code-block:: kv
size_hint_y: None
height: self.minimum_height
.. adaptive_width:
adaptive_width
-------------- --------------
.. code-block:: kv .. code-block:: kv
adaptive_width: True MDAnchorLayout:
md_bg_color: app.theme_cls.primary_color
Equivalent
.. code-block:: kv
size_hint_x: None
height: self.minimum_width
.. adaptive_size:
adaptive_size
-------------
.. code-block:: kv
adaptive_size: True
Equivalent
.. code-block:: kv
size_hint: None, None
size: self.minimum_size
""" """
__all__ = ("MDAnchorLayout",) __all__ = ("MDAnchorLayout",)
@ -86,7 +34,11 @@ __all__ = ("MDAnchorLayout",)
from kivy.uix.anchorlayout import AnchorLayout from kivy.uix.anchorlayout import AnchorLayout
from kivymd.uix import MDAdaptiveWidget from kivymd.uix import MDAdaptiveWidget
from kivymd.uix.behaviors import DeclarativeBehavior
class MDAnchorLayout(AnchorLayout, MDAdaptiveWidget): class MDAnchorLayout(DeclarativeBehavior, AnchorLayout, MDAdaptiveWidget):
pass """
Anchor layout class. For more information, see in the
:class:`~kivy.uix.anchorlayout.AnchorLayout` class documentation.
"""

View File

@ -35,8 +35,8 @@
if not root.front_layer_color \ if not root.front_layer_color \
else root.front_layer_color else root.front_layer_color
radius: radius:
[root.radius_left, root.radius_left, [root.radius_left, root.radius_right,
root.radius_right, root.radius_right] 0, 0]
OneLineListItem: OneLineListItem:
id: header_button id: header_button

View File

@ -31,84 +31,147 @@ Usage
Example Example
------- -------
.. code-block:: python .. tabs::
from kivy.lang import Builder .. tab:: Declarative KV styles
from kivymd.uix.screen import MDScreen .. code-block:: python
from kivymd.app import MDApp
# Your layouts. from kivy.lang import Builder
Builder.load_string(
''' from kivymd.uix.screen import MDScreen
#:import Window kivy.core.window.Window from kivymd.app import MDApp
#:import IconLeftWidget kivymd.uix.list.IconLeftWidget
# Your layouts.
Builder.load_string(
'''
#:import os os
#:import Window kivy.core.window.Window
#:import IconLeftWidget kivymd.uix.list.IconLeftWidget
#:import images_path kivymd.images_path
<ItemBackdropFrontLayer@TwoLineAvatarListItem> <ItemBackdropFrontLayer@TwoLineAvatarListItem>
icon: "android" icon: "android"
IconLeftWidget: IconLeftWidget:
icon: root.icon icon: root.icon
<MyBackdropFrontLayer@ItemBackdropFrontLayer> <MyBackdropFrontLayer@ItemBackdropFrontLayer>
backdrop: None backdrop: None
text: "Lower the front layer" text: "Lower the front layer"
secondary_text: " by 50 %" secondary_text: " by 50 %"
icon: "transfer-down" icon: "transfer-down"
on_press: root.backdrop.open(-Window.height / 2) on_press: root.backdrop.open(-Window.height / 2)
pos_hint: {"top": 1} pos_hint: {"top": 1}
_no_ripple_effect: True _no_ripple_effect: True
<MyBackdropBackLayer@Image> <MyBackdropBackLayer@Image>
size_hint: .8, .8 size_hint: .8, .8
source: "data/logo/kivy-icon-512.png" source: os.path.join(images_path, "logo", "kivymd-icon-512.png")
pos_hint: {"center_x": .5, "center_y": .6} pos_hint: {"center_x": .5, "center_y": .6}
''' '''
) )
# Usage example of MDBackdrop. # Usage example of MDBackdrop.
Builder.load_string( Builder.load_string(
''' '''
<ExampleBackdrop> <ExampleBackdrop>
MDBackdrop: MDBackdrop:
id: backdrop id: backdrop
left_action_items: [['menu', lambda x: self.open()]] left_action_items: [['menu', lambda x: self.open()]]
title: "Example Backdrop" title: "Example Backdrop"
radius_left: "25dp" radius_left: "25dp"
radius_right: "0dp" radius_right: "0dp"
header_text: "Menu:" header_text: "Menu:"
MDBackdropBackLayer: MDBackdropBackLayer:
MyBackdropBackLayer: MyBackdropBackLayer:
id: backlayer id: backlayer
MDBackdropFrontLayer: MDBackdropFrontLayer:
MyBackdropFrontLayer: MyBackdropFrontLayer:
backdrop: backdrop backdrop: backdrop
''' '''
) )
class ExampleBackdrop(MDScreen): class ExampleBackdrop(MDScreen):
pass pass
class TestBackdrop(MDApp): class Example(MDApp):
def __init__(self, **kwargs): def build(self):
super().__init__(**kwargs) self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
def build(self): return ExampleBackdrop()
return ExampleBackdrop()
TestBackdrop().run() Example().run()
.. tab:: Declarative python styles
.. code-block:: python
import os
from kivy.core.window import Window
from kivy.uix.image import Image
from kivymd import images_path
from kivymd.uix.backdrop import MDBackdrop
from kivymd.uix.backdrop.backdrop import (
MDBackdropBackLayer, MDBackdropFrontLayer
)
from kivymd.uix.list import TwoLineAvatarListItem, IconLeftWidget
from kivymd.uix.screen import MDScreen
from kivymd.app import MDApp
class Example(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return (
MDScreen(
MDBackdrop(
MDBackdropBackLayer(
Image(
size_hint=(0.8, 0.8),
source=os.path.join(images_path, "logo", "kivymd-icon-512.png"),
pos_hint={"center_x": 0.5, "center_y": 0.6},
)
),
MDBackdropFrontLayer(
TwoLineAvatarListItem(
IconLeftWidget(icon="transfer-down"),
text="Lower the front layer",
secondary_text=" by 50 %",
on_press=self.backdrop_open_by_50_percent,
pos_hint={"top": 1},
_no_ripple_effect=True,
),
),
id="backdrop",
title="Example Backdrop",
radius_left="25dp",
radius_right="0dp",
header_text="Menu:",
)
)
)
def backdrop_open_by_50_percent(self, *args):
self.root.ids.backdrop.open(-Window.height / 2)
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop.gif .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop.gif
:width: 280 px
:align: center :align: center
.. Note:: `See full example <https://github.com/kivymd/KivyMD/wiki/Components-Backdrop>`_ .. Note:: `See full example <https://github.com/kivymd/KivyMD/wiki/Components-Backdrop>`_
@ -139,7 +202,7 @@ from kivy.uix.boxlayout import BoxLayout
from kivymd import uix_path from kivymd import uix_path
from kivymd.theming import ThemableBehavior from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import FakeRectangularElevationBehavior from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.card import MDCard from kivymd.uix.card import MDCard
from kivymd.uix.floatlayout import MDFloatLayout from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.toolbar.toolbar import ActionTopAppBarButton, MDTopAppBar from kivymd.uix.toolbar.toolbar import ActionTopAppBarButton, MDTopAppBar
@ -151,7 +214,7 @@ with open(
Builder.load_string(kv_file.read()) Builder.load_string(kv_file.read())
class MDBackdrop(ThemableBehavior, MDFloatLayout): class MDBackdrop(MDFloatLayout, ThemableBehavior):
""" """
:Events: :Events:
:attr:`on_open` :attr:`on_open`
@ -167,6 +230,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
.. versionadded:: 1.0.0 .. versionadded:: 1.0.0
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-anchor-title.png
:align: center
:attr:`anchor_title` is an :class:`~kivy.properties.OptionProperty` :attr:`anchor_title` is an :class:`~kivy.properties.OptionProperty`
and defaults to `'left'`. and defaults to `'left'`.
""" """
@ -175,6 +241,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
""" """
Padding for contents of the front layer. Padding for contents of the front layer.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-padding.png
:align: center
:attr:`padding` is an :class:`~kivy.properties.ListProperty` :attr:`padding` is an :class:`~kivy.properties.ListProperty`
and defaults to `[0, 0, 0, 0]`. and defaults to `[0, 0, 0, 0]`.
""" """
@ -210,6 +279,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
""" """
Background color of back layer. Background color of back layer.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-back-layer-color.png
:align: center
:attr:`back_layer_color` is an :class:`~kivy.properties.ColorProperty` :attr:`back_layer_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`. and defaults to `None`.
""" """
@ -218,6 +290,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
""" """
Background color of front layer. Background color of front layer.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-front-layer-color.png
:align: center
:attr:`front_layer_color` is an :class:`~kivy.properties.ColorProperty` :attr:`front_layer_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`. and defaults to `None`.
""" """
@ -227,6 +302,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
The value of the rounding radius of the upper left corner The value of the rounding radius of the upper left corner
of the front layer. of the front layer.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-radius-left.png
:align: center
:attr:`radius_left` is an :class:`~kivy.properties.NumericProperty` :attr:`radius_left` is an :class:`~kivy.properties.NumericProperty`
and defaults to `16dp`. and defaults to `16dp`.
""" """
@ -244,6 +322,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
""" """
Whether to use a header above the contents of the front layer. Whether to use a header above the contents of the front layer.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-header.png
:align: center
:attr:`header` is an :class:`~kivy.properties.BooleanProperty` :attr:`header` is an :class:`~kivy.properties.BooleanProperty`
and defaults to `True`. and defaults to `True`.
""" """
@ -252,6 +333,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
""" """
Text of header. Text of header.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-header-text.png
:align: center
:attr:`header_text` is an :class:`~kivy.properties.StringProperty` :attr:`header_text` is an :class:`~kivy.properties.StringProperty`
and defaults to `'Header'`. and defaults to `'Header'`.
""" """
@ -261,6 +345,9 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
The name of the icon that will be installed on the toolbar The name of the icon that will be installed on the toolbar
on the left when opening the front layer. on the left when opening the front layer.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/backdrop-close-icon.png
:align: center
:attr:`close_icon` is an :class:`~kivy.properties.StringProperty` :attr:`close_icon` is an :class:`~kivy.properties.StringProperty`
and defaults to `'close'`. and defaults to `'close'`.
""" """
@ -310,8 +397,8 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
_open_icon = "" _open_icon = ""
_front_layer_open = False _front_layer_open = False
def __init__(self, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(**kwargs) super().__init__(*args, **kwargs)
self.register_event_type("on_open") self.register_event_type("on_open")
self.register_event_type("on_close") self.register_event_type("on_close")
Clock.schedule_once( Clock.schedule_once(
@ -332,8 +419,11 @@ class MDBackdrop(ThemableBehavior, MDFloatLayout):
self._open_icon = self.left_action_items[0][0] self._open_icon = self.left_action_items[0][0]
def on_header(self, instance_backdrop, value: bool) -> None: def on_header(self, instance_backdrop, value: bool) -> None:
if not value: def on_header(*args):
self.ids._front_layer.remove_widget(self.ids.header_button) if not value:
self.ids._front_layer.remove_widget(self.ids.header_button)
Clock.schedule_once(on_header)
def open(self, open_up_to: int = 0) -> None: def open(self, open_up_to: int = 0) -> None:
""" """
@ -425,11 +515,11 @@ class MDBackdropToolbar(MDTopAppBar):
"""Implements a toolbar for back content.""" """Implements a toolbar for back content."""
class MDBackdropFrontLayer(BoxLayout): class MDBackdropFrontLayer(MDBoxLayout):
"""Container for front content.""" """Container for front content."""
class MDBackdropBackLayer(BoxLayout): class MDBackdropBackLayer(MDBoxLayout):
"""Container for back content.""" """Container for back content."""
@ -437,5 +527,5 @@ class _BackLayer(BoxLayout):
pass pass
class _FrontLayer(MDCard, FakeRectangularElevationBehavior): class _FrontLayer(MDCard):
pass pass

View File

@ -35,7 +35,7 @@ Usage
MDTopAppBar: MDTopAppBar:
id: toolbar id: toolbar
title: "Example Banners" title: "Example Banners"
elevation: 10 elevation: 4
pos_hint: {'top': 1} pos_hint: {'top': 1}
MDBoxLayout: MDBoxLayout:
@ -157,7 +157,6 @@ from kivy.properties import (
from kivy.uix.widget import Widget from kivy.uix.widget import Widget
from kivymd import uix_path from kivymd import uix_path
from kivymd.uix.behaviors import FakeRectangularElevationBehavior
from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton from kivymd.uix.button import MDFlatButton
from kivymd.uix.card import MDCard from kivymd.uix.card import MDCard
@ -177,7 +176,7 @@ with open(
Builder.load_string(kv_file.read()) Builder.load_string(kv_file.read())
class MDBanner(MDCard, FakeRectangularElevationBehavior): class MDBanner(MDCard):
vertical_pad = NumericProperty(dp(68)) vertical_pad = NumericProperty(dp(68))
""" """
Indent the banner at the top of the screen. Indent the banner at the top of the screen.

View File

@ -5,22 +5,26 @@ Behaviors
Modules and classes implementing various behaviors for buttons etc. Modules and classes implementing various behaviors for buttons etc.
""" """
# flake8: NOQA
from .hover_behavior import HoverBehavior # isort:skip
from .backgroundcolor_behavior import ( from .backgroundcolor_behavior import (
BackgroundColorBehavior, BackgroundColorBehavior,
SpecificBackgroundColorBehavior, SpecificBackgroundColorBehavior,
) )
# flake8: NOQA
from .declarative_behavior import DeclarativeBehavior
from .elevation import ( from .elevation import (
CircularElevationBehavior, CircularElevationBehavior,
CommonElevationBehavior, CommonElevationBehavior,
FakeCircularElevationBehavior, FakeCircularElevationBehavior,
FakeRectangularElevationBehavior, FakeRectangularElevationBehavior,
ObservableShadow,
RectangularElevationBehavior, RectangularElevationBehavior,
RoundedRectangularElevationBehavior, RoundedRectangularElevationBehavior,
) )
from .focus_behavior import FocusBehavior
from .magic_behavior import MagicBehavior from .magic_behavior import MagicBehavior
from .ripple_behavior import CircularRippleBehavior, RectangularRippleBehavior from .ripple_behavior import CircularRippleBehavior, RectangularRippleBehavior
from .rotate_behavior import RotateBehavior
from .scale_behavior import ScaleBehavior
from .stencil_behavior import StencilBehavior
from .touch_behavior import TouchBehavior from .touch_behavior import TouchBehavior
from .hover_behavior import HoverBehavior # isort:skip

View File

@ -7,8 +7,9 @@ Behaviors/Background Color
__all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior") __all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior")
from typing import List from typing import List, Union
from kivy.animation import Animation
from kivy.lang import Builder from kivy.lang import Builder
from kivy.properties import ( from kivy.properties import (
ColorProperty, ColorProperty,
@ -24,8 +25,6 @@ from kivy.utils import get_color_from_hex
from kivymd.color_definitions import hue, palette, text_colors from kivymd.color_definitions import hue, palette, text_colors
from kivymd.theming import ThemeManager from kivymd.theming import ThemeManager
from .elevation import CommonElevationBehavior
Builder.load_string( Builder.load_string(
""" """
#:import RelativeLayout kivy.uix.relativelayout.RelativeLayout #:import RelativeLayout kivy.uix.relativelayout.RelativeLayout
@ -38,7 +37,7 @@ Builder.load_string(
angle: self.angle angle: self.angle
origin: self._background_origin origin: self._background_origin
Color: Color:
rgba: self.md_bg_color rgba: self._md_bg_color
RoundedRectangle: RoundedRectangle:
group: "Background_instruction" group: "Background_instruction"
size: self.size size: self.size
@ -67,7 +66,7 @@ Builder.load_string(
) )
class BackgroundColorBehavior(CommonElevationBehavior): class BackgroundColorBehavior:
background = StringProperty() background = StringProperty()
""" """
Background image path. Background image path.
@ -153,15 +152,26 @@ class BackgroundColorBehavior(CommonElevationBehavior):
_background_x = NumericProperty(0) _background_x = NumericProperty(0)
_background_y = NumericProperty(0) _background_y = NumericProperty(0)
_background_origin = ReferenceListProperty( _background_origin = ReferenceListProperty(_background_x, _background_y)
_background_x, _md_bg_color = ColorProperty([0, 0, 0, 0])
_background_y,
)
def __init__(self, **kwarg): def __init__(self, **kwarg):
super().__init__(**kwarg) super().__init__(**kwarg)
self.bind(pos=self.update_background_origin) self.bind(pos=self.update_background_origin)
def on_md_bg_color(self, instance_md_widget, color: Union[list, str]):
if (
hasattr(self, "theme_cls")
and self.theme_cls.theme_style_switch_animation
):
Animation(
_md_bg_color=color,
d=self.theme_cls.theme_style_switch_animation_duration,
t="linear",
).start(self)
else:
self._md_bg_color = color
def update_background_origin( def update_background_origin(
self, instance_md_widget, pos: List[float] self, instance_md_widget, pos: List[float]
) -> None: ) -> None:
@ -206,12 +216,14 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
super().__init__(**kwargs) super().__init__(**kwargs)
if hasattr(self, "theme_cls"): if hasattr(self, "theme_cls"):
self.theme_cls.bind( self.theme_cls.bind(
primary_palette=self._update_specific_text_color primary_palette=self._update_specific_text_color,
accent_palette=self._update_specific_text_color,
theme_style=self._update_specific_text_color,
) )
self.theme_cls.bind(accent_palette=self._update_specific_text_color) self.bind(
self.theme_cls.bind(theme_style=self._update_specific_text_color) background_hue=self._update_specific_text_color,
self.bind(background_hue=self._update_specific_text_color) background_palette=self._update_specific_text_color,
self.bind(background_palette=self._update_specific_text_color) )
self._update_specific_text_color(None, None) self._update_specific_text_color(None, None)
def _update_specific_text_color( def _update_specific_text_color(
@ -234,5 +246,17 @@ class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
secondary_color[3] = 0.54 secondary_color[3] = 0.54
else: else:
secondary_color[3] = 0.7 secondary_color[3] = 0.7
self.specific_text_color = color
self.specific_secondary_text_color = secondary_color if (
hasattr(self, "theme_cls")
and self.theme_cls.theme_style_switch_animation
):
Animation(
specific_text_color=color,
specific_secondary_text_color=secondary_color,
d=self.theme_cls.theme_style_switch_animation_duration,
t="linear",
).start(self)
else:
self.specific_text_color = color
self.specific_secondary_text_color = secondary_color

View File

@ -0,0 +1,317 @@
"""
Behaviors/Declarative
=====================
.. versionadded:: 1.0.0
.. raw:: html
<div style="position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden; max-width: 100%; height: auto;">
<iframe
src="https://www.youtube.com/embed/_kiaJacLz8o"
frameborder="0"
allowfullscreen
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;">
</iframe>
</div>
As you already know, the Kivy framework provides the best/simplest/modern
UI creation tool that allows you to separate the logic of your application
from the description of the properties of widgets/GUI components.
This tool is named `KV Language <https://kivy.org/doc/stable/guide/lang.html>`_.
But in addition to creating a user interface using the KV Language Kivy allows
you to create user interface elements directly in the Python code.
And if you've ever created a user interface in Python code, you know how ugly
it looks. Even in the simplest user interface design, which was created using
Python code it is impossible to trace the widget tree, because in Python code
you build the user interface in an imperative style.
Imperative style
----------------
.. code-block:: python
from kivymd.app import MDApp
from kivymd.uix.bottomnavigation import MDBottomNavigation, MDBottomNavigationItem
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import MDScreen
class Example(MDApp):
def build(self):
screen = MDScreen()
bottom_navigation = MDBottomNavigation(
panel_color="#eeeaea",
selected_color_background="#97ecf8",
text_color_active="white",
)
data = {
"screen 1": {"text": "Mail", "icon": "gmail"},
"screen 2": {"text": "Discord", "icon": "discord"},
"screen 3": {"text": "LinkedIN", "icon": "linkedin"},
}
for key in data.keys():
text = data[key]["text"]
navigation_item = MDBottomNavigationItem(
name=key, text=text, icon=data[key]["icon"]
)
navigation_item.add_widget(MDLabel(text=text, halign="center"))
bottom_navigation.add_widget(navigation_item)
screen.add_widget(bottom_navigation)
return screen
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation-styles-programming.png
:align: center
Take a look at the above code example. This is a very simple UI. But looking
at this code, you will not be able to figure the widget tree and understand
which UI this code implements. This is named imperative programming style,
which is used in Kivy.
Now let's see how the same code is implemented using the KV language,
which uses a declarative style of describing widget properties.
Declarative style with KV language
----------------------------------
.. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
class Test(MDApp):
def build(self):
return Builder.load_string(
'''
MDScreen:
MDBottomNavigation:
panel_color: "#eeeaea"
selected_color_background: "#97ecf8"
text_color_active: "white"
MDBottomNavigationItem:
name: "screen 1"
text: "Mail"
icon: "gmail"
MDLabel:
text: "Mail"
halign: "center"
MDBottomNavigationItem:
name: "screen 2"
text: "Discord"
icon: "discord"
MDLabel:
text: "Discord"
halign: "center"
MDBottomNavigationItem:
name: "screen 3"
text: "LinkedIN"
icon: "linkedin"
MDLabel:
text: "LinkedIN"
halign: "center"
'''
)
Test().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation-styles-programming.png
:align: center
Looking at this code, we can now clearly see the widget tree and their properties.
We can quickly navigate through the components of the screen and quickly
change/add new properties/widgets. This is named declarative UI creation style.
But now the KivyMD library allows you to write Python code in a declarative style.
Just as it is implemented in Flutter/Jetpack Compose/SwiftUI.
Declarative style with Python code
----------------------------------
.. code-block:: python
from kivymd.app import MDApp
from kivymd.uix.bottomnavigation import MDBottomNavigation, MDBottomNavigationItem
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import MDScreen
class Example(MDApp):
def build(self):
return (
MDScreen(
MDBottomNavigation(
MDBottomNavigationItem(
MDLabel(
text="Mail",
halign="center",
),
name="screen 1",
text="Mail",
icon="gmail",
),
MDBottomNavigationItem(
MDLabel(
text="Discord",
halign="center",
),
name="screen 2",
text="Discord",
icon="discord",
),
MDBottomNavigationItem(
MDLabel(
text="LinkedIN",
halign="center",
),
name="screen 3",
text="LinkedIN",
icon="linkedin",
),
panel_color="#eeeaea",
selected_color_background="#97ecf8",
text_color_active="white",
)
)
)
Example().run()
.. note:: The KivyMD library does not support creating Kivy widgets in Python
code in a declarative style.
But you can still use the declarative style of creating Kivy widgets in Python code.
To do this, you need to create a new class that will be inherited from the Kivy
widget and the :class:`~DeclarativeBehavior` class:
.. code-block:: python
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.button import Button
from kivymd.app import MDApp
from kivymd.uix.behaviors import DeclarativeBehavior
class DeclarativeStyleBoxLayout(DeclarativeBehavior, BoxLayout):
pass
class Example(MDApp):
def build(self):
return (
DeclarativeStyleBoxLayout(
Button(),
Button(),
orientation="vertical",
)
)
Example().run()
Get objects by identifiers
--------------------------
In the declarative style in Python code, the ids parameter of the specified
widget will return only the id of the child widget/container, ignoring other ids.
Therefore, to get objects by identifiers in declarative style in Python code,
you must specify all the container ids in which the widget is nested until you
get to the desired id:
.. code-block::
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDRaisedButton
from kivymd.uix.floatlayout import MDFloatLayout
class Example(MDApp):
def build(self):
return (
MDBoxLayout(
MDFloatLayout(
MDRaisedButton(
id="button_1",
text="Button 1",
pos_hint={"center_x": 0.5, "center_y": 0.5},
),
id="box_container_1",
),
MDBoxLayout(
MDFloatLayout(
MDRaisedButton(
id="button_2",
text="Button 2",
pos_hint={"center_x": 0.5, "center_y": 0.5},
),
id="float_container",
),
id="box_container_2",
)
)
)
def on_start(self):
# {
# 'box_container_1': <kivymd.uix.floatlayout.MDFloatLayout>,
# 'box_container_2': <kivymd.uix.boxlayout.MDBoxLayout object>
# }
print(self.root.ids)
# <kivymd.uix.button.button.MDRaisedButton>
print(self.root.ids.box_container_2.ids.float_container.ids.button_2)
Example().run()
Yes, this is not a very good solution, but I think it will be fixed soon.
.. warning:: Declarative programming style in Python code in the KivyMD library
is an experimental feature. Therefore, if you receive errors, do not hesitate
to create new issue in the KivyMD repository.
"""
from kivy.properties import StringProperty
from kivy.uix.widget import Widget
class DeclarativeBehavior:
"""
Implements the creation and addition of child widgets as declarative
programming style.
"""
id = StringProperty()
"""
Widget ID.
:attr:`id` is an :class:`~kivy.properties.StringProperty`
and defaults to `''`.
"""
def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
for child in args:
if issubclass(child.__class__, Widget):
self.add_widget(child)
if hasattr(child, "id") and child.id:
self.ids[child.id] = child

File diff suppressed because it is too large Load Diff

View File

@ -100,23 +100,35 @@ class FocusBehavior(HoverBehavior, ButtonBehavior):
def on_enter(self): def on_enter(self):
"""Called when mouse enter the bbox of the widget.""" """Called when mouse enter the bbox of the widget."""
if hasattr(self, "md_bg_color") and self.focus_behavior: if (
hasattr(self, "md_bg_color") or hasattr(self, "bg_color")
) and self.focus_behavior:
if hasattr(self, "theme_cls") and not self.focus_color: if hasattr(self, "theme_cls") and not self.focus_color:
self.md_bg_color = self.theme_cls.bg_normal color = self.theme_cls.bg_normal
else: else:
if not self.focus_color: if not self.focus_color:
self.md_bg_color = App.get_running_app().theme_cls.bg_normal color = App.get_running_app().theme_cls.bg_normal
else: else:
self.md_bg_color = self.focus_color color = self.focus_color
self._set_bg_color(color)
def on_leave(self): def on_leave(self):
"""Called when the mouse exit the widget.""" """Called when the mouse exit the widget."""
if hasattr(self, "md_bg_color") and self.focus_behavior: if (
hasattr(self, "md_bg_color") or hasattr(self, "bg_color")
) and self.focus_behavior:
if hasattr(self, "theme_cls") and not self.unfocus_color: if hasattr(self, "theme_cls") and not self.unfocus_color:
self.md_bg_color = self.theme_cls.bg_light color = self.theme_cls.bg_light
else: else:
if not self.unfocus_color: if not self.unfocus_color:
self.md_bg_color = App.get_running_app().theme_cls.bg_light color = App.get_running_app().theme_cls.bg_light
else: else:
self.md_bg_color = self.unfocus_color color = self.unfocus_color
self._set_bg_color(color)
def _set_bg_color(self, color):
if hasattr(self, "md_bg_color"):
self.md_bg_color = color
elif hasattr(self, "bg_color"):
self.bg_color = color

View File

@ -111,7 +111,7 @@ from kivy.properties import (
from kivy.uix.behaviors import ToggleButtonBehavior from kivy.uix.behaviors import ToggleButtonBehavior
class CommonRipple(object): class CommonRipple:
"""Base class for ripple effect.""" """Base class for ripple effect."""
ripple_rad_default = NumericProperty(1) ripple_rad_default = NumericProperty(1)

View File

@ -0,0 +1,133 @@
"""
Behaviors/Rotate
================
.. versionadded:: 1.1.0
Base class for controlling the rotate of the widget.
.. note:: See `kivy.graphics.Rotate
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Rotate>`_
for more information.
Kivy
----
.. code-block:: python
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.app import App
from kivy.properties import NumericProperty
from kivy.uix.button import Button
KV = '''
Screen:
RotateButton:
size_hint: .5, .5
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.change_rotate(self)
canvas.before:
PushMatrix
Rotate:
angle: self.rotate_value_angle
axis: 0, 0, 1
origin: self.center
canvas.after:
PopMatrix
'''
class RotateButton(Button):
rotate_value_angle = NumericProperty(0)
class Test(App):
def build(self):
return Builder.load_string(KV)
def change_rotate(self, instance_button: Button) -> None:
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
Test().run()
KivyMD
------
.. code-block:: python
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.uix.behaviors import ButtonBehavior
from kivymd.app import MDApp
from kivymd.uix.behaviors import RotateBehavior
from kivymd.uix.boxlayout import MDBoxLayout
KV = '''
MDScreen:
RotateBox:
size_hint: .5, .5
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.change_rotate(self)
md_bg_color: "red"
'''
class RotateBox(ButtonBehavior, RotateBehavior, MDBoxLayout):
pass
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
def change_rotate(self, instance_button: RotateBox) -> None:
Animation(rotate_value_angle=45, d=0.3).start(instance_button)
Test().run()
"""
__all__ = ("RotateBehavior",)
from kivy.lang import Builder
from kivy.properties import ListProperty, NumericProperty
Builder.load_string(
"""
<RotateBehavior>
canvas.before:
PushMatrix
Rotate:
angle: self.rotate_value_angle
axis: tuple(self.rotate_value_axis)
origin: self.center
canvas.after:
PopMatrix
"""
)
class RotateBehavior:
"""Base class for controlling the rotate of the widget."""
rotate_value_angle = NumericProperty(0)
"""
Property for getting/setting the angle of the rotation.
:attr:`rotate_value_angle` is an :class:`~kivy.properties.NumericProperty`
and defaults to `0`.
"""
rotate_value_axis = ListProperty((0, 0, 1))
"""
Property for getting/setting the axis of the rotation.
:attr:`rotate_value_axis` is an :class:`~kivy.properties.ListProperty`
and defaults to `(0, 0, 1)`.
"""

View File

@ -0,0 +1,156 @@
"""
Behaviors/Scale
===============
.. versionadded:: 1.1.0
Base class for controlling the scale of the widget.
.. note:: See `kivy.graphics.Rotate
<https://kivy.org/doc/stable/api-kivy.graphics.html#kivy.graphics.Scale>`_
for more information.
Kivy
----
.. code-block:: python
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.properties import NumericProperty
from kivy.uix.button import Button
from kivy.app import App
KV = '''
Screen:
ScaleButton:
size_hint: .5, .5
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.change_scale(self)
canvas.before:
PushMatrix
Scale:
x: self.scale_value_x
y: self.scale_value_y
z: self.scale_value_x
origin: self.center
canvas.after:
PopMatrix
'''
class ScaleButton(Button):
scale_value_x = NumericProperty(1)
scale_value_y = NumericProperty(1)
scale_value_z = NumericProperty(1)
class Test(App):
def build(self):
return Builder.load_string(KV)
def change_scale(self, instance_button: Button) -> None:
Animation(
scale_value_x=0.5,
scale_value_y=0.5,
scale_value_z=0.5,
d=0.3,
).start(instance_button)
Test().run()
KivyMD
------
.. code-block:: python
from kivy.animation import Animation
from kivy.lang import Builder
from kivy.uix.behaviors import ButtonBehavior
from kivymd.app import MDApp
from kivymd.uix.behaviors import ScaleBehavior
from kivymd.uix.boxlayout import MDBoxLayout
KV = '''
MDScreen:
ScaleBox:
size_hint: .5, .5
pos_hint: {"center_x": .5, "center_y": .5}
on_release: app.change_scale(self)
md_bg_color: "red"
'''
class ScaleBox(ButtonBehavior, ScaleBehavior, MDBoxLayout):
pass
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
def change_scale(self, instance_button: ScaleBox) -> None:
Animation(
scale_value_x=0.5,
scale_value_y=0.5,
scale_value_z=0.5,
d=0.3,
).start(instance_button)
Test().run()
"""
__all__ = ("ScaleBehavior",)
from kivy.lang import Builder
from kivy.properties import NumericProperty
Builder.load_string(
"""
<ScaleBehavior>
canvas.before:
PushMatrix
Scale:
x: self.scale_value_x
y: self.scale_value_y
z: self.scale_value_x
origin: self.center
canvas.after:
PopMatrix
"""
)
class ScaleBehavior:
"""Base class for controlling the scale of the widget."""
scale_value_x = NumericProperty(1)
"""
X-axis value.
:attr:`scale_value_x` is an :class:`~kivy.properties.NumericProperty`
and defaults to `1`.
"""
scale_value_y = NumericProperty(1)
"""
Y-axis value.
:attr:`scale_value_y` is an :class:`~kivy.properties.NumericProperty`
and defaults to `1`.
"""
scale_value_z = NumericProperty(1)
"""
Z-axis value.
:attr:`scale_value_z` is an :class:`~kivy.properties.NumericProperty`
and defaults to `1`.
"""

View File

@ -0,0 +1,134 @@
"""
Behaviors/Stencil
=================
.. versionadded:: 1.1.0
Base class for controlling the stencil instructions of the widget.
.. note:: See `Stencil instructions
<https://kivy.org/doc/stable/api-kivy.graphics.stencil_instructions.html>`_
for more information.
Kivy
----
.. code-block:: python
from kivy.lang import Builder
from kivy.app import App
KV = '''
Carousel:
Button:
size_hint: .9, .8
pos_hint: {"center_x": .5, "center_y": .5}
canvas.before:
StencilPush
RoundedRectangle:
pos: root.pos
size: root.size
StencilUse
canvas.after:
StencilUnUse
RoundedRectangle:
pos: root.pos
size: root.size
StencilPop
'''
class Test(App):
def build(self):
return Builder.load_string(KV)
Test().run()
KivyMD
------
.. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
from kivymd.uix.behaviors import StencilBehavior
from kivymd.uix.fitimage import FitImage
KV = '''
#:import os os
#:import images_path kivymd.images_path
MDCarousel:
StencilImage:
size_hint: .9, .8
pos_hint: {"center_x": .5, "center_y": .5}
source: os.path.join(images_path, "logo", "kivymd-icon-512.png")
'''
class StencilImage(FitImage, StencilBehavior):
pass
class Test(MDApp):
def build(self):
return Builder.load_string(KV)
Test().run()
"""
__all__ = ("StencilBehavior",)
from kivy.lang import Builder
from kivy.properties import VariableListProperty
Builder.load_string(
"""
<StencilBehavior>
canvas.before:
StencilPush
RoundedRectangle:
pos: root.pos
size: root.size
# FIXME: Sometimes the radius has the value [], which get a
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
radius: root.radius if root.radius else [0, 0, 0, 0]
StencilUse
canvas.after:
StencilUnUse
RoundedRectangle:
pos: root.pos
size: root.size
# FIXME: Sometimes the radius has the value [], which get a
# `GraphicException: Invalid radius value, must be list of tuples/numerics` error
radius: root.radius if root.radius else [0, 0, 0, 0]
StencilPop
"""
)
class StencilBehavior:
"""Base class for controlling the stencil instructions of the widget."""
radius = VariableListProperty([0], length=4)
"""
Canvas radius.
.. versionadded:: 1.0.0
.. code-block:: python
# Top left corner slice.
MDWidget:
radius: [25, 0, 0, 0]
:attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
and defaults to `[0, 0, 0, 0]`.
"""

View File

@ -14,61 +14,104 @@ example:
pass pass
.. code-block:: python .. tabs::
from kivy.lang import Builder .. tab:: Declarative KV style
from kivymd.app import MDApp .. code-block:: python
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
from kivymd.uix.button import MDRectangleFlatButton
KV = ''' from kivy.lang import Builder
Screen:
MDBoxLayout: from kivymd.app import MDApp
adaptive_size: True from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
pos_hint: {"center_x": .5, "center_y": .5} from kivymd.uix.button import MDFlatButton
MyToggleButton: KV = '''
text: "Show ads" MDScreen:
group: "x"
MyToggleButton: MDBoxLayout:
text: "Do not show ads" adaptive_size: True
group: "x" spacing: "12dp"
pos_hint: {"center_x": .5, "center_y": .5}
MyToggleButton: MyToggleButton:
text: "Does not matter" text: "Show ads"
group: "x" group: "x"
'''
MyToggleButton:
text: "Do not show ads"
group: "x"
MyToggleButton:
text: "Does not matter"
group: "x"
'''
class MyToggleButton(MDRectangleFlatButton, MDToggleButton): class MyToggleButton(MDFlatButton, MDToggleButton):
def __init__(self, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(**kwargs) super().__init__(*args, **kwargs)
self.background_down = self.theme_cls.primary_light self.background_down = self.theme_cls.primary_color
class Test(MDApp): class Test(MDApp):
def build(self): def build(self):
return Builder.load_string(KV) 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 kivymd.app import MDApp
from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.screen import MDScreen
class MyToggleButton(MDFlatButton, MDToggleButton):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.background_down = self.theme_cls.primary_color
class Test(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return (
MDScreen(
MDBoxLayout(
MyToggleButton(
text="Show ads",
group="x",
),
MyToggleButton(
text="Do not show ads",
group="x",
),
MyToggleButton(
text="Does not matter",
group="x",
),
adaptive_size=True,
spacing="12dp",
pos_hint={"center_x": .5, "center_y": .5},
),
)
)
Test().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
:align: center :align: center
.. code-block:: python
class MyToggleButton(MDFillRoundFlatButton, MDToggleButton):
def __init__(self, **kwargs):
self.background_down = MDApp.get_running_app().theme_cls.primary_dark
super().__init__(**kwargs)
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-2.gif
:align: center
You can inherit the ``MyToggleButton`` class only from the following classes You can inherit the ``MyToggleButton`` class only from the following classes
---------------------------------------------------------------------------- ----------------------------------------------------------------------------
@ -88,6 +131,7 @@ from kivy.properties import BooleanProperty, ColorProperty
from kivy.uix.behaviors import ToggleButtonBehavior from kivy.uix.behaviors import ToggleButtonBehavior
from kivymd.uix.button import ( from kivymd.uix.button import (
ButtonContentsIconText,
MDFillRoundFlatButton, MDFillRoundFlatButton,
MDFillRoundFlatIconButton, MDFillRoundFlatIconButton,
MDFlatButton, MDFlatButton,
@ -149,7 +193,8 @@ class MDToggleButton(ToggleButtonBehavior):
# Do the object inherited from the "supported" buttons? # Do the object inherited from the "supported" buttons?
if not issubclass(self.__class__, classinfo): if not issubclass(self.__class__, classinfo):
raise ValueError( raise ValueError(
f"Class {self.__class__} must be inherited from one of the classes in the list {classinfo}" f"Class {self.__class__} must be inherited from one of the "
f"classes in the list {classinfo}"
) )
if ( if (
not self.background_normal not self.background_normal
@ -165,10 +210,12 @@ class MDToggleButton(ToggleButtonBehavior):
): ):
self.__is_filled = True self.__is_filled = True
self.background_normal = self.theme_cls.primary_color self.background_normal = self.theme_cls.primary_color
# If not the background_normal must be the same as the inherited one: # If not background_normal must be the same as the inherited one.
else: else:
self.background_normal = self.md_bg_color[:] self.background_normal = (
# If no background_down is setted: self.md_bg_color[:] if self.md_bg_color else (0, 0, 0, 0)
)
# If no background_down is setter.
if ( if (
not self.background_down not self.background_down
): # This means that if the value == [] or None will return True. ): # This means that if the value == [] or None will return True.
@ -200,3 +247,6 @@ class MDToggleButton(ToggleButtonBehavior):
): # If the background is transparent, the font color must be the ): # If the background is transparent, the font color must be the
# primary color. # primary color.
self.text_color = self.font_color_normal self.text_color = self.font_color_normal
if issubclass(self.__class__, ButtonContentsIconText):
self.icon_color = self.text_color

View File

@ -1,4 +1,3 @@
#:import sm kivy.uix.screenmanager
#:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT #:import STANDARD_INCREMENT kivymd.material_resources.STANDARD_INCREMENT
@ -9,7 +8,7 @@
ScreenManager: ScreenManager:
id: tab_manager id: tab_manager
transition: sm.FadeTransition(duration=.2) transition: root.transition(duration=root.transition_duration)
on_current: on_current:
root.dispatch( \ root.dispatch( \
"on_switch_tabs", \ "on_switch_tabs", \
@ -96,7 +95,7 @@
radius: [16,] radius: [16,]
size: root._selected_region_width, dp(32) size: root._selected_region_width, dp(32)
pos: pos:
self.center_x - self.width - dp(8), \ self.center_x - root._selected_region_width / 2, \
self.center_y - (dp(16)) self.center_y - (dp(16))
MDLabel: MDLabel:

View File

@ -62,59 +62,120 @@ For ease of understanding, this code works like this:
Example Example
------- -------
.. code-block:: python .. tabs::
from kivy.lang import Builder .. tab:: Declarative KV style
from kivymd.app import MDApp .. code-block:: python
from kivy.lang import Builder
from kivymd.app import MDApp
class Test(MDApp): class Test(MDApp):
def build(self): def build(self):
self.theme_cls.material_style = "M3" self.theme_cls.material_style = "M3"
return Builder.load_string( self.theme_cls.theme_style = "Dark"
''' return Builder.load_string(
MDScreen: '''
MDScreen:
MDBottomNavigation: MDBottomNavigation:
panel_color: "#eeeaea" #panel_color: "#eeeaea"
selected_color_background: "#97ecf8" selected_color_background: "orange"
text_color_active: 0, 0, 0, 1 text_color_active: "lightgrey"
MDBottomNavigationItem: MDBottomNavigationItem:
name: 'screen 1' name: 'screen 1'
text: 'Mail' text: 'Mail'
icon: 'gmail' icon: 'gmail'
badge_icon: "numeric-10" badge_icon: "numeric-10"
MDLabel: MDLabel:
text: 'Mail' text: 'Mail'
halign: 'center' halign: 'center'
MDBottomNavigationItem: MDBottomNavigationItem:
name: 'screen 2' name: 'screen 2'
text: 'Discord' text: 'Twitter'
icon: 'discord' icon: 'twitter'
badge_icon: "numeric-5" badge_icon: "numeric-5"
MDLabel: MDLabel:
text: 'Discord' text: 'Twitter'
halign: 'center' halign: 'center'
MDBottomNavigationItem: MDBottomNavigationItem:
name: 'screen 3' name: 'screen 3'
text: 'LinkedIN' text: 'LinkedIN'
icon: 'linkedin' icon: 'linkedin'
MDLabel: MDLabel:
text: 'LinkedIN' text: 'LinkedIN'
halign: 'center' halign: 'center'
''' '''
) )
Test().run() Test().run()
.. tab:: Declarative python style
.. code-block:: python
from kivymd.app import MDApp
from kivymd.uix.bottomnavigation import MDBottomNavigation, MDBottomNavigationItem
from kivymd.uix.label import MDLabel
from kivymd.uix.screen import MDScreen
class Test(MDApp):
def build(self):
self.theme_cls.material_style = "M3"
self.theme_cls.theme_style = "Dark"
return (
MDScreen(
MDBottomNavigation(
MDBottomNavigationItem(
MDLabel(
text='Mail',
halign='center',
),
name='screen 1',
text='Mail',
icon='gmail',
badge_icon="numeric-10",
),
MDBottomNavigationItem(
MDLabel(
text='Twitter',
halign='center',
),
name='screen 1',
text='Twitter',
icon='twitter',
badge_icon="numeric-10",
),
MDBottomNavigationItem(
MDLabel(
text='LinkedIN',
halign='center',
),
name='screen 1',
text='LinkedIN',
icon='linkedin',
badge_icon="numeric-10",
),
selected_color_background="orange",
text_color_active="lightgrey",
)
)
)
Test().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation.gif .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/bottom-navigation.gif
:align: center :align: center
@ -192,13 +253,13 @@ from kivy.properties import (
) )
from kivy.uix.behaviors import ButtonBehavior from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivy.uix.screenmanager import ScreenManagerException from kivy.uix.screenmanager import FadeTransition, ScreenManagerException
from kivymd import uix_path from kivymd import uix_path
from kivymd.material_resources import STANDARD_INCREMENT from kivymd.material_resources import STANDARD_INCREMENT
from kivymd.theming import ThemableBehavior, ThemeManager from kivymd.theming import ThemableBehavior, ThemeManager
from kivymd.uix.anchorlayout import MDAnchorLayout from kivymd.uix.anchorlayout import MDAnchorLayout
from kivymd.uix.behaviors import FakeRectangularElevationBehavior from kivymd.uix.behaviors import CommonElevationBehavior, DeclarativeBehavior
from kivymd.uix.behaviors.backgroundcolor_behavior import ( from kivymd.uix.behaviors.backgroundcolor_behavior import (
SpecificBackgroundColorBehavior, SpecificBackgroundColorBehavior,
) )
@ -364,8 +425,8 @@ class MDTab(MDScreen, ThemableBehavior):
and defaults to `''`. and defaults to `''`.
""" """
def __init__(self, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(**kwargs) super().__init__(*args, **kwargs)
self.index = 0 self.index = 0
self.parent_widget = None self.parent_widget = None
self.register_event_type("on_tab_touch_down") self.register_event_type("on_tab_touch_down")
@ -407,6 +468,31 @@ class MDBottomNavigationItem(MDTab):
and defaults to `None`. and defaults to `None`.
""" """
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
def animate_header(
self, bottom_navigation_object, bottom_navigation_header_object
) -> None:
if bottom_navigation_object.use_text:
Animation(_label_font_size=sp(12), d=0.1).start(
bottom_navigation_object.previous_tab.header
)
Animation(
_selected_region_width=0,
t="in_out_sine",
d=0,
).start(bottom_navigation_header_object)
Animation(
_text_color_normal=bottom_navigation_header_object.text_color_normal
if bottom_navigation_object.previous_tab.header.text_color_normal
!= [1, 1, 1, 1]
else self.theme_cls.disabled_hint_text_color,
d=0.1,
).start(bottom_navigation_object.previous_tab.header)
bottom_navigation_object.previous_tab.header.active = False
self.header.active = True
def on_tab_press(self, *args) -> None: def on_tab_press(self, *args) -> None:
"""Called when clicking on a panel item.""" """Called when clicking on a panel item."""
@ -414,28 +500,13 @@ class MDBottomNavigationItem(MDTab):
bottom_navigation_header_object = ( bottom_navigation_header_object = (
bottom_navigation_object.previous_tab.header bottom_navigation_object.previous_tab.header
) )
bottom_navigation_object.ids.tab_manager.current = self.name
if bottom_navigation_object.previous_tab is not self: if bottom_navigation_object.previous_tab is not self:
if bottom_navigation_object.use_text: self.animate_header(
Animation(_label_font_size=sp(12), d=0.1).start( bottom_navigation_object, bottom_navigation_header_object
bottom_navigation_object.previous_tab.header )
)
Animation( super().on_tab_press(*args)
_selected_region_width=0,
t="in_out_sine",
d=0,
).start(bottom_navigation_header_object)
Animation(
_text_color_normal=bottom_navigation_header_object.text_color_normal
if bottom_navigation_object.previous_tab.header.text_color_normal
!= [1, 1, 1, 1]
else self.theme_cls.disabled_hint_text_color,
d=0.1,
).start(bottom_navigation_object.previous_tab.header)
bottom_navigation_object.previous_tab.header.active = False
self.header.active = True
bottom_navigation_object.previous_tab = self
def on_disabled( def on_disabled(
self, instance_bottom_navigation_item, disabled_value: bool self, instance_bottom_navigation_item, disabled_value: bool
@ -463,7 +534,7 @@ class TabbedPanelBase(
and defaults to `None`. and defaults to `None`.
""" """
previous_tab = ObjectProperty() previous_tab = ObjectProperty(None, aloownone=True)
""" """
:attr:`previous_tab` is an :class:`~MDTab` and defaults to `None`. :attr:`previous_tab` is an :class:`~MDTab` and defaults to `None`.
""" """
@ -479,7 +550,7 @@ class TabbedPanelBase(
tabs = ListProperty() tabs = ListProperty()
class MDBottomNavigation(TabbedPanelBase): class MDBottomNavigation(DeclarativeBehavior, TabbedPanelBase):
""" """
A bottom navigation that is implemented by delegating all items to a A bottom navigation that is implemented by delegating all items to a
:class:`~kivy.uix.screenmanager.ScreenManager`. :class:`~kivy.uix.screenmanager.ScreenManager`.
@ -492,6 +563,26 @@ class MDBottomNavigation(TabbedPanelBase):
.. versionadded:: 1.0.0 .. versionadded:: 1.0.0
""" """
transition = ObjectProperty(FadeTransition)
"""
Transition animation of bottom navigation screen manager.
.. versionadded:: 1.1.0
:attr:`transition` is an :class:`~kivy.properties.ObjectProperty`
and defaults to `FadeTransition`.
"""
transition_duration = NumericProperty(0.2)
"""
Duration animation of bottom navigation screen manager.
.. versionadded:: 1.1.0
:attr:`transition_duration` is an :class:`~kivy.properties.NumericProperty`
and defaults to `0.2`.
"""
text_color_normal = ColorProperty([1, 1, 1, 1]) text_color_normal = ColorProperty([1, 1, 1, 1])
""" """
Text color of the label when it is not selected. Text color of the label when it is not selected.
@ -594,14 +685,15 @@ class MDBottomNavigation(TabbedPanelBase):
and defaults to `False`. and defaults to `False`.
""" """
widget_index = NumericProperty(0)
# Text active color if it is selected. # Text active color if it is selected.
_active_color = ColorProperty([1, 1, 1, 1]) _active_color = ColorProperty([1, 1, 1, 1])
def __init__(self, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(**kwargs)
self.register_event_type("on_switch_tabs")
self.previous_tab = None self.previous_tab = None
self.widget_index = 0 self.register_event_type("on_switch_tabs")
super().__init__(*args, **kwargs)
self.theme_cls.bind(material_style=self.refresh_tabs) self.theme_cls.bind(material_style=self.refresh_tabs)
Window.bind(on_resize=self.on_resize) Window.bind(on_resize=self.on_resize)
Clock.schedule_once(lambda x: self.on_resize()) Clock.schedule_once(lambda x: self.on_resize())
@ -660,8 +752,11 @@ class MDBottomNavigation(TabbedPanelBase):
def on_selected_color_background( def on_selected_color_background(
self, instance_bottom_navigation, color: list self, instance_bottom_navigation, color: list
) -> None: ) -> None:
for tab in self.ids.tab_bar.children: def on_selected_color_background(*args):
tab.selected_color_background = color for tab in self.ids.tab_bar.children:
tab.selected_color_background = color
Clock.schedule_once(on_selected_color_background)
def on_use_text( def on_use_text(
self, instance_bottom_navigation, use_text_value: bool self, instance_bottom_navigation, use_text_value: bool
@ -698,12 +793,15 @@ class MDBottomNavigation(TabbedPanelBase):
def on_text_color_active( def on_text_color_active(
self, instance_bottom_navigation, color: list self, instance_bottom_navigation, color: list
) -> None: ) -> None:
MDBottomNavigationHeader.text_color_active = color def on_text_color_active(*args):
self.text_color_active = color MDBottomNavigationHeader.text_color_active = color
for tab in self.ids.tab_bar.children: self.text_color_active = color
tab.text_color_active = color for tab in self.ids.tab_bar.children:
if tab.active: tab.text_color_active = color
tab._text_color_normal = color if tab.active:
tab._text_color_normal = color
Clock.schedule_once(on_text_color_active)
def on_switch_tabs(self, bottom_navigation_item, name_tab: str) -> None: def on_switch_tabs(self, bottom_navigation_item, name_tab: str) -> None:
""" """
@ -759,8 +857,6 @@ class MDBottomNavigation(TabbedPanelBase):
class MDBottomNavigationBar( class MDBottomNavigationBar(
ThemableBehavior, ThemableBehavior, CommonElevationBehavior, MDFloatLayout
FakeRectangularElevationBehavior,
MDFloatLayout,
): ):
pass pass

View File

@ -34,7 +34,7 @@ Usage :class:`~MDListBottomSheet`
MDTopAppBar: MDTopAppBar:
title: "Example BottomSheet" title: "Example BottomSheet"
pos_hint: {"top": 1} pos_hint: {"top": 1}
elevation: 10 elevation: 4
MDRaisedButton: MDRaisedButton:
text: "Open list bottom sheet" text: "Open list bottom sheet"
@ -94,7 +94,7 @@ which will be used as an icon to the left of the item:
MDTopAppBar: MDTopAppBar:
title: 'Example BottomSheet' title: 'Example BottomSheet'
pos_hint: {"top": 1} pos_hint: {"top": 1}
elevation: 10 elevation: 4
MDRaisedButton: MDRaisedButton:
text: "Open grid bottom sheet" text: "Open grid bottom sheet"
@ -180,7 +180,7 @@ which will be used as an icon to the left of the item:
MDTopAppBar: MDTopAppBar:
title: 'Example BottomSheet' title: 'Example BottomSheet'
pos_hint: {"top": 1} pos_hint: {"top": 1}
elevation: 10 elevation: 4
MDRaisedButton: MDRaisedButton:
text: "Open custom bottom sheet" text: "Open custom bottom sheet"

View File

@ -8,7 +8,7 @@ with some widget properties. For example:
BoxLayout BoxLayout
--------- ---------
.. code-block:: .. code-block:: kv
BoxLayout: BoxLayout:
size_hint_y: None size_hint_y: None
@ -24,7 +24,7 @@ BoxLayout
MDBoxLayout MDBoxLayout
----------- -----------
.. code-block:: .. code-block:: kv
MDBoxLayout: MDBoxLayout:
adaptive_height: True adaptive_height: True
@ -88,7 +88,13 @@ __all__ = ("MDBoxLayout",)
from kivy.uix.boxlayout import BoxLayout from kivy.uix.boxlayout import BoxLayout
from kivymd.uix import MDAdaptiveWidget from kivymd.uix import MDAdaptiveWidget
from kivymd.uix.behaviors import DeclarativeBehavior
class MDBoxLayout(BoxLayout, MDAdaptiveWidget): class MDBoxLayout(DeclarativeBehavior, BoxLayout, MDAdaptiveWidget):
pass """
Box layout class.
For more information, see in the
:class:`~kivy.uix.boxlayout.BoxLayout` class documentation.
"""

View File

@ -1,6 +1,7 @@
# NOQA F401 # NOQA F401
from .button import ( from .button import (
BaseButton, BaseButton,
ButtonContentsIconText,
MDFillRoundFlatButton, MDFillRoundFlatButton,
MDFillRoundFlatIconButton, MDFillRoundFlatIconButton,
MDFlatButton, MDFlatButton,

View File

@ -3,9 +3,9 @@
Clear Clear
Color: Color:
rgba: rgba:
(self._md_bg_color or [0.0, 0.0, 0.0, 0.0]) \ self._md_bg_color \
if not self.disabled else \ if not self.disabled else \
(self._md_bg_color_disabled or [0.0, 0.0, 0.0, 0.0]) self._md_bg_color_disabled
RoundedRectangle: RoundedRectangle:
size: self.size size: self.size
pos: self.pos pos: self.pos
@ -13,19 +13,17 @@
radius: [root._radius, ] radius: [root._radius, ]
Color: Color:
rgba: rgba:
root._line_color or [0.0, 0.0, 0.0, 0.0] \ root._line_color \
if not root.disabled else \ if not root.disabled else \
( \ (root._line_color_disabled or self._disabled_color)
root._line_color_disabled \
or self._disabled_color \
or [0.0, 0.0, 0.0, 0.0] \
)
Line: Line:
width: root.line_width width: root.line_width
rounded_rectangle: rounded_rectangle:
(self.x, self.y, self.width, self.height, \ ( \
self.x, self.y, self.width, self.height, \
root._radius, root._radius, root._radius, root._radius, \ root._radius, root._radius, root._radius, root._radius, \
self.height) self.height \
)
size_hint: None, None size_hint: None, None
anchor_x: root.halign anchor_x: root.halign
@ -33,21 +31,28 @@
_round_rad: [self._radius] * 4 _round_rad: [self._radius] * 4
<ButtonContentsText> <ButtonContentsText>
lbl_txt: lbl_txt lbl_txt: lbl_txt
width: width:
max(root._min_width, \ max( \
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2]) root._min_width, \
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2] \
)
size_hint_min_x: size_hint_min_x:
max(root._min_width, \ max( \
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2]) root._min_width, \
root.padding[0] + lbl_txt.texture_size[0] + root.padding[2] \
)
height: height:
max(root._min_height, \ max( \
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3]) root._min_height, \
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3] \
)
size_hint_min_y: size_hint_min_y:
max(root._min_height, \ max( \
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3]) root._min_height, \
root.padding[1] + lbl_txt.texture_size[1] + root.padding[3] \
)
MDLabel: MDLabel:
id: lbl_txt id: lbl_txt
@ -84,7 +89,10 @@
# This is only a temporary fix and does not fix the cause of the error. # This is only a temporary fix and does not fix the cause of the error.
(root._icon_color if root._icon_color else root.theme_cls.text_color) \ (root._icon_color if root._icon_color else root.theme_cls.text_color) \
if not root.disabled else \ if not root.disabled else \
root.theme_cls.disabled_hint_text_color root.theme_cls.disabled_hint_text_color \
if not root.disabled_color else \
root.disabled_color
on_icon: on_icon:
if self.icon not in md_icons.keys(): self.size_hint = (1, 1) if self.icon not in md_icons.keys(): self.size_hint = (1, 1)
theme_text_color: root._theme_icon_color theme_text_color: root._theme_icon_color
@ -131,7 +139,7 @@
id: box id: box
adaptive_size: True adaptive_size: True
padding: 0 padding: 0
spacing: "4dp" spacing: "8dp"
MDIcon: MDIcon:
id: lbl_ic id: lbl_ic
@ -193,48 +201,21 @@
radius: [self.height / 2] radius: [self.height / 2]
<BaseFloatingRootButton> <MDFloatingRootButton>
theme_text_color: "Custom" theme_text_color: "Custom"
md_bg_color: self.theme_cls.primary_color md_bg_color: self.theme_cls.primary_color
<MDFloatingLabel>
padding_x: "8dp"
padding_y: "8dp"
adaptive_size: True
theme_text_color: "Custom"
canvas.before: canvas.before:
PushMatrix
Rotate:
angle: self._angle
axis: (0, 0, 1)
origin: self.center
canvas.after:
PopMatrix
# FIXME: Use :class:`~kivymd.uix.boxlayout.MDBoxLayout` instead
# :class:`~kivy.uix.boxlayout.BoxLayout`.
<BaseFloatingLabel>
size_hint: None, None
padding: "8dp", "4dp", "8dp", "4dp"
height: label.texture_size[1] + self.padding[1] * 2
width: label.texture_size[0] + self.padding[0] * 2
elevation: 10
# TODO: Use `md_bg_color` and `radius` instead `canvasю
canvas:
Color: Color:
rgba: rgba: self.bg_color
self.theme_cls.primary_color \
if not root.bg_color else \
root.bg_color
RoundedRectangle: RoundedRectangle:
pos: self.pos
size: self.size size: self.size
radius: [5] pos: self.pos
radius: self.radius
Label:
id: label
markup: True
text: root.text
size_hint: None, None
size: self.texture_size
color:
root.theme_cls.text_color \
if not root.text_color else \
root.text_color

File diff suppressed because it is too large Load Diff

View File

@ -2,17 +2,6 @@
md_bg_color: app.theme_cls.divider_color md_bg_color: app.theme_cls.divider_color
<MDCard>
canvas.before:
Color:
rgba: self.md_bg_color
RoundedRectangle:
size: self.size
pos: self.pos
radius: root.radius
source: root.background
<MDSeparator> <MDSeparator>
md_bg_color: md_bg_color:
self.theme_cls.divider_color \ self.theme_cls.divider_color \

File diff suppressed because it is too large Load Diff

View File

@ -57,8 +57,10 @@ MDCarousel
from kivy.animation import Animation from kivy.animation import Animation
from kivy.uix.carousel import Carousel from kivy.uix.carousel import Carousel
from kivymd.uix.behaviors import DeclarativeBehavior
class MDCarousel(Carousel):
class MDCarousel(DeclarativeBehavior, Carousel):
""" """
based on kivy's carousel. based on kivy's carousel.
@ -68,8 +70,8 @@ class MDCarousel(Carousel):
_scrolling = False _scrolling = False
def __init__(self, **kwargs): def __init__(self, *args, **kwargs):
super().__init__(**kwargs) super().__init__(*args, **kwargs)
self.register_event_type("on_slide_progress") self.register_event_type("on_slide_progress")
self.register_event_type("on_slide_complete") self.register_event_type("on_slide_complete")

View File

@ -1 +1 @@
from .chip import MDChip, MDChooseChip # NOQA F401 from .chip import MDChip # NOQA F401

View File

@ -132,7 +132,7 @@ Use with elevation
icon_right: "close-circle-outline" icon_right: "close-circle-outline"
line_color: app.theme_cls.disabled_hint_text_color line_color: app.theme_cls.disabled_hint_text_color
md_bg_color: 1, 0, 0, .5 md_bg_color: 1, 0, 0, .5
elevation: 12 elevation: 4
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/chip-with-elevation.png
:align: center :align: center
@ -304,7 +304,6 @@ __all__ = ("MDChip",)
import os import os
from kivy import Logger
from kivy.animation import Animation from kivy.animation import Animation
from kivy.lang import Builder from kivy.lang import Builder
from kivy.metrics import dp from kivy.metrics import dp
@ -314,14 +313,13 @@ from kivy.uix.behaviors import ButtonBehavior
from kivymd import uix_path from kivymd import uix_path
from kivymd.theming import ThemableBehavior from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import ( from kivymd.uix.behaviors import (
FakeRectangularElevationBehavior, CommonElevationBehavior,
RectangularRippleBehavior, RectangularRippleBehavior,
ScaleBehavior,
TouchBehavior, TouchBehavior,
) )
from kivymd.uix.boxlayout import MDBoxLayout from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.label import MDIcon from kivymd.uix.label import MDIcon
from kivymd.uix.stacklayout import MDStackLayout
from kivymd.uix.templates import ScaleWidget
with open( with open(
os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8" os.path.join(uix_path, "chip", "chip.kv"), encoding="utf-8"
@ -330,12 +328,12 @@ with open(
class MDChip( class MDChip(
MDBoxLayout,
ThemableBehavior, ThemableBehavior,
RectangularRippleBehavior, RectangularRippleBehavior,
FakeRectangularElevationBehavior,
TouchBehavior,
ButtonBehavior, ButtonBehavior,
MDBoxLayout, CommonElevationBehavior,
TouchBehavior,
): ):
text = StringProperty() text = StringProperty()
""" """
@ -345,17 +343,6 @@ class MDChip(
and defaults to `''`. and defaults to `''`.
""" """
icon = StringProperty("checkbox-blank-circle", deprecated=True)
"""
Chip icon.
.. deprecated:: 1.0.0
Use :attr:`icon_right` and :attr:`icon_left` instead.
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
and defaults to `'checkbox-blank-circle'`.
"""
icon_left = StringProperty() icon_left = StringProperty()
""" """
Chip left icon. Chip left icon.
@ -376,16 +363,6 @@ class MDChip(
and defaults to `''`. and defaults to `''`.
""" """
color = ColorProperty(None, deprecated=True)
"""
Chip color in ``rgba`` format.
.. deprecated:: 1.0.0
:attr:`color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
text_color = ColorProperty(None) text_color = ColorProperty(None)
""" """
Chip's text color in ``rgba`` format. Chip's text color in ``rgba`` format.
@ -394,17 +371,6 @@ class MDChip(
and defaults to `None`. and defaults to `None`.
""" """
icon_color = ColorProperty(None, deprecated=True)
"""
Chip's icon color in ``rgba`` format.
.. deprecated:: 1.0.0
Use :attr:`icon_right_color` and :attr:`icon_left_color` instead.
:attr:`icon_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
icon_right_color = ColorProperty(None) icon_right_color = ColorProperty(None)
""" """
Chip's right icon color in ``rgba`` format. Chip's right icon color in ``rgba`` format.
@ -435,26 +401,6 @@ class MDChip(
and defaults to `None`. and defaults to `None`.
""" """
check = BooleanProperty(False, deprecated=True)
"""
If `True`, a checkmark is added to the left when touch to the chip.
.. deprecated:: 1.0.0
:attr:`check` is an :class:`~kivy.properties.BooleanProperty`
and defaults to `False`.
"""
selected_chip_color = ColorProperty(None, deprecated=True)
"""
The color of the chip that is currently selected in ``rgba`` format.
.. deprecated:: 1.0.0
:attr:`selected_chip_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`.
"""
active = BooleanProperty(False) active = BooleanProperty(False)
""" """
Whether the check is marked or not. Whether the check is marked or not.
@ -508,16 +454,7 @@ class MDChip(
self.active = False self.active = False
class MDChooseChip(MDStackLayout): class MDScalableCheckIcon(MDIcon, ScaleBehavior):
def __init__(self, **kwargs):
super().__init__(**kwargs)
Logger.warning(
"MDChooseChip: "
"class is deprecated and will be removed in a future version"
)
class MDScalableCheckIcon(MDIcon, ScaleWidget):
pos_hint = {"center_y": 0.5} pos_hint = {"center_y": 0.5}

View File

@ -2,6 +2,8 @@
Controllers/WindowController Controllers/WindowController
============================ ============================
.. versionadded:: 1.0.0
Modules and classes that implement useful methods for getting information Modules and classes that implement useful methods for getting information
about the state of the current application window. about the state of the current application window.
@ -33,16 +35,35 @@ Controlling the resizing direction of the application window
from kivy.core.window import Window from kivy.core.window import Window
from kivy.core.window.window_sdl2 import WindowSDL from kivy.core.window.window_sdl2 import WindowSDL
from kivy.metrics import dp
class WindowController: class WindowController:
def __init__(self): def __init__(self):
self.window_resizing_direction = "unknown" self.window_resizing_direction = "unknown"
self.real_device_type = "unknown"
self.__width = Window.width self.__width = Window.width
Window.bind(on_resize=self._on_resize) Window.bind(on_resize=self._on_resize)
def on_size(self, instance, size: list) -> None:
"""Called when the application screen size changes."""
window_width = size[0]
if window_width < dp(500):
self.real_device_type = "mobile"
elif window_width < dp(1100):
self.real_device_type = "tablet"
else:
self.real_device_type = "desktop"
def get_real_device_type(self) -> str:
"""Returns the device type - 'mobile', 'tablet' or 'desktop'."""
return self.real_device_type
def get_window_width_resizing_direction(self) -> str: def get_window_width_resizing_direction(self) -> str:
"""Return window width resizing direction - 'left' or 'right'""" """Return window width resizing direction - 'left' or 'right'."""
return self.window_resizing_direction return self.window_resizing_direction

View File

@ -1,5 +1,4 @@
#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE #:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE
#:import FakeRectangularElevationBehavior kivymd.uix.behaviors.FakeRectangularElevationBehavior
<CellRow> <CellRow>
@ -66,7 +65,7 @@
size_hint_y: None size_hint_y: None
height: self.minimum_height height: self.minimum_height
spacing: "4dp" spacing: "4dp"
tooltip_text: root.text tooltip_text: root.tooltip if root.tooltip else root.text
BoxLayout: BoxLayout:
id: box id: box
@ -175,7 +174,11 @@
font_size: "14sp" font_size: "14sp"
on_release: root.table_data.open_pagination_menu() on_release: root.table_data.open_pagination_menu()
text: text:
f"{root.table_data.rows_num if root.table_data.rows_num < len(root.table_data.row_data) else len(root.table_data.row_data)}" "{}".format( \
root.table_data.rows_num \
if root.table_data.rows_num < len(root.table_data.row_data) else \
len(root.table_data.row_data) \
)
Widget: Widget:
size_hint_x: None size_hint_x: None
@ -192,9 +195,11 @@
if root.theme_cls.theme_style == "Dark" else \ if root.theme_cls.theme_style == "Dark" else \
(0, 0, 0, 1) (0, 0, 0, 1)
text: text:
f"1-" \ "1-{} of {}".format( \
f"{root.table_data.rows_num if root.table_data.rows_num > len(root.table_data.row_data) else len(root.table_data.row_data)} " \ root.table_data.rows_num \
f"of {len(root.table_data.row_data)}" if root.table_data.rows_num > len(root.table_data.row_data) else \
len(root.table_data.row_data), len(root.table_data.row_data) \
)
MDIconButton: MDIconButton:
id: button_back id: button_back
@ -217,7 +222,7 @@
on_release: root.table_data.set_next_row_data_parts("forward") on_release: root.table_data.set_next_row_data_parts("forward")
<TableContainer@MDCard+FakeRectangularElevationBehavior> <TableContainer@MDCard>
<MDDataTable> <MDDataTable>

View File

@ -11,19 +11,6 @@ Components/DataTables
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-previous.png .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-previous.png
:align: center :align: center
Warnings
---------
.. warning:: Data tables are still far from perfect. The class is in constant
change, because of optimizations and bug fixes. If you find a bug or have
an improvement you want to share, take some time and share your discoveries
with us over the main git repo.
Any help is well appreciated.
.. warning:: In versions prior to `Kivy 2.1.0-dev0` exists an error in which is
the table has only one row in the current page, the table will only render
one column instead of the whole row.
.. note:: `MDDataTable` allows developers to sort the data provided by column. .. note:: `MDDataTable` allows developers to sort the data provided by column.
This happens thanks to the use of an external function that you can bind This happens thanks to the use of an external function that you can bind
while you're defining the table columns. Be aware that the sorting function while you're defining the table columns. Be aware that the sorting function
@ -159,6 +146,15 @@ class CellHeader(MDTooltip, BoxLayout):
and defaults to `''`. and defaults to `''`.
""" """
tooltip = StringProperty()
"""
Tooltip containing descriptive text for the column.
If the tooltip is not provided, column `text` shall be used instead.
:attr:`tooltip` is a :class:`~kivy.properties.StringProperty`
and defaults to `''`.
"""
# TODO: Added example. # TODO: Added example.
sort_action = ObjectProperty() sort_action = ObjectProperty()
""" """
@ -340,11 +336,19 @@ class TableHeader(ThemableBehavior, ScrollView):
CellHeader( CellHeader(
text=col_heading[0], text=col_heading[0],
sort_action=col_heading[2], sort_action=col_heading[2],
tooltip=col_heading[3],
width=self.cols_minimum[i], width=self.cols_minimum[i],
table_data=self.table_data, table_data=self.table_data,
is_sorted=(col_heading[0] == self.sorted_on), is_sorted=(col_heading[0] == self.sorted_on),
sorted_order=self.sorted_order, sorted_order=self.sorted_order,
) )
if len(col_heading) == 4
else CellHeader(
text=col_heading[0],
sort_action=col_heading[2],
width=self.cols_minimum[i],
table_data=self.table_data,
)
if len(col_heading) == 3 if len(col_heading) == 3
else CellHeader( else CellHeader(
text=col_heading[0], text=col_heading[0],
@ -356,6 +360,9 @@ class TableHeader(ThemableBehavior, ScrollView):
else: else:
# Sets the text in the first cell. # Sets the text in the first cell.
self.ids.first_cell.text = col_heading[0] self.ids.first_cell.text = col_heading[0]
self.ids.first_cell.tooltip = (
col_heading[3] if len(col_heading) == 4 else ""
)
self.ids.first_cell.ids.separator.height = 0 self.ids.first_cell.ids.separator.height = 0
self.ids.first_cell.width = self.cols_minimum[i] self.ids.first_cell.width = self.cols_minimum[i]
@ -765,6 +772,9 @@ class TablePagination(ThemableBehavior, MDBoxLayout):
class MDDataTable(ThemableBehavior, AnchorLayout): class MDDataTable(ThemableBehavior, AnchorLayout):
""" """
See :class:`~kivy.uix.anchorlayout.AnchorLayout` class documentation for
more information.
:Events: :Events:
:attr:`on_row_press` :attr:`on_row_press`
Called when a table row is clicked. Called when a table row is clicked.
@ -775,7 +785,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
.. code-block:: python .. code-block:: python
from kivy.metrics import dp from kivy.metrics import dp
from kivymd.app import MDApp from kivymd.app import MDApp
@ -914,38 +923,82 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
""" """
Data for header columns. Data for header columns.
.. code-block:: python .. tabs::
from kivy.metrics import dp .. tab:: Imperative python style
from kivymd.app import MDApp .. code-block:: python
from kivymd.uix.datatables import MDDataTable
from kivy.uix.anchorlayout import AnchorLayout from kivy.metrics import dp
from kivymd.app import MDApp
from kivymd.uix.datatables import MDDataTable
from kivy.uix.anchorlayout import AnchorLayout
class Example(MDApp): class Example(MDApp):
def build(self): def build(self):
layout = AnchorLayout() self.theme_cls.theme_style = "Dark"
self.data_tables = MDDataTable( self.theme_cls.primary_palette = "Orange"
size_hint=(0.7, 0.6),
use_pagination=True, layout = AnchorLayout()
check=True, self.data_tables = MDDataTable(
# name column, width column, sorting function column(optional) size_hint=(0.7, 0.6),
column_data=[ use_pagination=True,
("No.", dp(30)), check=True,
("Status", dp(30)), # name column, width column, sorting function column(optional), custom tooltip
("Signal Name", dp(60)), column_data=[
("Severity", dp(30)), ("No.", dp(30), None, "Custom tooltip"),
("Stage", dp(30)), ("Status", dp(30)),
("Schedule", dp(30), lambda *args: print("Sorted using Schedule")), ("Signal Name", dp(60)),
("Team Lead", dp(30)), ("Severity", dp(30)),
], ("Stage", dp(30)),
) ("Schedule", dp(30), lambda *args: print("Sorted using Schedule")),
layout.add_widget(self.data_tables) ("Team Lead", dp(30)),
return layout ],
)
layout.add_widget(self.data_tables)
return layout
Example().run() Example().run()
.. tab:: Declarative python style
.. code-block:: python
from kivy.metrics import dp
from kivymd.app import MDApp
from kivymd.uix.anchorlayout import MDAnchorLayout
from kivymd.uix.datatables import MDDataTable
class Example(MDApp):
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return MDAnchorLayout(
MDDataTable(
size_hint=(0.7, 0.6),
use_pagination=True,
check=True,
# name column, width column, sorting function column(optional)
column_data=[
("No.", dp(30)),
("Status", dp(30)),
("Signal Name", dp(60)),
("Severity", dp(30)),
("Stage", dp(30)),
("Schedule", dp(30),
lambda *args: print("Sorted using Schedule")),
("Team Lead", dp(30)),
],
)
)
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-column-data.png
:align: center :align: center
@ -1060,6 +1113,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
class Example(MDApp): class Example(MDApp):
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
layout = AnchorLayout() layout = AnchorLayout()
data_tables = MDDataTable( data_tables = MDDataTable(
size_hint=(0.9, 0.6), size_hint=(0.9, 0.6),
@ -1187,7 +1243,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
""" """
Use or not use checkboxes for rows. Use or not use checkboxes for rows.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.gif .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-check.png
:align: center :align: center
:attr:`check` is an :class:`~kivy.properties.BooleanProperty` :attr:`check` is an :class:`~kivy.properties.BooleanProperty`
@ -1209,6 +1265,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
class Example(MDApp): class Example(MDApp):
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
layout = AnchorLayout() layout = AnchorLayout()
data_tables = MDDataTable( data_tables = MDDataTable(
size_hint=(0.9, 0.6), size_hint=(0.9, 0.6),
@ -1238,19 +1297,19 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
and defaults to `False`. and defaults to `False`.
""" """
elevation = NumericProperty(8) elevation = NumericProperty(4)
""" """
Table elevation. Table elevation.
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty` :attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
and defaults to `8`. and defaults to `4`.
""" """
rows_num = NumericProperty(5) rows_num = NumericProperty(5)
""" """
The number of rows displayed on one page of the table. The number of rows displayed on one page of the table.
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination.gif .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-use-pagination-rows-num.png
:align: center :align: center
:attr:`rows_num` is an :class:`~kivy.properties.NumericProperty` :attr:`rows_num` is an :class:`~kivy.properties.NumericProperty`
@ -1266,7 +1325,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
.. rubric:: Center .. rubric:: Center
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-center.png .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-pos-top.png
:align: center :align: center
.. rubric:: Auto .. rubric:: Auto
@ -1282,11 +1341,6 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
""" """
Menu height for selecting the number of displayed rows. Menu height for selecting the number of displayed rows.
.. rubric:: 140dp
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-140.png
:align: center
.. rubric:: 240dp .. rubric:: 240dp
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-240.png .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-menu-height-240.png
@ -1298,7 +1352,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
background_color = ColorProperty([0, 0, 0, 0]) background_color = ColorProperty([0, 0, 0, 0])
""" """
Background color in the format (r, g, b, a). Background color in the format (r, g, b, a) or string format.
See :attr:`~kivy.uix.modalview.ModalView.background_color`. See :attr:`~kivy.uix.modalview.ModalView.background_color`.
Use markup strings Use markup strings
@ -1315,6 +1369,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
class Example(MDApp): class Example(MDApp):
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
layout = AnchorLayout() layout = AnchorLayout()
data_tables = MDDataTable( data_tables = MDDataTable(
size_hint=(0.9, 0.6), size_hint=(0.9, 0.6),
@ -1354,7 +1411,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
background_color_header = ColorProperty(None) background_color_header = ColorProperty(None)
""" """
Background color for :class:`~TableHeader` class. Background color in the format (r, g, b, a) or string format for
:class:`~TableHeader` class.
.. versionadded:: 1.0.0 .. versionadded:: 1.0.0
@ -1374,7 +1432,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
background_color_cell = ColorProperty(None) background_color_cell = ColorProperty(None)
""" """
Background color for :class:`~CellRow` class. Background color in the format (r, g, b, a) or string format for
:class:`~CellRow` class.
.. versionadded:: 1.0.0 .. versionadded:: 1.0.0
@ -1395,7 +1454,8 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
background_color_selected_cell = ColorProperty(None) background_color_selected_cell = ColorProperty(None)
""" """
Background selected color for :class:`~CellRow` class. Background selected color in the format (r, g, b, a) or string format for
:class:`~CellRow` class.
.. versionadded:: 1.0.0 .. versionadded:: 1.0.0
@ -1408,7 +1468,7 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
background_color_selected_cell="e4514f", background_color_selected_cell="e4514f",
) )
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.gif .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/data-tables-background-color-selected-cell.png
:align: center :align: center
:attr:`background_color_selected_cell` is a :class:`~kivy.properties.ColorProperty` and :attr:`background_color_selected_cell` is a :class:`~kivy.properties.ColorProperty` and
@ -1503,6 +1563,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
data_tables = None data_tables = None
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
layout = MDFloatLayout() # root layout layout = MDFloatLayout() # root layout
# Creating control buttons. # Creating control buttons.
button_box = MDBoxLayout( button_box = MDBoxLayout(
@ -1604,6 +1667,9 @@ class MDDataTable(ThemableBehavior, AnchorLayout):
data_tables = None data_tables = None
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
layout = MDFloatLayout() layout = MDFloatLayout()
layout.add_widget( layout.add_widget(
MDRaisedButton( MDRaisedButton(

View File

@ -18,7 +18,11 @@
PopMatrix PopMatrix
<DialogContainer@MDCard+FakeRectangularElevationBehavior> <DialogContainer@MDCard>
shadow_color: 0.0, 0.0, 0.0, 0.0
elevation: 0
shadow_softness: 0
shadow_offset: 0, 0
<MDDialog> <MDDialog>
@ -28,7 +32,6 @@
orientation: "vertical" orientation: "vertical"
size_hint_y: None size_hint_y: None
height: self.minimum_height height: self.minimum_height
elevation: 24
padding: "24dp", "24dp", "8dp", "8dp" padding: "24dp", "24dp", "8dp", "8dp"
radius: root.radius radius: root.radius
md_bg_color: md_bg_color:

View File

@ -38,6 +38,8 @@ Usage
dialog = None dialog = None
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV) return Builder.load_string(KV)
def show_alert_dialog(self): def show_alert_dialog(self):
@ -87,6 +89,7 @@ from kivy.uix.modalview import ModalView
from kivymd import uix_path from kivymd import uix_path
from kivymd.material_resources import DEVICE_TYPE from kivymd.material_resources import DEVICE_TYPE
from kivymd.theming import ThemableBehavior from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import CommonElevationBehavior
from kivymd.uix.button import BaseButton from kivymd.uix.button import BaseButton
from kivymd.uix.card import MDSeparator from kivymd.uix.card import MDSeparator
from kivymd.uix.list import BaseListItem from kivymd.uix.list import BaseListItem
@ -97,7 +100,40 @@ with open(
Builder.load_string(kv_file.read()) Builder.load_string(kv_file.read())
class BaseDialog(ThemableBehavior, ModalView): class BaseDialog(ThemableBehavior, ModalView, CommonElevationBehavior):
elevation = NumericProperty(3)
"""
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.elevation`
attribute for more information.
.. versionadded:: 1.1.0
:attr:`elevation` is an :class:`~kivy.properties.NumericProperty`
and defaults to `3`.
"""
shadow_softness = NumericProperty(24)
"""
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_softness`
attribute for more information.
.. versionadded:: 1.1.0
:attr:`shadow_softness` is an :class:`~kivy.properties.NumericProperty`
and defaults to `24`.
"""
shadow_offset = ListProperty((0, 4))
"""
See :attr:`kivymd.uix.behaviors.elevation.CommonElevationBehavior.shadow_offset`
attribute for more information.
.. versionadded:: 1.1.0
:attr:`shadow_offset` is an :class:`~kivy.properties.ListProperty`
and defaults to `[0, 4]`.
"""
radius = ListProperty([dp(7), dp(7), dp(7), dp(7)]) radius = ListProperty([dp(7), dp(7), dp(7), dp(7)])
""" """
Dialog corners rounding value. Dialog corners rounding value.
@ -250,21 +286,22 @@ class MDDialog(BaseDialog):
class Example(MDApp): class Example(MDApp):
dialog = None dialog = None
def build(self): def build(self):
return Builder.load_string(KV) self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV)
def show_simple_dialog(self): def show_simple_dialog(self):
if not self.dialog: if not self.dialog:
self.dialog = MDDialog( self.dialog = MDDialog(
title="Set backup account", title="Set backup account",
type="simple", type="simple",
items=[ items=[
Item(text="user01@gmail.com", source="user-1.png"), Item(text="user01@gmail.com", source="kivymd/images/logo/kivymd-icon-128.png"),
Item(text="user02@gmail.com", source="user-2.png"), Item(text="user02@gmail.com", source="data/logo/kivy-icon-128.png"),
Item(text="Add account", source="add-icon.png"), ],
], )
) self.dialog.open()
self.dialog.open()
Example().run() Example().run()
@ -317,6 +354,8 @@ class MDDialog(BaseDialog):
dialog = None dialog = None
def build(self): def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV) return Builder.load_string(KV)
def show_confirmation_dialog(self): def show_confirmation_dialog(self):
@ -385,71 +424,140 @@ class MDDialog(BaseDialog):
""" """
Custom content class. Custom content class.
.. code-block:: python .. tabs::
from kivy.lang import Builder .. tab:: Declarative KV style
from kivy.uix.boxlayout import BoxLayout
from kivymd.app import MDApp .. code-block:: python
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
KV = ''' from kivy.lang import Builder
<Content> from kivy.uix.boxlayout import BoxLayout
orientation: "vertical"
spacing: "12dp"
size_hint_y: None
height: "120dp"
MDTextField: from kivymd.app import MDApp
hint_text: "City" from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
MDTextField: KV = '''
hint_text: "Street" <Content>
orientation: "vertical"
spacing: "12dp"
size_hint_y: None
height: "120dp"
MDTextField:
hint_text: "City"
MDTextField:
hint_text: "Street"
MDFloatLayout: MDFloatLayout:
MDFlatButton: MDFlatButton:
text: "ALERT DIALOG" text: "ALERT DIALOG"
pos_hint: {'center_x': .5, 'center_y': .5} pos_hint: {'center_x': .5, 'center_y': .5}
on_release: app.show_confirmation_dialog() on_release: app.show_confirmation_dialog()
''' '''
class Content(BoxLayout): class Content(BoxLayout):
pass pass
class Example(MDApp): class Example(MDApp):
dialog = None dialog = None
def build(self): def build(self):
return Builder.load_string(KV) self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return Builder.load_string(KV)
def show_confirmation_dialog(self): def show_confirmation_dialog(self):
if not self.dialog: if not self.dialog:
self.dialog = MDDialog( self.dialog = MDDialog(
title="Address:", title="Address:",
type="custom", type="custom",
content_cls=Content(), content_cls=Content(),
buttons=[ buttons=[
MDFlatButton( MDFlatButton(
text="CANCEL", text="CANCEL",
theme_text_color="Custom", theme_text_color="Custom",
text_color=self.theme_cls.primary_color, text_color=self.theme_cls.primary_color,
), ),
MDFlatButton( MDFlatButton(
text="OK", text="OK",
theme_text_color="Custom", theme_text_color="Custom",
text_color=self.theme_cls.primary_color, text_color=self.theme_cls.primary_color,
), ),
], ],
) )
self.dialog.open() self.dialog.open()
Example().run() Example().run()
.. tab:: Declarative Python style
.. code-block:: python
from kivymd.app import MDApp
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFlatButton
from kivymd.uix.dialog import MDDialog
from kivymd.uix.floatlayout import MDFloatLayout
from kivymd.uix.textfield import MDTextField
class Example(MDApp):
dialog = None
def build(self):
self.theme_cls.theme_style = "Dark"
self.theme_cls.primary_palette = "Orange"
return (
MDFloatLayout(
MDFlatButton(
text="ALERT DIALOG",
pos_hint={'center_x': 0.5, 'center_y': 0.5},
on_release=self.show_confirmation_dialog,
)
)
)
def show_confirmation_dialog(self, *args):
if not self.dialog:
self.dialog = MDDialog(
title="Address:",
type="custom",
content_cls=MDBoxLayout(
MDTextField(
hint_text="City",
),
MDTextField(
hint_text="Street",
),
orientation="vertical",
spacing="12dp",
size_hint_y=None,
height="120dp",
),
buttons=[
MDFlatButton(
text="CANCEL",
theme_text_color="Custom",
text_color=self.theme_cls.primary_color,
),
MDFlatButton(
text="OK",
theme_text_color="Custom",
text_color=self.theme_cls.primary_color,
),
],
)
self.dialog.open()
Example().run()
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dialog-custom.png
:align: center :align: center
@ -460,7 +568,7 @@ class MDDialog(BaseDialog):
md_bg_color = ColorProperty(None) md_bg_color = ColorProperty(None)
""" """
Background color in the format (r, g, b, a). Background color in the (r, g, b, a) or string format.
:attr:`md_bg_color` is an :class:`~kivy.properties.ColorProperty` :attr:`md_bg_color` is an :class:`~kivy.properties.ColorProperty`
and defaults to `None`. and defaults to `None`.

View File

@ -1,7 +1,7 @@
<_Triangle>: <_Triangle>:
canvas: canvas:
Color: Color:
rgba: root.theme_cls.text_color rgba: app.theme_cls.text_color
Triangle: Triangle:
points: points:
[ \ [ \
@ -13,7 +13,8 @@
<MDDropDownItem> <MDDropDownItem>
orientation: "vertical" orientation: "vertical"
adaptive_size: True size_hint: None, None
size: self.minimum_size
spacing: "5dp" spacing: "5dp"
padding: "5dp", "5dp", "5dp", 0 padding: "5dp", "5dp", "5dp", 0

View File

@ -15,13 +15,13 @@ Usage
from kivymd.app import MDApp from kivymd.app import MDApp
KV = ''' KV = '''
Screen MDScreen
MDDropDownItem: MDDropDownItem:
id: drop_item id: drop_item
pos_hint: {'center_x': .5, 'center_y': .5} pos_hint: {'center_x': .5, 'center_y': .5}
text: 'Item' text: 'Item'
on_release: self.set_item("New Item") on_release: print("Press item")
''' '''
@ -48,12 +48,12 @@ import os
from kivy.lang import Builder from kivy.lang import Builder
from kivy.properties import NumericProperty, StringProperty from kivy.properties import NumericProperty, StringProperty
from kivy.uix.behaviors import ButtonBehavior from kivy.uix.behaviors import ButtonBehavior
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.widget import Widget from kivy.uix.widget import Widget
from kivymd import uix_path from kivymd import uix_path
from kivymd.theming import ThemableBehavior from kivymd.theming import ThemableBehavior
from kivymd.uix.behaviors import FakeRectangularElevationBehavior from kivymd.uix.behaviors import DeclarativeBehavior
from kivymd.uix.boxlayout import MDBoxLayout
with open( with open(
os.path.join(uix_path, "dropdownitem", "dropdownitem.kv"), encoding="utf-8" os.path.join(uix_path, "dropdownitem", "dropdownitem.kv"), encoding="utf-8"
@ -61,15 +61,12 @@ with open(
Builder.load_string(kv_file.read()) Builder.load_string(kv_file.read())
class _Triangle(ThemableBehavior, Widget): class _Triangle(Widget):
pass pass
class MDDropDownItem( class MDDropDownItem(
ThemableBehavior, DeclarativeBehavior, ThemableBehavior, ButtonBehavior, BoxLayout
FakeRectangularElevationBehavior,
ButtonBehavior,
MDBoxLayout,
): ):
text = StringProperty() text = StringProperty()
""" """

View File

@ -56,6 +56,8 @@ Example
.. code-block:: python .. code-block:: python
import os
from kivy.lang import Builder from kivy.lang import Builder
from kivymd.app import MDApp from kivymd.app import MDApp
@ -75,7 +77,7 @@ Example
icon: 'phone' icon: 'phone'
ScrollView: MDScrollView:
MDGridLayout: MDGridLayout:
id: box id: box
@ -96,7 +98,7 @@ Example
for i in range(10): for i in range(10):
self.root.ids.box.add_widget( self.root.ids.box.add_widget(
MDExpansionPanel( MDExpansionPanel(
icon=f"{images_path}kivymd.png", icon=os.path.join(images_path, "logo", "kivymd-icon-128.png"),
content=Content(), content=Content(),
panel_cls=MDExpansionPanelThreeLine( panel_cls=MDExpansionPanelThreeLine(
text="Text", text="Text",

View File

@ -6,28 +6,29 @@
background_normal: "" background_normal: ""
background_down: "" background_down: ""
dir_or_file_name: "" dir_or_file_name: ""
icon_color: 0, 0, 0, 0
_selected: False _selected: False
events_callback: lambda x: None events_callback: lambda x: None
orientation: "vertical" orientation: "vertical"
ModifiedOneLineIconListItem: ModifiedOneLineIconListItem:
text: root.dir_or_file_name text: root.dir_or_file_name
on_release: root.events_callback(root.path, root)
bg_color: bg_color:
self.theme_cls.bg_darkest \ self.theme_cls.bg_darkest \
if root._selected else self.theme_cls.bg_normal if root._selected else \
on_release: root.events_callback(root.path, root) self.theme_cls.bg_normal
IconLeftWidget: IconLeftWidget:
icon: root.icon icon: root.icon
theme_text_color: "Custom" theme_icon_color: "Custom"
text_color: self.theme_cls.primary_color icon_color: root.icon_color
MDSeparator: MDSeparator:
<LabelContent@MDLabel> <LabelContent@MDLabel>
size_hint_y: None adaptive_height: True
height: self.texture_size[1]
shorten: True shorten: True
shorten_from: "center" shorten_from: "center"
halign: "center" halign: "center"
@ -61,23 +62,6 @@
text: root.name text: root.name
<FloatButton>
anchor_x: "right"
anchor_y: "bottom"
size_hint_y: None
height: dp(56)
padding: dp(10)
MDFloatingActionButton:
size_hint: None, None
size:dp(56), dp(56)
icon: root.icon
opposite_colors: True
elevation: 8
on_release: root.callback()
md_bg_color: root.md_bg_color
<MDFileManager> <MDFileManager>
md_bg_color: root.theme_cls.bg_normal md_bg_color: root.theme_cls.bg_normal
@ -90,7 +74,11 @@
title: root.current_path title: root.current_path
right_action_items: [["close-box", lambda x: root.exit_manager(1)]] right_action_items: [["close-box", lambda x: root.exit_manager(1)]]
left_action_items: [["chevron-left", lambda x: root.back()]] left_action_items: [["chevron-left", lambda x: root.back()]]
elevation: 10 elevation: 3
md_bg_color:
app.theme_cls.primary_color \
if not root.background_color_toolbar else \
root.background_color_toolbar
RecycleView: RecycleView:
id: rv id: rv

Some files were not shown because too many files have changed in this diff Show More