first commit
This commit is contained in:
commit
417e54da96
5696 changed files with 900003 additions and 0 deletions
|
@ -0,0 +1,8 @@
|
|||
# NOQA F401
|
||||
from .expansionpanel import (
|
||||
MDExpansionPanel,
|
||||
MDExpansionPanelLabel,
|
||||
MDExpansionPanelOneLine,
|
||||
MDExpansionPanelThreeLine,
|
||||
MDExpansionPanelTwoLine,
|
||||
)
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,18 @@
|
|||
<MDExpansionChevronRight>:
|
||||
icon: "chevron-right"
|
||||
disabled: True
|
||||
md_bg_color_disabled: 0, 0, 0, 0
|
||||
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
Rotate:
|
||||
angle: self._angle
|
||||
axis: (0, 0, 1)
|
||||
origin: self.center
|
||||
canvas.after:
|
||||
PopMatrix
|
||||
|
||||
|
||||
<MDExpansionPanel>
|
||||
size_hint_y: None
|
||||
# height: dp(68)
|
|
@ -0,0 +1,486 @@
|
|||
"""
|
||||
Components/ExpansionPanel
|
||||
=========================
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Material Design spec, Expansion panel <https://material.io/archive/guidelines/components/expansion-panels.html#>`_
|
||||
|
||||
.. rubric:: Expansion panels contain creation flows and allow lightweight editing of an element.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/expansion-panel.png
|
||||
:align: center
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.add_widget(
|
||||
MDExpansionPanel(
|
||||
icon="logo.png", # panel icon
|
||||
content=Content(), # panel content
|
||||
panel_cls=MDExpansionPanelOneLine(text="Secondary text"), # panel class
|
||||
)
|
||||
)
|
||||
|
||||
To use :class:`~MDExpansionPanel` you must pass one of the following classes
|
||||
to the :attr:`~MDExpansionPanel.panel_cls` parameter:
|
||||
|
||||
- :class:`~MDExpansionPanelOneLine`
|
||||
- :class:`~MDExpansionPanelTwoLine`
|
||||
- :class:`~MDExpansionPanelThreeLine`
|
||||
|
||||
These classes are inherited from the following classes:
|
||||
|
||||
- :class:`~kivymd.uix.list.OneLineAvatarIconListItem`
|
||||
- :class:`~kivymd.uix.list.TwoLineAvatarIconListItem`
|
||||
- :class:`~kivymd.uix.list.ThreeLineAvatarIconListItem`
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
self.root.ids.box.add_widget(
|
||||
MDExpansionPanel(
|
||||
icon="logo.png",
|
||||
content=Content(),
|
||||
panel_cls=MDExpansionPanelThreeLine(
|
||||
text="Text",
|
||||
secondary_text="Secondary text",
|
||||
tertiary_text="Tertiary text",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import os
|
||||
|
||||
from kivy.lang import Builder
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.uix.expansionpanel import MDExpansionPanel, MDExpansionPanelThreeLine
|
||||
from kivymd import images_path
|
||||
|
||||
KV = '''
|
||||
<Content>
|
||||
adaptive_height: True
|
||||
|
||||
TwoLineIconListItem:
|
||||
text: "(050)-123-45-67"
|
||||
secondary_text: "Mobile"
|
||||
|
||||
IconLeftWidget:
|
||||
icon: 'phone'
|
||||
|
||||
|
||||
MDScrollView:
|
||||
|
||||
MDGridLayout:
|
||||
id: box
|
||||
cols: 1
|
||||
adaptive_height: True
|
||||
'''
|
||||
|
||||
|
||||
class Content(MDBoxLayout):
|
||||
'''Custom content.'''
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def on_start(self):
|
||||
for i in range(10):
|
||||
self.root.ids.box.add_widget(
|
||||
MDExpansionPanel(
|
||||
icon=os.path.join(images_path, "logo", "kivymd-icon-128.png"),
|
||||
content=Content(),
|
||||
panel_cls=MDExpansionPanelThreeLine(
|
||||
text="Text",
|
||||
secondary_text="Secondary text",
|
||||
tertiary_text="Tertiary text",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/expansion-panel.gif
|
||||
:align: center
|
||||
|
||||
Two events are available for :class:`~MDExpansionPanel`
|
||||
-------------------------------------------------------
|
||||
|
||||
- :attr:`~MDExpansionPanel.on_open`
|
||||
- :attr:`~MDExpansionPanel.on_close`
|
||||
|
||||
.. code-block:: kv
|
||||
|
||||
MDExpansionPanel:
|
||||
on_open: app.on_panel_open(args)
|
||||
on_close: app.on_panel_close(args)
|
||||
|
||||
The user function takes one argument - the object of the panel:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
def on_panel_open(self, instance_panel):
|
||||
print(instance_panel)
|
||||
|
||||
.. seealso:: `See Expansion panel example <https://github.com/kivymd/KivyMD/wiki/Components-Expansion-Panel>`_
|
||||
|
||||
`Expansion panel and MDCard <https://github.com/kivymd/KivyMD/wiki/Components-Expansion-Panel-and-MDCard>`_
|
||||
"""
|
||||
|
||||
__all__ = (
|
||||
"MDExpansionPanel",
|
||||
"MDExpansionPanelOneLine",
|
||||
"MDExpansionPanelTwoLine",
|
||||
"MDExpansionPanelThreeLine",
|
||||
"MDExpansionPanelLabel",
|
||||
)
|
||||
|
||||
import os
|
||||
from typing import Union
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.clock import Clock
|
||||
from kivy.lang import Builder
|
||||
from kivy.metrics import dp
|
||||
from kivy.properties import NumericProperty, ObjectProperty, StringProperty
|
||||
from kivy.uix.relativelayout import RelativeLayout
|
||||
from kivy.uix.widget import WidgetException
|
||||
|
||||
import kivymd.material_resources as m_res
|
||||
from kivymd import uix_path
|
||||
from kivymd.icon_definitions import md_icons
|
||||
from kivymd.uix.button import MDIconButton
|
||||
from kivymd.uix.list import (
|
||||
IconLeftWidget,
|
||||
ImageLeftWidget,
|
||||
IRightBodyTouch,
|
||||
OneLineAvatarIconListItem,
|
||||
ThreeLineAvatarIconListItem,
|
||||
TwoLineAvatarIconListItem,
|
||||
TwoLineListItem,
|
||||
)
|
||||
|
||||
with open(
|
||||
os.path.join(uix_path, "expansionpanel", "expansionpanel.kv"),
|
||||
encoding="utf-8",
|
||||
) as kv_file:
|
||||
Builder.load_string(kv_file.read())
|
||||
|
||||
|
||||
class MDExpansionChevronRight(IRightBodyTouch, MDIconButton):
|
||||
"""Chevron icon on the right panel."""
|
||||
|
||||
_angle = NumericProperty(0)
|
||||
|
||||
|
||||
class MDExpansionPanelOneLine(OneLineAvatarIconListItem):
|
||||
"""
|
||||
Single line panel.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivymd.uix.list.OneLineAvatarIconListItem` class documentation.
|
||||
"""
|
||||
|
||||
|
||||
class MDExpansionPanelTwoLine(TwoLineAvatarIconListItem):
|
||||
"""
|
||||
Two-line panel.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivymd.uix.list.TwoLineAvatarIconListItem` class documentation.
|
||||
"""
|
||||
|
||||
|
||||
class MDExpansionPanelThreeLine(ThreeLineAvatarIconListItem):
|
||||
"""
|
||||
Three-line panel.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivymd.uix.list.ThreeLineAvatarIconListItem` class documentation.
|
||||
"""
|
||||
|
||||
|
||||
class MDExpansionPanelLabel(TwoLineListItem):
|
||||
"""
|
||||
Label panel.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivymd.uix.list.TwoLineListItem` class documentation.
|
||||
|
||||
..warning:: This class is created for use in the
|
||||
:class:`~kivymd.uix.stepper.MDStepperVertical` and
|
||||
:class:`~kivymd.uix.stepper.MDStepper` classes, and has not
|
||||
been tested for use outside of these classes.
|
||||
"""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Clock.schedule_once(self.set_paddings)
|
||||
|
||||
def set_paddings(self, interval: Union[int, float]) -> None:
|
||||
self._txt_bot_pad = dp(36)
|
||||
self._txt_left_pad = dp(0)
|
||||
|
||||
|
||||
class MDExpansionPanel(RelativeLayout):
|
||||
"""
|
||||
Expansion panel class.
|
||||
|
||||
For more information, see in the
|
||||
:class:`~kivy.uix.relativelayout.RelativeLayout` classes documentation.
|
||||
|
||||
:Events:
|
||||
:attr:`on_open`
|
||||
Called when a panel is opened.
|
||||
:attr:`on_close`
|
||||
Called when a panel is closed.
|
||||
"""
|
||||
|
||||
content = ObjectProperty()
|
||||
"""
|
||||
Content of panel. Must be `Kivy` widget.
|
||||
|
||||
:attr:`content` is an :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
icon = StringProperty()
|
||||
"""
|
||||
Icon of panel.
|
||||
|
||||
Icon Should be either be a path to an image or
|
||||
a logo name in :class:`~kivymd.icon_definitions.md_icons`
|
||||
|
||||
:attr:`icon` is an :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `''`.
|
||||
"""
|
||||
|
||||
opening_transition = StringProperty("out_cubic")
|
||||
"""
|
||||
The name of the animation transition type to use when animating to
|
||||
the :attr:`state` `'open'`.
|
||||
|
||||
:attr:`opening_transition` is a :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `'out_cubic'`.
|
||||
"""
|
||||
|
||||
opening_time = NumericProperty(0.2)
|
||||
"""
|
||||
The time taken for the panel to slide to the :attr:`state` `'open'`.
|
||||
|
||||
:attr:`opening_time` is a :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0.2`.
|
||||
"""
|
||||
|
||||
closing_transition = StringProperty("out_sine")
|
||||
"""
|
||||
The name of the animation transition type to use when animating to
|
||||
the :attr:`state` 'close'.
|
||||
|
||||
:attr:`closing_transition` is a :class:`~kivy.properties.StringProperty`
|
||||
and defaults to `'out_sine'`.
|
||||
"""
|
||||
|
||||
closing_time = NumericProperty(0.2)
|
||||
"""
|
||||
The time taken for the panel to slide to the :attr:`state` `'close'`.
|
||||
|
||||
:attr:`closing_time` is a :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0.2`.
|
||||
"""
|
||||
|
||||
panel_cls = ObjectProperty()
|
||||
"""
|
||||
Panel object. The object must be one of the classes
|
||||
:class:`~MDExpansionPanelOneLine`, :class:`~MDExpansionPanelTwoLine` or
|
||||
:class:`~MDExpansionPanelThreeLine`.
|
||||
|
||||
:attr:`panel_cls` is a :class:`~kivy.properties.ObjectProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
_state = StringProperty("close")
|
||||
_anim_playing = False
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.register_event_type("on_open")
|
||||
self.register_event_type("on_close")
|
||||
|
||||
if self.panel_cls and isinstance(
|
||||
self.panel_cls,
|
||||
(
|
||||
MDExpansionPanelOneLine,
|
||||
MDExpansionPanelTwoLine,
|
||||
MDExpansionPanelThreeLine,
|
||||
MDExpansionPanelLabel,
|
||||
),
|
||||
):
|
||||
self.panel_cls.pos_hint = {"top": 1}
|
||||
self.panel_cls._no_ripple_effect = True
|
||||
self.panel_cls.bind(
|
||||
on_release=lambda x: self.check_open_panel(self.panel_cls)
|
||||
)
|
||||
if not isinstance(self.panel_cls, MDExpansionPanelLabel):
|
||||
self.chevron = MDExpansionChevronRight()
|
||||
self.panel_cls.add_widget(self.chevron)
|
||||
if self.icon:
|
||||
if self.icon in md_icons.keys():
|
||||
self.panel_cls.add_widget(
|
||||
IconLeftWidget(
|
||||
icon=self.icon,
|
||||
pos_hint={"center_y": 0.5},
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.panel_cls.add_widget(
|
||||
ImageLeftWidget(
|
||||
source=self.icon, pos_hint={"center_y": 0.5}
|
||||
)
|
||||
)
|
||||
else:
|
||||
self.panel_cls.remove_widget(
|
||||
self.panel_cls.ids._left_container
|
||||
)
|
||||
self.panel_cls._txt_left_pad = 0
|
||||
else:
|
||||
# if no icon
|
||||
self.panel_cls._txt_left_pad = m_res.HORIZ_MARGINS
|
||||
self.add_widget(self.panel_cls)
|
||||
else:
|
||||
raise ValueError(
|
||||
"KivyMD: `panel_cls` object must be must be one of the "
|
||||
"objects from the list\n"
|
||||
"[MDExpansionPanelOneLine, MDExpansionPanelTwoLine, "
|
||||
"MDExpansionPanelThreeLine]"
|
||||
)
|
||||
|
||||
def on_open(self, *args):
|
||||
"""Called when a panel is opened."""
|
||||
|
||||
def on_close(self, *args):
|
||||
"""Called when a panel is closed."""
|
||||
|
||||
def check_open_panel(
|
||||
self,
|
||||
instance_panel: [
|
||||
MDExpansionPanelThreeLine,
|
||||
MDExpansionPanelTwoLine,
|
||||
MDExpansionPanelThreeLine,
|
||||
MDExpansionPanelLabel,
|
||||
],
|
||||
) -> None:
|
||||
"""
|
||||
Called when you click on the panel. Called methods to open or close
|
||||
a panel.
|
||||
"""
|
||||
|
||||
press_current_panel = False
|
||||
for panel in self.parent.children:
|
||||
if isinstance(panel, MDExpansionPanel):
|
||||
if len(panel.children) == 2:
|
||||
if instance_panel is panel.children[1]:
|
||||
press_current_panel = True
|
||||
panel.remove_widget(panel.children[0])
|
||||
if not isinstance(self.panel_cls, MDExpansionPanelLabel):
|
||||
chevron = panel.children[0].children[0].children[0]
|
||||
self.set_chevron_up(chevron)
|
||||
self.close_panel(panel, press_current_panel)
|
||||
self.dispatch("on_close")
|
||||
break
|
||||
if not press_current_panel:
|
||||
self.set_chevron_down()
|
||||
|
||||
def set_chevron_down(self) -> None:
|
||||
"""Sets the chevron down."""
|
||||
|
||||
if not isinstance(self.panel_cls, MDExpansionPanelLabel):
|
||||
Animation(_angle=-90, d=self.opening_time).start(self.chevron)
|
||||
self.open_panel()
|
||||
self.dispatch("on_open")
|
||||
|
||||
def set_chevron_up(self, instance_chevron: MDExpansionChevronRight) -> None:
|
||||
"""Sets the chevron up."""
|
||||
|
||||
if not isinstance(self.panel_cls, MDExpansionPanelLabel):
|
||||
Animation(_angle=0, d=self.closing_time).start(instance_chevron)
|
||||
|
||||
def close_panel(
|
||||
self, instance_expansion_panel, press_current_panel: bool
|
||||
) -> None:
|
||||
"""Method closes the panel."""
|
||||
|
||||
if self._anim_playing:
|
||||
return
|
||||
|
||||
if press_current_panel:
|
||||
self._anim_playing = True
|
||||
|
||||
self._state = "close"
|
||||
|
||||
anim = Animation(
|
||||
height=self.panel_cls.height,
|
||||
d=self.closing_time,
|
||||
t=self.closing_transition,
|
||||
)
|
||||
anim.bind(on_complete=self._disable_anim)
|
||||
anim.start(instance_expansion_panel)
|
||||
|
||||
def open_panel(self, *args) -> None:
|
||||
"""Method opens a panel."""
|
||||
|
||||
if self._anim_playing:
|
||||
return
|
||||
|
||||
self._anim_playing = True
|
||||
self._state = "open"
|
||||
|
||||
anim = Animation(
|
||||
height=self.content.height + self.height,
|
||||
d=self.opening_time,
|
||||
t=self.opening_transition,
|
||||
)
|
||||
anim.bind(on_complete=self._add_content)
|
||||
anim.bind(on_complete=self._disable_anim)
|
||||
anim.start(self)
|
||||
|
||||
def get_state(self) -> str:
|
||||
"""Returns the state of panel. Can be `close` or `open` ."""
|
||||
|
||||
return self._state
|
||||
|
||||
def add_widget(self, widget, index=0, canvas=None):
|
||||
if isinstance(
|
||||
widget,
|
||||
(
|
||||
MDExpansionPanelOneLine,
|
||||
MDExpansionPanelTwoLine,
|
||||
MDExpansionPanelThreeLine,
|
||||
MDExpansionPanelLabel,
|
||||
),
|
||||
):
|
||||
self.height = widget.height
|
||||
return super().add_widget(widget)
|
||||
|
||||
def _disable_anim(self, *args):
|
||||
self._anim_playing = False
|
||||
|
||||
def _add_content(self, *args):
|
||||
if self.content:
|
||||
try:
|
||||
if isinstance(self.panel_cls, MDExpansionPanelLabel):
|
||||
self.content.y = dp(36)
|
||||
self.add_widget(self.content)
|
||||
except WidgetException:
|
||||
pass
|
Loading…
Add table
Add a link
Reference in a new issue