├── kivymd
├── tools
│ ├── __init__.py
│ ├── release
│ │ ├── __init__.py
│ │ ├── git_commands.py
│ │ ├── argument_parser.py
│ │ └── update_icons.py
│ ├── packaging
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-38.pyc
│ │ │ └── __init__.cpython-39.pyc
│ │ └── pyinstaller
│ │ │ ├── __pycache__
│ │ │ ├── __init__.cpython-38.pyc
│ │ │ └── __init__.cpython-39.pyc
│ │ │ ├── hook-kivymd.py
│ │ │ └── __init__.py
│ └── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ └── __init__.cpython-39.pyc
├── utils
│ ├── __init__.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ ├── __init__.cpython-39.pyc
│ │ ├── fitimage.cpython-38.pyc
│ │ ├── fitimage.cpython-39.pyc
│ │ └── hot_reload_viewer.cpython-39.pyc
│ ├── fpsmonitor.py
│ ├── asynckivy.py
│ ├── cropimage.py
│ ├── fitimage.py
│ └── hot_reload_viewer.py
├── toast
│ ├── kivytoast
│ │ ├── __init__.py
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-38.pyc
│ │ │ ├── __init__.cpython-39.pyc
│ │ │ ├── kivytoast.cpython-38.pyc
│ │ │ └── kivytoast.cpython-39.pyc
│ │ └── kivytoast.py
│ ├── __pycache__
│ │ ├── __init__.cpython-38.pyc
│ │ └── __init__.cpython-39.pyc
│ ├── __init__.py
│ ├── androidtoast
│ │ ├── __init__.py
│ │ └── androidtoast.py
│ ├── LICENSE
│ └── README.md
├── images
│ ├── folder.png
│ ├── quad_shadow-0.png
│ ├── quad_shadow-1.png
│ ├── quad_shadow-2.png
│ ├── rec_shadow-0.png
│ ├── rec_shadow-1.png
│ ├── transparent.png
│ ├── rec_st_shadow-0.png
│ ├── rec_st_shadow-1.png
│ ├── rec_st_shadow-2.png
│ ├── round_shadow-0.png
│ ├── round_shadow-1.png
│ ├── round_shadow-2.png
│ ├── rec_shadow.atlas
│ ├── quad_shadow.atlas
│ ├── round_shadow.atlas
│ └── rec_st_shadow.atlas
├── fonts
│ ├── Roboto-Bold.ttf
│ ├── Roboto-Thin.ttf
│ ├── Roboto-Black.ttf
│ ├── Roboto-Italic.ttf
│ ├── Roboto-Light.ttf
│ ├── Roboto-Medium.ttf
│ ├── Roboto-Regular.ttf
│ ├── Roboto-BlackItalic.ttf
│ ├── Roboto-BoldItalic.ttf
│ ├── Roboto-LightItalic.ttf
│ ├── Roboto-MediumItalic.ttf
│ ├── Roboto-ThinItalic.ttf
│ └── materialdesignicons-webfont.ttf
├── __pycache__
│ ├── app.cpython-38.pyc
│ ├── app.cpython-39.pyc
│ ├── theming.cpython-38.pyc
│ ├── theming.cpython-39.pyc
│ ├── __init__.cpython-38.pyc
│ ├── __init__.cpython-39.pyc
│ ├── color_definitions.cpython-38.pyc
│ ├── color_definitions.cpython-39.pyc
│ ├── factory_registers.cpython-38.pyc
│ ├── factory_registers.cpython-39.pyc
│ ├── font_definitions.cpython-38.pyc
│ ├── font_definitions.cpython-39.pyc
│ ├── icon_definitions.cpython-38.pyc
│ ├── icon_definitions.cpython-39.pyc
│ ├── material_resources.cpython-38.pyc
│ ├── material_resources.cpython-39.pyc
│ ├── theming_dynamic_text.cpython-38.pyc
│ └── theming_dynamic_text.cpython-39.pyc
├── uix
│ ├── __pycache__
│ │ ├── card.cpython-38.pyc
│ │ ├── card.cpython-39.pyc
│ │ ├── chip.cpython-38.pyc
│ │ ├── chip.cpython-39.pyc
│ │ ├── label.cpython-38.pyc
│ │ ├── label.cpython-39.pyc
│ │ ├── list.cpython-38.pyc
│ │ ├── list.cpython-39.pyc
│ │ ├── menu.cpython-38.pyc
│ │ ├── __init__.cpython-38.pyc
│ │ ├── __init__.cpython-39.pyc
│ │ ├── button.cpython-38.pyc
│ │ ├── button.cpython-39.pyc
│ │ ├── dialog.cpython-38.pyc
│ │ ├── dialog.cpython-39.pyc
│ │ ├── picker.cpython-38.pyc
│ │ ├── picker.cpython-39.pyc
│ │ ├── slider.cpython-39.pyc
│ │ ├── toolbar.cpython-38.pyc
│ │ ├── toolbar.cpython-39.pyc
│ │ ├── tooltip.cpython-38.pyc
│ │ ├── tooltip.cpython-39.pyc
│ │ ├── boxlayout.cpython-38.pyc
│ │ ├── boxlayout.cpython-39.pyc
│ │ ├── gridlayout.cpython-38.pyc
│ │ ├── gridlayout.cpython-39.pyc
│ │ ├── textfield.cpython-38.pyc
│ │ ├── textfield.cpython-39.pyc
│ │ ├── floatlayout.cpython-38.pyc
│ │ ├── floatlayout.cpython-39.pyc
│ │ ├── stacklayout.cpython-38.pyc
│ │ ├── stacklayout.cpython-39.pyc
│ │ ├── circularlayout.cpython-38.pyc
│ │ ├── circularlayout.cpython-39.pyc
│ │ ├── relativelayout.cpython-38.pyc
│ │ ├── relativelayout.cpython-39.pyc
│ │ ├── selectioncontrol.cpython-38.pyc
│ │ └── selectioncontrol.cpython-39.pyc
│ ├── behaviors
│ │ ├── __pycache__
│ │ │ ├── __init__.cpython-38.pyc
│ │ │ ├── __init__.cpython-39.pyc
│ │ │ ├── elevation.cpython-38.pyc
│ │ │ ├── elevation.cpython-39.pyc
│ │ │ ├── focus_behavior.cpython-38.pyc
│ │ │ ├── focus_behavior.cpython-39.pyc
│ │ │ ├── hover_behavior.cpython-38.pyc
│ │ │ ├── hover_behavior.cpython-39.pyc
│ │ │ ├── magic_behavior.cpython-38.pyc
│ │ │ ├── magic_behavior.cpython-39.pyc
│ │ │ ├── ripple_behavior.cpython-38.pyc
│ │ │ ├── ripple_behavior.cpython-39.pyc
│ │ │ ├── touch_behavior.cpython-38.pyc
│ │ │ ├── touch_behavior.cpython-39.pyc
│ │ │ ├── backgroundcolor_behavior.cpython-38.pyc
│ │ │ └── backgroundcolor_behavior.cpython-39.pyc
│ │ ├── __init__.py
│ │ ├── touch_behavior.py
│ │ ├── focus_behavior.py
│ │ ├── magic_behavior.py
│ │ ├── toggle_behavior.py
│ │ └── backgroundcolor_behavior.py
│ ├── screen.py
│ ├── relativelayout.py
│ ├── floatlayout.py
│ ├── boxlayout.py
│ ├── gridlayout.py
│ ├── stacklayout.py
│ ├── __init__.py
│ ├── dropdownitem.py
│ ├── circularlayout.py
│ ├── refreshlayout.py
│ └── carousel.py
├── tests
│ ├── test_icon_definitions.py
│ ├── test_font_definitions.py
│ ├── test_app.py
│ └── pyinstaller
│ │ └── test_pyinstaller_packaging.py
├── stiffscroll
│ ├── README.md
│ └── LICENSE
├── material_resources.py
├── font_definitions.py
├── app.py
├── __init__.py
├── theming_dynamic_text.py
└── factory_registers.py
├── .gitignore
├── icons.ttf
├── reminder.db
├── .gitattributes
├── Roboto-Black.ttf
├── other
├── icon.blend
├── icon.blend1
├── color scheme.py
├── color scheme.kv
├── gesture pad.py
├── gesture_box.py
└── my_gestures.py
├── remindyicon.png
├── Roboto-Medium.ttf
├── Roboto-Regular.ttf
├── reminder design.png
├── pics
├── design style.webp
├── Color inspiration.png
├── reminder design.png
├── reminder design style.png
├── todo_and_translator_4x.webp
├── Color Hunt Palette 117601.png
├── Color Hunt Palette 281694.png
├── Color Hunt Palette 282007.png
├── photo_2022-06-01_20-29-57.jpg
├── photo_2022-06-01_20-30-03.jpg
├── 31e41c5e6c832e94816a84b3c08bdf97.webp
├── Screenshot from 2021-03-10 22-46-21.png
└── check.svg
├── __pycache__
├── theming.cpython-38.pyc
└── toolbar.cpython-38.pyc
├── suma.py
├── scr
├── ReminderMarkComp.java
├── FullScreenNotify.java
├── ReminderSnooze.java
├── ReminderAlarmReceiver.java
└── ReminderRepeatingAlarmReceiver.java
├── README.md
├── theming.py
└── reminderscheduler.py
/kivymd/tools/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivymd/utils/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivymd/tools/release/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivymd/tools/packaging/__init__.py:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | bin/
2 | .buildozer/
3 |
4 |
--------------------------------------------------------------------------------
/icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/icons.ttf
--------------------------------------------------------------------------------
/reminder.db:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/reminder.db
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Auto detect text files and perform LF normalization
2 | * text=auto
3 |
--------------------------------------------------------------------------------
/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/Roboto-Black.ttf
--------------------------------------------------------------------------------
/other/icon.blend:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/other/icon.blend
--------------------------------------------------------------------------------
/remindyicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/remindyicon.png
--------------------------------------------------------------------------------
/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/kivymd/toast/kivytoast/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ("toast",)
2 |
3 | from .kivytoast import toast
4 |
--------------------------------------------------------------------------------
/other/icon.blend1:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/other/icon.blend1
--------------------------------------------------------------------------------
/reminder design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/reminder design.png
--------------------------------------------------------------------------------
/pics/design style.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/design style.webp
--------------------------------------------------------------------------------
/kivymd/images/folder.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/folder.png
--------------------------------------------------------------------------------
/pics/Color inspiration.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/Color inspiration.png
--------------------------------------------------------------------------------
/pics/reminder design.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/reminder design.png
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Bold.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Thin.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Thin.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Black.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Black.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Italic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Italic.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Light.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Light.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Medium.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Medium.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-Regular.ttf
--------------------------------------------------------------------------------
/kivymd/images/quad_shadow-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/quad_shadow-0.png
--------------------------------------------------------------------------------
/kivymd/images/quad_shadow-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/quad_shadow-1.png
--------------------------------------------------------------------------------
/kivymd/images/quad_shadow-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/quad_shadow-2.png
--------------------------------------------------------------------------------
/kivymd/images/rec_shadow-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/rec_shadow-0.png
--------------------------------------------------------------------------------
/kivymd/images/rec_shadow-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/rec_shadow-1.png
--------------------------------------------------------------------------------
/kivymd/images/transparent.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/transparent.png
--------------------------------------------------------------------------------
/pics/reminder design style.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/reminder design style.png
--------------------------------------------------------------------------------
/kivymd/images/rec_st_shadow-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/rec_st_shadow-0.png
--------------------------------------------------------------------------------
/kivymd/images/rec_st_shadow-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/rec_st_shadow-1.png
--------------------------------------------------------------------------------
/kivymd/images/rec_st_shadow-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/rec_st_shadow-2.png
--------------------------------------------------------------------------------
/kivymd/images/round_shadow-0.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/round_shadow-0.png
--------------------------------------------------------------------------------
/kivymd/images/round_shadow-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/round_shadow-1.png
--------------------------------------------------------------------------------
/kivymd/images/round_shadow-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/images/round_shadow-2.png
--------------------------------------------------------------------------------
/pics/todo_and_translator_4x.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/todo_and_translator_4x.webp
--------------------------------------------------------------------------------
/__pycache__/theming.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/__pycache__/theming.cpython-38.pyc
--------------------------------------------------------------------------------
/__pycache__/toolbar.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/__pycache__/toolbar.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-BlackItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-BlackItalic.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-BoldItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-BoldItalic.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-LightItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-LightItalic.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-MediumItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-MediumItalic.ttf
--------------------------------------------------------------------------------
/kivymd/fonts/Roboto-ThinItalic.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/Roboto-ThinItalic.ttf
--------------------------------------------------------------------------------
/pics/Color Hunt Palette 117601.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/Color Hunt Palette 117601.png
--------------------------------------------------------------------------------
/pics/Color Hunt Palette 281694.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/Color Hunt Palette 281694.png
--------------------------------------------------------------------------------
/pics/Color Hunt Palette 282007.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/Color Hunt Palette 282007.png
--------------------------------------------------------------------------------
/pics/photo_2022-06-01_20-29-57.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/photo_2022-06-01_20-29-57.jpg
--------------------------------------------------------------------------------
/pics/photo_2022-06-01_20-30-03.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/photo_2022-06-01_20-30-03.jpg
--------------------------------------------------------------------------------
/kivymd/__pycache__/app.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/app.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/app.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/app.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/theming.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/theming.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/theming.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/theming.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/card.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/card.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/card.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/card.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/chip.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/chip.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/chip.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/chip.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/label.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/label.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/label.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/label.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/list.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/list.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/list.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/list.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/menu.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/menu.cpython-38.pyc
--------------------------------------------------------------------------------
/pics/31e41c5e6c832e94816a84b3c08bdf97.webp:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/31e41c5e6c832e94816a84b3c08bdf97.webp
--------------------------------------------------------------------------------
/kivymd/fonts/materialdesignicons-webfont.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/fonts/materialdesignicons-webfont.ttf
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/button.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/button.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/button.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/button.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/dialog.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/dialog.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/dialog.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/dialog.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/picker.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/picker.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/picker.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/picker.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/slider.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/slider.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/toolbar.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/toolbar.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/toolbar.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/toolbar.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/tooltip.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/tooltip.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/tooltip.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/tooltip.cpython-39.pyc
--------------------------------------------------------------------------------
/pics/Screenshot from 2021-03-10 22-46-21.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/pics/Screenshot from 2021-03-10 22-46-21.png
--------------------------------------------------------------------------------
/kivymd/toast/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/toast/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/toast/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/toast/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/tools/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/tools/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/tools/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/tools/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/boxlayout.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/boxlayout.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/boxlayout.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/boxlayout.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/gridlayout.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/gridlayout.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/gridlayout.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/gridlayout.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/textfield.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/textfield.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/textfield.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/textfield.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/utils/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/utils/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/utils/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/utils/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/utils/__pycache__/fitimage.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/utils/__pycache__/fitimage.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/utils/__pycache__/fitimage.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/utils/__pycache__/fitimage.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/color_definitions.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/color_definitions.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/color_definitions.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/color_definitions.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/factory_registers.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/factory_registers.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/factory_registers.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/factory_registers.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/font_definitions.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/font_definitions.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/font_definitions.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/font_definitions.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/icon_definitions.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/icon_definitions.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/icon_definitions.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/icon_definitions.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/floatlayout.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/floatlayout.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/floatlayout.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/floatlayout.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/stacklayout.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/stacklayout.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/stacklayout.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/stacklayout.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/material_resources.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/material_resources.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/material_resources.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/material_resources.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/circularlayout.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/circularlayout.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/circularlayout.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/circularlayout.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/relativelayout.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/relativelayout.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/relativelayout.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/relativelayout.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/theming_dynamic_text.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/theming_dynamic_text.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/__pycache__/theming_dynamic_text.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/__pycache__/theming_dynamic_text.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/selectioncontrol.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/selectioncontrol.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/__pycache__/selectioncontrol.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/__pycache__/selectioncontrol.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/toast/kivytoast/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/toast/kivytoast/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/toast/kivytoast/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/toast/kivytoast/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/tools/packaging/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/tools/packaging/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/tools/packaging/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/tools/packaging/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/elevation.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/elevation.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/elevation.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/elevation.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/utils/__pycache__/hot_reload_viewer.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/utils/__pycache__/hot_reload_viewer.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/toast/kivytoast/__pycache__/kivytoast.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/toast/kivytoast/__pycache__/kivytoast.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/toast/kivytoast/__pycache__/kivytoast.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/toast/kivytoast/__pycache__/kivytoast.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/focus_behavior.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/focus_behavior.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/focus_behavior.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/focus_behavior.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/hover_behavior.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/hover_behavior.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/hover_behavior.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/hover_behavior.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/magic_behavior.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/magic_behavior.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/magic_behavior.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/magic_behavior.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/ripple_behavior.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/ripple_behavior.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/ripple_behavior.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/ripple_behavior.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/touch_behavior.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/touch_behavior.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/touch_behavior.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/touch_behavior.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/tools/packaging/pyinstaller/__pycache__/__init__.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/tools/packaging/pyinstaller/__pycache__/__init__.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/tools/packaging/pyinstaller/__pycache__/__init__.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/tools/packaging/pyinstaller/__pycache__/__init__.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/backgroundcolor_behavior.cpython-38.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/backgroundcolor_behavior.cpython-38.pyc
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__pycache__/backgroundcolor_behavior.cpython-39.pyc:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Guhan-SenSam/Reminder-App/HEAD/kivymd/uix/behaviors/__pycache__/backgroundcolor_behavior.cpython-39.pyc
--------------------------------------------------------------------------------
/kivymd/toast/__init__.py:
--------------------------------------------------------------------------------
1 | __all__ = ("toast",)
2 |
3 | from kivy.utils import platform
4 |
5 | if platform == "android":
6 | try:
7 | from .androidtoast import toast
8 | except BaseException:
9 | from .kivytoast import toast
10 | else:
11 | from .kivytoast import toast
12 |
--------------------------------------------------------------------------------
/kivymd/toast/androidtoast/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Toast for Android device
3 | ========================
4 |
5 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toast.png
6 | :align: center
7 |
8 | """
9 |
10 | __all__ = ("toast",)
11 |
12 | from .androidtoast import toast
13 |
--------------------------------------------------------------------------------
/kivymd/tests/test_icon_definitions.py:
--------------------------------------------------------------------------------
1 | def test_icons_have_size():
2 | from kivy.core.text import Label
3 |
4 | from kivymd.icon_definitions import md_icons
5 |
6 | lbl = Label(font_name="Icons")
7 | for icon_name, icon_value in md_icons.items():
8 | assert len(icon_value) == 1
9 | lbl.refresh()
10 | assert lbl.get_extents(icon_value) is not None
11 |
--------------------------------------------------------------------------------
/other/color scheme.py:
--------------------------------------------------------------------------------
1 | from kivymd.app import MDApp
2 | from kivy.lang import Builder
3 | from kivy.uix.boxlayout import BoxLayout
4 |
5 | from kivymd.uix.card import MDCard
6 |
7 | class tempstuff(BoxLayout):
8 | pass
9 |
10 | class Mainapp(MDApp):
11 |
12 | def build(self):
13 | Builder.load_file('test.kv')
14 | return tempstuff()
15 |
16 | Mainapp().run()
17 |
--------------------------------------------------------------------------------
/pics/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/kivymd/tests/test_font_definitions.py:
--------------------------------------------------------------------------------
1 | def test_fonts_registration():
2 | # This should register fonts:
3 | from kivy.core.text import LabelBase
4 |
5 | import kivymd # NOQA
6 |
7 | fonts = [
8 | "Roboto",
9 | "RobotoThin",
10 | "RobotoLight",
11 | "RobotoMedium",
12 | "RobotoBlack",
13 | "Icons",
14 | ]
15 | for font in fonts:
16 | assert font in LabelBase._fonts.keys()
17 |
--------------------------------------------------------------------------------
/kivymd/tools/packaging/pyinstaller/hook-kivymd.py:
--------------------------------------------------------------------------------
1 | """
2 | PyInstaller hook for KivyMD
3 | ===========================
4 |
5 | Adds fonts and images to package.
6 |
7 | All modules from uix directory are added by Kivy hook.
8 | """
9 |
10 | from pathlib import Path
11 |
12 | import kivymd
13 |
14 | datas = [
15 | (
16 | kivymd.fonts_path,
17 | str(Path("kivymd").joinpath(Path(kivymd.fonts_path).name)),
18 | ),
19 | (
20 | kivymd.images_path,
21 | str(Path("kivymd").joinpath(Path(kivymd.images_path).name)),
22 | ),
23 | ]
24 |
--------------------------------------------------------------------------------
/kivymd/tests/test_app.py:
--------------------------------------------------------------------------------
1 | from kivy import lang
2 | from kivy.clock import Clock
3 | from kivy.tests.common import GraphicUnitTest
4 |
5 | from kivymd.app import MDApp
6 | from kivymd.theming import ThemeManager
7 |
8 |
9 | class AppTest(GraphicUnitTest):
10 | def test_start_raw_app(self):
11 | lang._delayed_start = None
12 | a = MDApp()
13 | Clock.schedule_once(a.stop, 0.1)
14 | a.run()
15 |
16 | def test_theme_manager_existance(self):
17 | lang._delayed_start = None
18 | a = MDApp()
19 | Clock.schedule_once(a.stop, 0.1)
20 | a.run()
21 | assert isinstance(a.theme_cls, ThemeManager)
22 |
--------------------------------------------------------------------------------
/kivymd/images/rec_shadow.atlas:
--------------------------------------------------------------------------------
1 | {"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]}}
--------------------------------------------------------------------------------
/kivymd/images/quad_shadow.atlas:
--------------------------------------------------------------------------------
1 | {"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]}}
--------------------------------------------------------------------------------
/kivymd/images/round_shadow.atlas:
--------------------------------------------------------------------------------
1 | {"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]}}
--------------------------------------------------------------------------------
/kivymd/images/rec_st_shadow.atlas:
--------------------------------------------------------------------------------
1 | {"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]}}
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Behaviors
3 | =========
4 |
5 | Modules and classes implementing various behaviors for buttons etc.
6 | """
7 |
8 | # flake8: NOQA
9 | from .hover_behavior import HoverBehavior # isort:skip
10 | from .backgroundcolor_behavior import (
11 | BackgroundColorBehavior,
12 | SpecificBackgroundColorBehavior,
13 | )
14 | from .elevation import (
15 | CircularElevationBehavior,
16 | CommonElevationBehavior,
17 | FakeCircularElevationBehavior,
18 | FakeRectangularElevationBehavior,
19 | ObservableShadow,
20 | RectangularElevationBehavior,
21 | RoundedRectangularElevationBehavior,
22 | )
23 | from .focus_behavior import FocusBehavior
24 | from .magic_behavior import MagicBehavior
25 | from .ripple_behavior import CircularRippleBehavior, RectangularRippleBehavior
26 | from .touch_behavior import TouchBehavior
27 |
--------------------------------------------------------------------------------
/kivymd/uix/screen.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Screen
3 | =================
4 |
5 | :class:`~kivy.uix.screenmanager.Screen` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 | Screen
9 | ------
10 |
11 | .. code-block::
12 |
13 | Screen:
14 | canvas:
15 | Color:
16 | rgba: app.theme_cls.primary_color
17 | RoundedRectangle:
18 | pos: self.pos
19 | size: self.size
20 | radius: [25, 0, 0, 0]
21 |
22 | MDScreen
23 | --------
24 |
25 | .. code-block::
26 |
27 | MDScreen:
28 | radius: [25, 0, 0, 0]
29 | md_bg_color: app.theme_cls.primary_color
30 | """
31 |
32 | from kivy.uix.screenmanager import Screen
33 |
34 | from kivymd.uix import MDAdaptiveWidget
35 |
36 |
37 | class MDScreen(Screen, MDAdaptiveWidget):
38 | pass
39 |
--------------------------------------------------------------------------------
/other/color scheme.kv:
--------------------------------------------------------------------------------
1 | :
2 | MDCard:
3 | md_bg_color:44/250,62/250,80/250, 1
4 |
5 | Label:
6 | text:'44,62,80, 1 (Main Background Color)'
7 | bold: True
8 |
9 | MDCard:
10 | md_bg_color:50/255,49/255,61/255,1
11 |
12 | Label:
13 | text:'50,49,61,1 (Primary card color)'
14 | bold: True
15 |
16 | MDCard:
17 | md_bg_color:70/255,69/255,81/255,1
18 |
19 | Label:
20 | text:'70,69,81,1 (Secondary card color)'
21 | bold: True
22 |
23 | MDCard:
24 | md_bg_color:90/255,89/255,101/255,1
25 |
26 | Label:
27 | text:'90,89,101,1 (Tertiary card color)'
28 | bold: True
29 |
30 | MDCard:
31 | md_bg_color:218/255,68/255,83/255, 1
32 |
33 | Label:
34 | text:'218,68,83, 1 (Primary accent color)'
35 | bold: True
36 |
--------------------------------------------------------------------------------
/kivymd/uix/relativelayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Relative Layout
3 | ==========================
4 |
5 | :class:`~kivy.uix.relativelayout.RelativeLayout` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 | RelativeLayout
9 | --------------
10 |
11 | .. code-block::
12 |
13 | RelativeLayout:
14 | canvas:
15 | Color:
16 | rgba: app.theme_cls.primary_color
17 | RoundedRectangle:
18 | pos: (0, 0)
19 | size: self.size
20 | radius: [25, ]
21 |
22 | MDRelativeLayout
23 | ----------------
24 |
25 | .. code-block::
26 |
27 | MDRelativeLayout:
28 | radius: [25, ]
29 | md_bg_color: app.theme_cls.primary_color
30 | """
31 |
32 | from kivy.uix.relativelayout import RelativeLayout
33 |
34 | from kivymd.uix import MDAdaptiveWidget
35 |
36 |
37 | class MDRelativeLayout(RelativeLayout, MDAdaptiveWidget):
38 | pass
39 |
--------------------------------------------------------------------------------
/suma.py:
--------------------------------------------------------------------------------
1 | """
2 | Loading multiple instances of a widget over a period of time to prevent lag
3 | """
4 |
5 | from kivy.app import App
6 | from kivy.lang import Builder
7 | from kivy.clock import Clock
8 | from kivy.uix.button import Button
9 | from kivy.animation import Animation
10 |
11 |
12 | KV = '''
13 | GridLayout:
14 | id:container
15 | cols:5
16 | rows:20
17 | '''
18 |
19 |
20 | class MessengerApp(App):
21 |
22 | counter = 0
23 |
24 | def build(self):
25 | self.kv = Builder.load_string(KV)
26 | return self.kv
27 |
28 | def on_start(self):
29 | Clock.schedule_interval(self.btn_create,0.3)
30 |
31 | def btn_create(self,time):
32 | if self.counter<50:
33 | btn = Button(text = str(self.counter))
34 | btn.opacity = 0 # Set the opacity of the button to 0
35 | self.kv.add_widget(btn) # Add the button
36 | Animation(opacity = 1, duration = .25).start(btn) # Duration is < than clock duration
37 | self.counter +=1
38 |
39 |
40 | if __name__ == '__main__':
41 | MessengerApp().run()
42 |
--------------------------------------------------------------------------------
/kivymd/stiffscroll/README.md:
--------------------------------------------------------------------------------
1 | stiffscroll
2 | ===========
3 |
4 | A ScrollEffect for use with a Kivy ScrollView. It makes scrolling more
5 | laborious as you reach the edge of the scrollable area.
6 |
7 | A ScrollView constructed with StiffScrollEffect,
8 | eg. ScrollView(effect_cls=StiffScrollEffect), will get harder to
9 | scroll as you get nearer to its edges. You can scroll all the way to
10 | the edge if you want to, but it will take more finger-movement than
11 | usual.
12 |
13 | Unlike DampedScrollEffect, it is impossible to overscroll with
14 | StiffScrollEffect. That means you cannot push the contents of the
15 | ScrollView far enough to see what's beneath them. This is appropriate
16 | if the ScrollView contains, eg., a background image, like a desktop
17 | wallpaper. Overscrolling may give the impression that there is some
18 | reason to overscroll, even if just to take a peek beneath, and that
19 | impression may be misleading.
20 |
21 | StiffScrollEffect was written by Zachary Spector. His other stuff is at:
22 | https://github.com/LogicalDash/
23 | He can be reached, and possibly hired, at:
24 | zacharyspector@gmail.com
--------------------------------------------------------------------------------
/kivymd/uix/floatlayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Float Layout
3 | =======================
4 |
5 | :class:`~kivy.uix.floatlayout.FloatLayout` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 | FloatLayout
9 | -----------
10 |
11 | .. code-block::
12 |
13 | FloatLayout:
14 | canvas:
15 | Color:
16 | rgba: app.theme_cls.primary_color
17 | RoundedRectangle:
18 | pos: self.pos
19 | size: self.size
20 | radius: [25, 0, 0, 0]
21 |
22 | MDFloatLayout
23 | -------------
24 |
25 | .. code-block::
26 |
27 | MDFloatLayout:
28 | radius: [25, 0, 0, 0]
29 | md_bg_color: app.theme_cls.primary_color
30 |
31 | .. Warning:: For a :class:`~kivy.uix.floatlayout.FloatLayout`, the
32 | ``minimum_size`` attributes are always 0, so you cannot use
33 | ``adaptive_size`` and related options.
34 | """
35 |
36 | from kivy.uix.floatlayout import FloatLayout
37 |
38 | from kivymd.uix import MDAdaptiveWidget
39 |
40 |
41 | class MDFloatLayout(FloatLayout, MDAdaptiveWidget):
42 | pass
43 |
--------------------------------------------------------------------------------
/kivymd/utils/fpsmonitor.py:
--------------------------------------------------------------------------------
1 | """
2 | Monitor module
3 | ==============
4 |
5 | The Monitor module is a toolbar that shows the activity of your current
6 | application :
7 |
8 | * FPS
9 |
10 | """
11 |
12 | from kivy.clock import Clock
13 | from kivy.lang import Builder
14 | from kivy.properties import NumericProperty, StringProperty
15 | from kivy.uix.label import Label
16 |
17 | Builder.load_string(
18 | """
19 | :
20 | size_hint_y: None
21 | height: self.texture_size[1]
22 | text: root._fsp_value
23 | pos_hint: {"top": 1}
24 |
25 | canvas.before:
26 | Color:
27 | rgba: app.theme_cls.primary_dark
28 | Rectangle:
29 | pos: self.pos
30 | size: self.size
31 | """
32 | )
33 |
34 |
35 | class FpsMonitor(Label):
36 | updated_interval = NumericProperty(0.5)
37 | """FPS refresh rate."""
38 |
39 | _fsp_value = StringProperty()
40 |
41 | def start(self):
42 | Clock.schedule_interval(self.update_fps, self.updated_interval)
43 |
44 | def update_fps(self, *args):
45 | self._fsp_value = "FPS: %f" % Clock.get_fps()
46 |
--------------------------------------------------------------------------------
/kivymd/stiffscroll/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 LogicalDash
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/kivymd/material_resources.py:
--------------------------------------------------------------------------------
1 | """
2 | Material Resources
3 | ==================
4 | """
5 |
6 | import os
7 |
8 | from kivy.core.window import Window
9 | from kivy.metrics import dp
10 | from kivy.utils import platform
11 |
12 | if "KIVY_DOC_INCLUDE" in os.environ:
13 | dp = lambda x: x # NOQA: F811
14 |
15 | # Feel free to override this const if you're designing for a device such as
16 | # a GNU/Linux tablet.
17 | DEVICE_IOS = platform == "ios" or platform == "macosx"
18 | if platform != "android" and platform != "ios":
19 | DEVICE_TYPE = "desktop"
20 | elif Window.width >= dp(600) and Window.height >= dp(600):
21 | DEVICE_TYPE = "tablet"
22 | else:
23 | DEVICE_TYPE = "mobile"
24 |
25 | if DEVICE_TYPE == "mobile":
26 | MAX_NAV_DRAWER_WIDTH = dp(300)
27 | HORIZ_MARGINS = dp(16)
28 | STANDARD_INCREMENT = dp(56)
29 | PORTRAIT_TOOLBAR_HEIGHT = STANDARD_INCREMENT
30 | LANDSCAPE_TOOLBAR_HEIGHT = STANDARD_INCREMENT - dp(8)
31 | else:
32 | MAX_NAV_DRAWER_WIDTH = dp(400)
33 | HORIZ_MARGINS = dp(24)
34 | STANDARD_INCREMENT = dp(64)
35 | PORTRAIT_TOOLBAR_HEIGHT = STANDARD_INCREMENT
36 | LANDSCAPE_TOOLBAR_HEIGHT = STANDARD_INCREMENT
37 |
38 | TOUCH_TARGET_HEIGHT = dp(48)
39 |
--------------------------------------------------------------------------------
/kivymd/toast/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2013 Brian - androidtoast library
4 | Copyright (c) 2019 Ivanov Yuri - kivytoast library
5 |
6 | Permission is hereby granted, free of charge, to any person obtaining a copy of
7 | this software and associated documentation files (the "Software"), to deal in
8 | the Software without restriction, including without limitation the rights to
9 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
10 | the Software, and to permit persons to whom the Software is furnished to do so,
11 | subject to the following conditions:
12 |
13 | The above copyright notice and this permission notice shall be included in all
14 | copies or substantial portions of the Software.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
18 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
19 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
20 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--------------------------------------------------------------------------------
/kivymd/toast/README.md:
--------------------------------------------------------------------------------
1 | KivyToast
2 | ========
3 |
4 | A package for working with messages like Toast on Android. It is intended for use in applications written using the Kivy framework.
5 |
6 | This package is an improved version of the package https://github.com/knappador/kivy-toaster in which human toasts are written, written on Kivy.
7 |
8 |
9 |
10 | The package modules are written using the framework for cross-platform development of .
11 | Information about the framework is available at http://kivy.org.
12 |
13 | An example of usage (note that with this import the native implementation of toasts will be used for the Android platform and implementation on Kivy for others:
14 |
15 | ```python
16 | from toast import toast
17 |
18 | ...
19 |
20 | # And then in the code, toasts are available
21 | # by calling the toast function:
22 | toast ('Your message')
23 | ```
24 |
25 | To force the Kivy implementation on the Android platform, use the import of the form:
26 |
27 | ```python
28 | from toast.kivytoast import toast
29 | ```
30 |
31 | PROGRAMMING LANGUAGE
32 | --------------------
33 | Python 2.7 +
34 |
35 | DEPENDENCE
36 | ----------
37 | The [Kivy] framework (http://kivy.org/docs/installation/installation.html)
38 |
39 | LICENSE
40 | -------
41 | MIT
--------------------------------------------------------------------------------
/scr/ReminderMarkComp.java:
--------------------------------------------------------------------------------
1 | package org.org.remindy;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Intent;
5 | import android.content.Context;
6 |
7 | import android.database.sqlite.SQLiteDatabase;
8 | import android.content.ContentValues;
9 | import androidx.core.app.NotificationManagerCompat;
10 | import android.widget.Toast;
11 |
12 |
13 | public class ReminderMarkComp extends BroadcastReceiver{
14 |
15 | @Override
16 | public void onReceive(Context context, Intent intent) {
17 | SQLiteDatabase db = SQLiteDatabase.openDatabase("/data/data/org.remindy.remindy/files/app/reminder.db",null,SQLiteDatabase.OPEN_READWRITE);
18 | db.beginTransaction();
19 | ContentValues cv = new ContentValues();
20 | cv.put("state",1);
21 | String id = String.valueOf(intent.getShortExtra("IDENTIFICATION", (short) 0));
22 | long result = db.update(intent.getExtras().getString("CURRENT_LIST"), cv, "rem_id ="+ id , null);
23 | db.setTransactionSuccessful();
24 | db.endTransaction();
25 | //Now remove the notification from panel
26 | NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
27 | notificationManager.cancel(intent.getExtras().getInt("NOTIFICATION_ID"));
28 | //Show a toast to the user
29 | Toast toast = Toast.makeText(context, "Remider Marked Complete", Toast.LENGTH_SHORT);
30 | toast.show();
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/scr/FullScreenNotify.java:
--------------------------------------------------------------------------------
1 | package org.org.remindy;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import org.remindy.remindy.R;
6 | import android.os.Build;
7 | import android.view.WindowManager;
8 | import android.content.Context;
9 | import android.app.KeyguardManager;
10 |
11 | public class FullScreenNotify extends Activity {
12 |
13 | public void onCreate(Bundle savedInstanceState) {
14 | //Set parameters to ensure device is woken up
15 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
16 | setShowWhenLocked(true);
17 | setTurnScreenOn(true);
18 | this.getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
19 | KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
20 | keyguardManager.requestDismissKeyguard(this, null);
21 |
22 |
23 | } else {
24 | this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
25 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
26 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
27 | WindowManager.LayoutParams.FLAG_FULLSCREEN |
28 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
29 | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
30 | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD);
31 |
32 | };
33 | super.onCreate(savedInstanceState);
34 | // Load xml file
35 | setContentView(R.layout.fullscreenalarm);
36 |
37 | }
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/kivymd/uix/boxlayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Box Layout
3 | =====================
4 |
5 | :class:`~kivy.uix.boxlayout.BoxLayout` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 | BoxLayout
9 | ---------
10 |
11 | .. code-block::
12 |
13 | BoxLayout:
14 | size_hint_y: None
15 | height: self.minimum_height
16 |
17 | canvas:
18 | Color:
19 | rgba: app.theme_cls.primary_color
20 | Rectangle:
21 | pos: self.pos
22 | size: self.size
23 |
24 | MDBoxLayout
25 | -----------
26 |
27 | .. code-block::
28 |
29 | MDBoxLayout:
30 | adaptive_height: True
31 | md_bg_color: app.theme_cls.primary_color
32 |
33 | Available options are:
34 | ----------------------
35 |
36 | - adaptive_height_
37 | - adaptive_width_
38 | - adaptive_size_
39 |
40 | .. adaptive_height:
41 | adaptive_height
42 | ---------------
43 |
44 | .. code-block:: kv
45 |
46 | adaptive_height: True
47 |
48 | Equivalent
49 |
50 | .. code-block:: kv
51 |
52 | size_hint_y: None
53 | height: self.minimum_height
54 |
55 | .. adaptive_width:
56 | adaptive_width
57 | --------------
58 |
59 | .. code-block:: kv
60 |
61 | adaptive_width: True
62 |
63 | Equivalent
64 |
65 | .. code-block:: kv
66 |
67 | size_hint_x: None
68 | height: self.minimum_width
69 |
70 | .. adaptive_size:
71 | adaptive_size
72 | -------------
73 |
74 | .. code-block:: kv
75 |
76 | adaptive_size: True
77 |
78 | Equivalent
79 |
80 | .. code-block:: kv
81 |
82 | size_hint: None, None
83 | size: self.minimum_size
84 | """
85 |
86 | from kivy.uix.boxlayout import BoxLayout
87 |
88 | from kivymd.uix import MDAdaptiveWidget
89 |
90 |
91 | class MDBoxLayout(BoxLayout, MDAdaptiveWidget):
92 | pass
93 |
--------------------------------------------------------------------------------
/kivymd/tools/packaging/pyinstaller/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | PyInstaller hooks
3 | =================
4 |
5 | Add ``hookspath=[kivymd.hooks_path]`` to your .spec file.
6 |
7 | Example of .spec file
8 | =====================
9 |
10 | .. code-block:: python
11 |
12 | # -*- mode: python ; coding: utf-8 -*-
13 |
14 | import sys
15 | import os
16 |
17 | from kivy_deps import sdl2, glew
18 |
19 | from kivymd import hooks_path as kivymd_hooks_path
20 |
21 | path = os.path.abspath(".")
22 |
23 | a = Analysis(
24 | ["main.py"],
25 | pathex=[path],
26 | hookspath=[kivymd_hooks_path],
27 | win_no_prefer_redirects=False,
28 | win_private_assemblies=False,
29 | cipher=None,
30 | noarchive=False,
31 | )
32 | pyz = PYZ(a.pure, a.zipped_data, cipher=None)
33 |
34 | exe = EXE(
35 | pyz,
36 | a.scripts,
37 | a.binaries,
38 | a.zipfiles,
39 | a.datas,
40 | *[Tree(p) for p in (sdl2.dep_bins + glew.dep_bins)],
41 | debug=False,
42 | strip=False,
43 | upx=True,
44 | name="app_name",
45 | console=True,
46 | )
47 | """
48 |
49 | __all__ = ("hooks_path", "get_hook_dirs", "get_pyinstaller_tests")
50 |
51 | import os
52 | from pathlib import Path
53 |
54 | import kivymd
55 |
56 | hooks_path = str(Path(__file__).absolute().parent)
57 | """Path to hook directory to use with PyInstaller.
58 | See :mod:`kivymd.tools.packaging.pyinstaller` for more information."""
59 |
60 |
61 | def get_hook_dirs():
62 | return [hooks_path]
63 |
64 |
65 | def get_pyinstaller_tests():
66 | return [os.path.join(kivymd.path, "tests", "pyinstaller")]
67 |
68 |
69 | if __name__ == "__main__":
70 | print(hooks_path)
71 | print(get_hook_dirs())
72 | print(get_pyinstaller_tests())
73 |
--------------------------------------------------------------------------------
/kivymd/uix/gridlayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Grid Layout
3 | ======================
4 |
5 | :class:`~kivy.uix.gridlayout.GridLayout` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 | GridLayout
9 | ----------
10 |
11 | .. code-block::
12 |
13 | GridLayout:
14 | size_hint_y: None
15 | height: self.minimum_height
16 |
17 | canvas:
18 | Color:
19 | rgba: app.theme_cls.primary_color
20 | Rectangle:
21 | pos: self.pos
22 | size: self.size
23 |
24 | MDGridLayout
25 | ------------
26 |
27 | .. code-block::
28 |
29 | MDGridLayout:
30 | adaptive_height: True
31 | md_bg_color: app.theme_cls.primary_color
32 |
33 | Available options are:
34 | ----------------------
35 |
36 | - adaptive_height_
37 | - adaptive_width_
38 | - adaptive_size_
39 |
40 | .. adaptive_height:
41 | adaptive_height
42 | ---------------
43 |
44 | .. code-block:: kv
45 |
46 | adaptive_height: True
47 |
48 | Equivalent
49 |
50 | .. code-block:: kv
51 |
52 | size_hint_y: None
53 | height: self.minimum_height
54 |
55 | .. adaptive_width:
56 | adaptive_width
57 | --------------
58 |
59 | .. code-block:: kv
60 |
61 | adaptive_width: True
62 |
63 | Equivalent
64 |
65 | .. code-block:: kv
66 |
67 | size_hint_x: None
68 | height: self.minimum_width
69 |
70 | .. adaptive_size:
71 | adaptive_size
72 | -------------
73 |
74 | .. code-block:: kv
75 |
76 | adaptive_size: True
77 |
78 | Equivalent
79 |
80 | .. code-block:: kv
81 |
82 | size_hint: None, None
83 | size: self.minimum_size
84 | """
85 |
86 | from kivy.uix.gridlayout import GridLayout
87 |
88 | from kivymd.uix import MDAdaptiveWidget
89 |
90 |
91 | class MDGridLayout(GridLayout, MDAdaptiveWidget):
92 | pass
93 |
--------------------------------------------------------------------------------
/kivymd/uix/stacklayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/StackLayout
3 | ======================
4 |
5 | :class:`~kivy.uix.stacklayout.StackLayout` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 | StackLayout
9 | -----------
10 |
11 | .. code-block::
12 |
13 | StackLayout:
14 | size_hint_y: None
15 | height: self.minimum_height
16 |
17 | canvas:
18 | Color:
19 | rgba: app.theme_cls.primary_color
20 | Rectangle:
21 | pos: self.pos
22 | size: self.size
23 |
24 | MDStackLayout
25 | -------------
26 |
27 | .. code-block::
28 |
29 | MDStackLayout:
30 | adaptive_height: True
31 | md_bg_color: app.theme_cls.primary_color
32 |
33 | Available options are:
34 | ----------------------
35 |
36 | - adaptive_height_
37 | - adaptive_width_
38 | - adaptive_size_
39 |
40 | .. adaptive_height:
41 | adaptive_height
42 | ---------------
43 |
44 | .. code-block:: kv
45 |
46 | adaptive_height: True
47 |
48 | Equivalent
49 |
50 | .. code-block:: kv
51 |
52 | size_hint_y: None
53 | height: self.minimum_height
54 |
55 | .. adaptive_width:
56 | adaptive_width
57 | --------------
58 |
59 | .. code-block:: kv
60 |
61 | adaptive_width: True
62 |
63 | Equivalent
64 |
65 | .. code-block:: kv
66 |
67 | size_hint_x: None
68 | width: self.minimum_width
69 |
70 | .. adaptive_size:
71 | adaptive_size
72 | -------------
73 |
74 | .. code-block:: kv
75 |
76 | adaptive_size: True
77 |
78 | Equivalent
79 |
80 | .. code-block:: kv
81 |
82 | size_hint: None, None
83 | size: self.minimum_size
84 | """
85 |
86 | from kivy.uix.stacklayout import StackLayout
87 |
88 | from kivymd.uix import MDAdaptiveWidget
89 |
90 |
91 | class MDStackLayout(StackLayout, MDAdaptiveWidget):
92 | pass
93 |
--------------------------------------------------------------------------------
/kivymd/utils/asynckivy.py:
--------------------------------------------------------------------------------
1 | """
2 | asynckivy
3 | =========
4 |
5 | Copyright (c) 2019 Nattōsai Mitō
6 |
7 | GitHub -
8 | https://github.com/gottadiveintopython
9 | GitHub Gist -
10 | https://gist.github.com/gottadiveintopython/5f4a775849f9277081c396de65dc57c1
11 |
12 | """
13 |
14 | __all__ = ("start", "sleep", "event")
15 |
16 | import types
17 | from collections import namedtuple
18 | from functools import partial
19 |
20 | from kivy.clock import Clock
21 |
22 | CallbackParameter = namedtuple("CallbackParameter", ("args", "kwargs"))
23 |
24 |
25 | def start(coro):
26 | def step(*args, **kwargs):
27 | try:
28 | coro.send(CallbackParameter(args, kwargs))(step)
29 | except StopIteration:
30 | pass
31 |
32 | try:
33 | coro.send(None)(step)
34 | except StopIteration:
35 | pass
36 |
37 |
38 | @types.coroutine
39 | def sleep(duration):
40 | # The partial() here looks meaningless. But this is needed in order
41 | # to avoid weak reference.
42 | param = yield lambda step_coro: Clock.schedule_once(
43 | partial(step_coro), duration
44 | )
45 | return param.args[0]
46 |
47 |
48 | class event:
49 | def __init__(self, ed, name):
50 | self.bind_id = None
51 | self.ed = ed
52 | self.name = name
53 |
54 | def bind(self, step_coro):
55 | self.bind_id = bind_id = self.ed.fbind(self.name, self.callback)
56 | assert bind_id > 0 # check if binding succeeded
57 | self.step_coro = step_coro
58 |
59 | def callback(self, *args, **kwargs):
60 | self.parameter = CallbackParameter(args, kwargs)
61 | ed = self.ed
62 | ed.unbind_uid(self.name, self.bind_id)
63 | self.step_coro()
64 |
65 | def __await__(self):
66 | yield self.bind
67 | return self.parameter
68 |
--------------------------------------------------------------------------------
/kivymd/font_definitions.py:
--------------------------------------------------------------------------------
1 | """
2 | Themes/Font Definitions
3 | =======================
4 |
5 | .. seealso::
6 |
7 | `Material Design spec, The type system `_
8 | """
9 |
10 | from kivy.core.text import LabelBase
11 |
12 | from kivymd import fonts_path
13 |
14 | fonts = [
15 | {
16 | "name": "Roboto",
17 | "fn_regular": fonts_path + "Roboto-Regular.ttf",
18 | "fn_bold": fonts_path + "Roboto-Bold.ttf",
19 | "fn_italic": fonts_path + "Roboto-Italic.ttf",
20 | "fn_bolditalic": fonts_path + "Roboto-BoldItalic.ttf",
21 | },
22 | {
23 | "name": "RobotoThin",
24 | "fn_regular": fonts_path + "Roboto-Thin.ttf",
25 | "fn_italic": fonts_path + "Roboto-ThinItalic.ttf",
26 | },
27 | {
28 | "name": "RobotoLight",
29 | "fn_regular": fonts_path + "Roboto-Light.ttf",
30 | "fn_italic": fonts_path + "Roboto-LightItalic.ttf",
31 | },
32 | {
33 | "name": "RobotoMedium",
34 | "fn_regular": fonts_path + "Roboto-Medium.ttf",
35 | "fn_italic": fonts_path + "Roboto-MediumItalic.ttf",
36 | },
37 | {
38 | "name": "RobotoBlack",
39 | "fn_regular": fonts_path + "Roboto-Black.ttf",
40 | "fn_italic": fonts_path + "Roboto-BlackItalic.ttf",
41 | },
42 | {
43 | "name": "Icons",
44 | "fn_regular": fonts_path + "materialdesignicons-webfont.ttf",
45 | },
46 | ]
47 |
48 | for font in fonts:
49 | LabelBase.register(**font)
50 |
51 | theme_font_styles = [
52 | "H1",
53 | "H2",
54 | "H3",
55 | "H4",
56 | "H5",
57 | "H6",
58 | "Subtitle1",
59 | "Subtitle2",
60 | "Body1",
61 | "Body2",
62 | "Button",
63 | "Caption",
64 | "Overline",
65 | "Icon",
66 | ]
67 | """
68 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/font-styles-2.png
69 | """
70 |
--------------------------------------------------------------------------------
/scr/ReminderSnooze.java:
--------------------------------------------------------------------------------
1 | package org.org.remindy;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Intent;
5 | import android.content.Context;
6 | import android.app.PendingIntent;
7 | import java.util.Calendar;
8 | import android.app.AlarmManager;
9 | import androidx.core.app.NotificationManagerCompat;
10 | import android.widget.Toast;
11 |
12 | public class ReminderSnooze extends BroadcastReceiver{
13 |
14 | @Override
15 | public void onReceive(Context context, Intent intent) {
16 |
17 | Intent snoozedrem = new Intent(context,ReminderAlarmReceiver.class);
18 | snoozedrem.putExtra("TITLE", intent.getExtras().getString("TITLE"));
19 | snoozedrem.putExtra("DESCRIPTION", intent.getExtras().getString("DESCRIPTION"));
20 | snoozedrem.putExtra("IDENTIFICATION", intent.getExtras().getShort("IDENTIFICATION"));
21 | snoozedrem.putExtra("CURRENT_LIST", intent.getExtras().getString("CURRENT_LIST"));
22 | snoozedrem.putExtra("INTENT_ID", intent.getExtras().getShort("INTENT_ID"));
23 | PendingIntent pendingsnoozedrem = PendingIntent.getBroadcast(context, intent.getExtras().getShort("INTENT_ID"), snoozedrem, PendingIntent.FLAG_CANCEL_CURRENT);
24 | Calendar calendar = Calendar.getInstance();
25 | Long timetoring = calendar.getTimeInMillis() + 10*60*60*1000;
26 | AlarmManager alarmManager=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
27 | alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,timetoring, pendingsnoozedrem);
28 |
29 | //Now clear the notification from the bar
30 |
31 | NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
32 | notificationManager.cancel(intent.getExtras().getInt("NOTIFICATION_ID"));
33 |
34 | //Give a toast to the user
35 | Toast toast = Toast.makeText(context, "Snoozed for 10 mins", Toast.LENGTH_SHORT);
36 | toast.show();
37 |
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/kivymd/tests/pyinstaller/test_pyinstaller_packaging.py:
--------------------------------------------------------------------------------
1 | """
2 | PyInstaller freezing test
3 | =========================
4 |
5 | PyInstaller must package KivyMD apps correctly.
6 | """
7 |
8 | import subprocess
9 |
10 | from PyInstaller import __main__ as pyi_main
11 |
12 |
13 | def test_datas(tmp_path):
14 | """Test fonts and images."""
15 | app_name = "userapp"
16 | workpath = tmp_path / "build"
17 | distpath = tmp_path / "dist"
18 | app = tmp_path / (app_name + ".py")
19 | app.write_text(
20 | """
21 | import os
22 | import kivymd
23 | from kivy.core.text import LabelBase
24 |
25 | fonts = os.listdir(kivymd.fonts_path)
26 | print(fonts)
27 | assert "Roboto-Regular.ttf" in fonts
28 | assert "materialdesignicons-webfont.ttf" in fonts
29 | print(LabelBase._fonts.keys())
30 | assert "Roboto" in LabelBase._fonts.keys() # NOQA
31 | assert "Icons" in LabelBase._fonts.keys() # NOQA
32 |
33 | images = os.listdir(kivymd.images_path)
34 | print(images)
35 | assert "folder.png" in images
36 | assert "rec_shadow.atlas" in images
37 | """
38 | )
39 | pyi_main.run(
40 | [
41 | "--workpath",
42 | str(workpath),
43 | "--distpath",
44 | str(distpath),
45 | "--specpath",
46 | str(tmp_path),
47 | str(app),
48 | ]
49 | )
50 | subprocess.run([str(distpath / app_name / app_name)], check=True)
51 |
52 |
53 | def test_widgets(tmp_path):
54 | """Test that all widgets are accesible."""
55 | app_name = "userapp"
56 | workpath = tmp_path / "build"
57 | distpath = tmp_path / "dist"
58 | app = tmp_path / (app_name + ".py")
59 | app.write_text(
60 | """
61 | import os
62 | import kivymd # NOQA
63 | __import__("kivymd.uix.label")
64 | __import__("kivymd.uix.button")
65 | __import__("kivymd.uix.list")
66 | __import__("kivymd.uix.navigationdrawer")
67 |
68 | print(os.listdir(os.path.dirname(kivymd.uix.__path__[0])))
69 | """
70 | )
71 | pyi_main.run(
72 | [
73 | "--workpath",
74 | str(workpath),
75 | "--distpath",
76 | str(distpath),
77 | "--specpath",
78 | str(tmp_path),
79 | str(app),
80 | ]
81 | )
82 | subprocess.run([str(distpath / app_name / app_name)], check=True)
83 |
--------------------------------------------------------------------------------
/kivymd/app.py:
--------------------------------------------------------------------------------
1 | """
2 | Themes/Material App
3 | ===================
4 |
5 | This module contains :class:`MDApp` class that is inherited from
6 | :class:`~kivy.app.App`. :class:`MDApp` has some properties needed for ``KivyMD``
7 | library (like :attr:`~MDApp.theme_cls`).
8 |
9 | You can turn on the monitor displaying the current ``FPS`` value in your application:
10 |
11 | .. code-block:: python
12 |
13 | KV = '''
14 | Screen:
15 |
16 | MDLabel:
17 | text: "Hello, World!"
18 | halign: "center"
19 | '''
20 |
21 | from kivy.lang import Builder
22 |
23 | from kivymd.app import MDApp
24 |
25 |
26 | class MainApp(MDApp):
27 | def build(self):
28 | return Builder.load_string(KV)
29 |
30 | def on_start(self):
31 | self.fps_monitor_start()
32 |
33 |
34 | MainApp().run()
35 |
36 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/fps-monitor.png
37 | :width: 350 px
38 | :align: center
39 |
40 | """
41 |
42 | __all__ = ("MDApp",)
43 |
44 | from kivy.app import App
45 | from kivy.properties import ObjectProperty
46 |
47 | from kivymd.theming import ThemeManager
48 |
49 |
50 | class FpsMonitoring:
51 | """Adds a monitor to display the current FPS in the toolbar."""
52 |
53 | def fps_monitor_start(self):
54 | from kivy.core.window import Window
55 |
56 | from kivymd.utils.fpsmonitor import FpsMonitor
57 |
58 | monitor = FpsMonitor()
59 | monitor.start()
60 | Window.add_widget(monitor)
61 |
62 |
63 | class MDApp(App, FpsMonitoring):
64 | theme_cls = ObjectProperty()
65 | """
66 | Instance of :class:`~ThemeManager` class.
67 |
68 | .. Warning:: The :attr:`~theme_cls` attribute is already available
69 | in a class that is inherited from the :class:`~MDApp` class.
70 | The following code will result in an error!
71 |
72 | .. code-block:: python
73 |
74 | class MainApp(MDApp):
75 | theme_cls = ThemeManager()
76 | theme_cls.primary_palette = "Teal"
77 |
78 | .. Note:: Correctly do as shown below!
79 |
80 | .. code-block:: python
81 |
82 | class MainApp(MDApp):
83 | def build(self):
84 | self.theme_cls.primary_palette = "Teal"
85 |
86 | :attr:`theme_cls` is an :class:`~kivy.properties.ObjectProperty`.
87 | """
88 |
89 | def __init__(self, **kwargs):
90 | super().__init__(**kwargs)
91 | self.theme_cls = ThemeManager()
92 |
--------------------------------------------------------------------------------
/kivymd/toast/androidtoast/androidtoast.py:
--------------------------------------------------------------------------------
1 | """
2 | AndroidToast
3 | ============
4 |
5 | .. rubric:: Native implementation of toast for Android devices.
6 |
7 | .. code-block:: python
8 |
9 | # Will be automatically used native implementation of the toast
10 | # if your application is running on an Android device.
11 | # Otherwise, will be used toast implementation
12 | # from the kivymd/toast/kivytoast package.
13 |
14 | from kivy.lang import Builder
15 | from kivy.uix.screenmanager import ScreenManager
16 |
17 | from kivymd.toast import toast
18 | from kivymd.app import MDApp
19 |
20 | KV = '''
21 | MDScreen:
22 |
23 | MDFlatButton:
24 | text: "My Toast"
25 | pos_hint:{"center_x": .5, "center_y": .5}
26 | on_press: app.show_toast()
27 | '''
28 |
29 |
30 | class Test(MDApp):
31 | def build(self):
32 | return Builder.load_string(KV)
33 |
34 | def show_toast(self):
35 | toast("Hello World", True, 80, 200, 0)
36 |
37 |
38 | Test().run()
39 | """
40 | __all__ = ("toast",)
41 |
42 | from android.runnable import run_on_ui_thread
43 | from jnius import autoclass
44 |
45 | activity = autoclass("org.kivy.android.PythonActivity").mActivity
46 | Toast = autoclass("android.widget.Toast")
47 | String = autoclass("java.lang.String")
48 |
49 |
50 | @run_on_ui_thread
51 | def toast(text, length_long=False, gravity=0, y=0, x=0):
52 | """
53 | Displays a toast.
54 |
55 | :param length_long: the amount of time (in seconds) that the toast is
56 | visible on the screen.
57 | :param text: text to be displayed in the toast;
58 | :param short_duration: duration of the toast, if `True` the toast
59 | will last 2.3s but if it is `False` the toast will last 3.9s;
60 | :param gravity: refers to the toast position, if it is 80the toast will
61 | be shown below, if it is 40 the toast will be displayed above;
62 | :param y: refers to the vertical position of the toast;
63 | :param x: refers to the horizontal position of the toast;
64 |
65 | Important: if only the text value is specified and the value of
66 | the `gravity`, `y`, `x` parameters is not specified, their values will
67 | be 0 which means that the toast will be shown in the center.
68 | """
69 |
70 | duration = Toast.LENGTH_SHORT if length_long else Toast.LENGTH_LONG
71 | t = Toast.makeText(activity, String(text), duration)
72 | t.setGravity(gravity, x, y)
73 | t.show()
74 |
--------------------------------------------------------------------------------
/kivymd/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | KivyMD
3 | ======
4 |
5 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/previous.png
6 |
7 | Is a collection of Material Design compliant widgets for use with,
8 | `Kivy cross-platform graphical framework `_
9 | a framework for cross-platform, touch-enabled graphical applications.
10 | The project's goal is to approximate Google's `Material Design spec
11 | `_ as close as possible without
12 | sacrificing ease of use or application performance.
13 |
14 | This library is a fork of the `KivyMD project
15 | `_ the author of which stopped supporting
16 | this project three years ago. We found the strength and brought this project
17 | to a new level. Currently we're in **beta** status, so things are changing
18 | all the time and we cannot promise any kind of API stability.
19 | However it is safe to vendor now and make use of what's currently available.
20 |
21 | Join the project! Just fork the project, branch out and submit a pull request
22 | when your patch is ready. If any changes are necessary, we'll guide you
23 | through the steps that need to be done via PR comments or access to your for
24 | may be requested to outright submit them. If you wish to become a project
25 | developer (permission to create branches on the project without forking for
26 | easier collaboration), have at least one PR approved and ask for it.
27 | If you contribute regularly to the project the role may be offered to you
28 | without asking too.
29 | """
30 |
31 | import os
32 |
33 | import kivy
34 | from kivy.logger import Logger
35 |
36 | __version__ = "0.104.2.dev0"
37 | """KivyMD version."""
38 |
39 | release = False
40 | kivy.require("2.0.0")
41 |
42 | try:
43 | from kivymd._version import __date__, __hash__, __short_hash__
44 | except ImportError:
45 | __hash__ = __short_hash__ = __date__ = ""
46 |
47 | path = os.path.dirname(__file__)
48 | """Path to KivyMD package directory."""
49 |
50 | fonts_path = os.path.join(path, f"fonts{os.sep}")
51 | """Path to fonts directory."""
52 |
53 | images_path = os.path.join(path, f"images{os.sep}")
54 | """Path to images directory."""
55 |
56 | _log_message = (
57 | "KivyMD:"
58 | + (" Release" if release else "")
59 | + f" {__version__}"
60 | + (f", git-{__short_hash__}" if __short_hash__ else "")
61 | + (f", {__date__}" if __date__ else "")
62 | + f' (installed at "{__file__}")'
63 | )
64 | Logger.info(_log_message)
65 |
66 | import kivymd.factory_registers # NOQA
67 | import kivymd.font_definitions # NOQA
68 | from kivymd.tools.packaging.pyinstaller import hooks_path # NOQA
69 |
--------------------------------------------------------------------------------
/kivymd/tools/release/git_commands.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2019-2020 Artem Bulgakov
2 | #
3 | # This file is distributed under the terms of the same license,
4 | # as the Kivy framework.
5 |
6 | import subprocess
7 |
8 |
9 | def command(cmd: list, capture_output: bool = False) -> str:
10 | """Run system command."""
11 | print(f"Command: {subprocess.list2cmdline(cmd)}")
12 | if capture_output:
13 | out = subprocess.check_output(cmd)
14 | out = out.decode("utf-8")
15 | print(out.strip())
16 | return out
17 | else:
18 | subprocess.check_call(cmd)
19 | return ""
20 |
21 |
22 | def get_previous_version() -> str:
23 | """Returns latest tag in git."""
24 | command(["git", "checkout", "master"])
25 | old_version = command(
26 | ["git", "describe", "--abbrev=0", "--tags"], capture_output=True
27 | )
28 | old_version = old_version[:-1] # Remove \n
29 | return old_version
30 |
31 |
32 | def git_clean(ask: bool = True):
33 | """Clean git repository from untracked and changed files."""
34 | # Check what files will be removed
35 | files_to_clean = command(
36 | ["git", "clean", "-dx", "--force", "--dry-run"], capture_output=True
37 | ).strip()
38 | # Ask before removing
39 | if ask and files_to_clean:
40 | while True:
41 | ans = input("Do you want to remove these files? (yes/no)").lower()
42 | if ans == "y" or ans == "yes":
43 | break
44 | elif ans == "n" or ans == "no":
45 | print("git clean is required. Exit")
46 | exit(0)
47 |
48 | # Remove all untracked files
49 | command(["git", "clean", "-dx", "--force"])
50 | command(["git", "reset", "--hard"])
51 |
52 |
53 | def git_commit(message: str, allow_error: bool = False, add_files: list = None):
54 | """Make commit."""
55 | add_files = add_files if add_files else ["-A"]
56 | command(["git", "add", *add_files])
57 | try:
58 | command(["git", "commit", "--all", "-m", message])
59 | except subprocess.CalledProcessError as e:
60 | if not allow_error:
61 | raise e
62 |
63 |
64 | def git_tag(name: str):
65 | """Create tag."""
66 | command(["git", "tag", name])
67 |
68 |
69 | def git_push(branches_to_push: list, ask: bool = True, push: bool = False):
70 | """Push all changes."""
71 | if ask:
72 | push = input("Do you want to push changes? (y)") in (
73 | "",
74 | "y",
75 | "yes",
76 | )
77 |
78 | cmd = ["git", "push", "--tags", "origin", "master", *branches_to_push]
79 | if push:
80 | command(cmd)
81 | else:
82 | print(
83 | f"Changes are not pushed. Command for manual pushing: {subprocess.list2cmdline(cmd)}"
84 | )
85 |
86 |
87 | if __name__ == "__main__":
88 | git_clean(ask=True)
89 |
--------------------------------------------------------------------------------
/kivymd/uix/__init__.py:
--------------------------------------------------------------------------------
1 | from kivy.properties import BooleanProperty
2 | from kivy.uix.floatlayout import FloatLayout
3 | from kivy.uix.label import Label
4 | from kivy.uix.screenmanager import Screen
5 |
6 | from kivymd.uix.behaviors import SpecificBackgroundColorBehavior
7 |
8 |
9 | class MDAdaptiveWidget(SpecificBackgroundColorBehavior):
10 | adaptive_height = BooleanProperty(False)
11 | """
12 | If `True`, the following properties will be applied to the widget:
13 |
14 | .. code-block:: kv
15 |
16 | size_hint_y: None
17 | height: self.minimum_height
18 |
19 | :attr:`adaptive_height` is an :class:`~kivy.properties.BooleanProperty`
20 | and defaults to `False`.
21 | """
22 |
23 | adaptive_width = BooleanProperty(False)
24 | """
25 | If `True`, the following properties will be applied to the widget:
26 |
27 | .. code-block:: kv
28 |
29 | size_hint_x: None
30 | width: self.minimum_width
31 |
32 | :attr:`adaptive_width` is an :class:`~kivy.properties.BooleanProperty`
33 | and defaults to `False`.
34 | """
35 |
36 | adaptive_size = BooleanProperty(False)
37 | """
38 | If `True`, the following properties will be applied to the widget:
39 |
40 | .. code-block:: kv
41 |
42 | size_hint: None, None
43 | size: self.minimum_size
44 |
45 | :attr:`adaptive_size` is an :class:`~kivy.properties.BooleanProperty`
46 | and defaults to `False`.
47 | """
48 |
49 | def on_adaptive_height(self, instance, value):
50 | self.size_hint_y = None
51 | if issubclass(self.__class__, Label):
52 | self.bind(
53 | texture_size=lambda *x: self.setter("height")(
54 | self, self.texture_size[1]
55 | )
56 | )
57 | else:
58 | if not isinstance(self, (FloatLayout, Screen)):
59 | self.bind(minimum_height=self.setter("height"))
60 |
61 | def on_adaptive_width(self, instance, value):
62 | self.size_hint_x = None
63 | if issubclass(self.__class__, Label):
64 | self.bind(
65 | texture_size=lambda *x: self.setter("width")(
66 | self, self.texture_size[0]
67 | )
68 | )
69 | else:
70 | if not isinstance(self, (FloatLayout, Screen)):
71 | self.bind(minimum_width=self.setter("width"))
72 |
73 | def on_adaptive_size(self, instance, value):
74 | self.size_hint = (None, None)
75 | if issubclass(self.__class__, Label):
76 | self.text_size = (None, None)
77 | self.bind(
78 | texture_size=lambda *x: self.setter("size")(
79 | self, self.texture_size
80 | )
81 | )
82 | else:
83 | if not isinstance(self, (FloatLayout, Screen)):
84 | self.bind(minimum_size=self.setter("size"))
85 |
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/touch_behavior.py:
--------------------------------------------------------------------------------
1 | """
2 | Behaviors/Touch
3 | ===============
4 |
5 | .. rubric:: Provides easy access to events.
6 |
7 | The following events are available:
8 |
9 | - on_long_touch
10 | - on_double_tap
11 | - on_triple_tap
12 |
13 | Usage
14 | -----
15 |
16 | .. code-block:: python
17 |
18 | from kivy.lang import Builder
19 |
20 | from kivymd.app import MDApp
21 | from kivymd.uix.behaviors import TouchBehavior
22 | from kivymd.uix.button import MDRaisedButton
23 |
24 | KV = '''
25 | Screen:
26 |
27 | MyButton:
28 | text: "PRESS ME"
29 | pos_hint: {"center_x": .5, "center_y": .5}
30 | '''
31 |
32 |
33 | class MyButton(MDRaisedButton, TouchBehavior):
34 | def on_long_touch(self, *args):
35 | print(" event")
36 |
37 | def on_double_tap(self, *args):
38 | print(" event")
39 |
40 | def on_triple_tap(self, *args):
41 | print(" event")
42 |
43 |
44 | class MainApp(MDApp):
45 | def build(self):
46 | return Builder.load_string(KV)
47 |
48 |
49 | MainApp().run()
50 | """
51 |
52 | __all__ = ("TouchBehavior",)
53 |
54 | from functools import partial
55 |
56 | from kivy.clock import Clock
57 | from kivy.properties import NumericProperty
58 |
59 |
60 | class TouchBehavior:
61 | duration_long_touch = NumericProperty(0.4)
62 | """
63 | Time for a long touch.
64 |
65 | :attr:`duration_long_touch` is an :class:`~kivy.properties.NumericProperty`
66 | and defaults to `0.4`.
67 | """
68 |
69 | def __init__(self, **kwargs):
70 | super().__init__(**kwargs)
71 | self.bind(
72 | on_touch_down=self.create_clock, on_touch_up=self.delete_clock
73 | )
74 |
75 | def create_clock(self, widget, touch, *args):
76 | if self.collide_point(touch.x, touch.y):
77 | callback = partial(self.on_long_touch, touch)
78 | Clock.schedule_once(callback, self.duration_long_touch)
79 | touch.ud["event"] = callback
80 |
81 | def delete_clock(self, widget, touch, *args):
82 | if self.collide_point(touch.x, touch.y):
83 | try:
84 | Clock.unschedule(touch.ud["event"])
85 | except KeyError:
86 | pass
87 |
88 | if touch.is_double_tap:
89 | self.on_double_tap(touch, *args)
90 | if touch.is_triple_tap:
91 | self.on_triple_tap(touch, *args)
92 |
93 | def on_long_touch(self, touch, *args):
94 | """Called when the widget is pressed for a long time."""
95 |
96 | def on_double_tap(self, touch, *args):
97 | """Called by double clicking on the widget."""
98 |
99 | def on_triple_tap(self, touch, *args):
100 | """Called by triple clicking on the widget."""
101 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Reminder-App
2 | An android app for creating reminders made using the kivy and kivyMD framework for python.
3 |
4 | 
5 | 
6 | 
7 |
8 | ## Features
9 | This reminder app organizes your reminders into lists. You can create multiple lists that contains reminders inside them. Each reminder can be set to notify you through notifications on a particular day or date at a specific time.
10 | * Create and delete named lists that can store reminders inside them.
11 | * Create reminderes that have a title and description. A reminder can be set to not notify you, to notify you on particular days(such as Monday, Tuesday, Wednesday etc.) or upto 5 specific dates. You can also set a time at which you want the reminder to ring.
12 | * Reminders appear as notifications. Clicking on the notification takes you directly to the reminder.
13 | * Snooze reminders for a certain amount of time directly from the notification
14 | * Mark reminders as complete direclty from the notification.
15 | * Internal themeing support.
16 |
17 |
18 | ## History
19 |
20 | > This App currently stands as an abandoned project
21 |
22 |
23 | This project was initially started for commercial purposes and to prove a point that commercial scale apps could be made using python and still be performant. It was originally named as Remindy, but unfortunately other apps already exist under that name so as to prevent copyright violations, the name of this repository has been changed.
24 |
25 | The app went through numerous iterations before it reached the stage it is at now and still needs much more to become a full fledged reminder app. Unfortunetly none of those updates or changes will be coming anytime soon.
26 |
27 | ### Why was it abandoned?
28 |
29 | The app's fundamental concept was based on sorting reminders into lists and displaying them as if they are a stack of cards. The App's entire UI was based on this fundamental concept. This presented a really interesting UX interaction with the user but deliverd a lack luster UI experience. Unfortunately I realized this too far into the development of the project that I was forced to scrap the entire idea and hence why the project is now considered as abandoned.
30 |
31 |
32 | ### Did the fact that it was coded in Python affect my Idea to abandon it?
33 |
34 | Not at all. In fact it was python that encouraged me to continue the project even after I knew that the UI was not good. The Kivy library really allows for rapid development of user interfaces.
35 | The performance impact that python had on the app where signifcant and the app incorporates numerous optimization techniques in order to reduce the performance impacts. You are welcome to use the logic I implemented in your own apps to reduce performance issues.
36 |
37 | ## Will the project ever continue again?
38 |
39 | Probably not. The concept of the reminder app may live on in another form but as of now I am focusing on learning more langaiges rather than sticking with just python.
40 |
--------------------------------------------------------------------------------
/other/gesture pad.py:
--------------------------------------------------------------------------------
1 | from kivy.app import App
2 |
3 | from kivy.uix.floatlayout import FloatLayout
4 | from kivy.graphics import Color, Ellipse, Line
5 | from kivy.gesture import Gesture, GestureDatabase
6 |
7 | from my_gestures import cross, circle, check, square
8 |
9 |
10 |
11 | def simplegesture(name, point_list):
12 | """
13 | A simple helper function
14 | """
15 | g = Gesture()
16 | g.add_stroke(point_list)
17 | g.normalize()
18 | g.name = name
19 | return g
20 |
21 |
22 | class GestureBoard(FloatLayout):
23 | """
24 | Our application main widget, derived from touchtracer example, use data
25 | constructed from touches to match symboles loaded from my_gestures.
26 | """
27 | def __init__(self, *args, **kwargs):
28 | super(GestureBoard, self).__init__()
29 | self.gdb = GestureDatabase()
30 |
31 | # add pre-recorded gestures to database
32 | self.gdb.add_gesture(cross)
33 | self.gdb.add_gesture(check)
34 | self.gdb.add_gesture(circle)
35 | self.gdb.add_gesture(square)
36 |
37 | def on_touch_down(self, touch):
38 | # start collecting points in touch.ud
39 | # create a line to display the points
40 | userdata = touch.ud
41 | with self.canvas:
42 | Color(1, 1, 0)
43 | d = 30.
44 | Ellipse(pos=(touch.x - d / 2, touch.y - d / 2), size=(d, d))
45 | userdata['line'] = Line(points=(touch.x, touch.y))
46 | return True
47 |
48 | def on_touch_move(self, touch):
49 | # store points of the touch movement
50 | try:
51 | touch.ud['line'].points += [touch.x, touch.y]
52 | return True
53 | except (KeyError) as e:
54 | pass
55 |
56 | def on_touch_up(self, touch):
57 | # touch is over, display informations, and check if it matches some
58 | # known gesture.
59 | g = simplegesture('', list(zip(touch.ud['line'].points[::2],
60 | touch.ud['line'].points[1::2])))
61 | # gestures to my_gestures.py
62 | print("gesture representation:", self.gdb.gesture_to_str(g))
63 |
64 | # print match scores between all known gestures
65 | print("cross:", g.get_score(cross))
66 | print("check:", g.get_score(check))
67 | print("circle:", g.get_score(circle))
68 | print("square:", g.get_score(square))
69 |
70 | # use database to find the more alike gesture, if any
71 | g2 = self.gdb.find(g, minscore=0.60)
72 |
73 | print(g2)
74 | if g2:
75 | if g2[1] == circle:
76 | print("circle")
77 | if g2[1] == square:
78 | print("square")
79 | if g2[1] == check:
80 | print("check")
81 | if g2[1] == cross:
82 | print("cross")
83 |
84 | # erase the lines on the screen, this is a bit quick&dirty, since we
85 | # can have another touch event on the way...
86 | self.canvas.clear()
87 |
88 |
89 | class DemoGesture(App):
90 | def build(self):
91 | return GestureBoard()
92 |
93 |
94 | if __name__ == '__main__':
95 | DemoGesture().run()
96 |
--------------------------------------------------------------------------------
/kivymd/theming_dynamic_text.py:
--------------------------------------------------------------------------------
1 | """
2 | Theming Dynamic Text
3 | ====================
4 |
5 | Two implementations. The first is based on color brightness obtained from-
6 | https://www.w3.org/TR/AERT#color-contrast
7 | The second is based on relative luminance calculation for sRGB obtained from-
8 | https://www.w3.org/TR/2008/REC-WCAG20-20081211/#relativeluminancedef
9 | and contrast ratio calculation obtained from-
10 | https://www.w3.org/TR/2008/REC-WCAG20-20081211/#contrast-ratiodef
11 |
12 | Preliminary testing suggests color brightness more closely matches the
13 | `Material Design spec` suggested text colors, but the alternative implementation
14 | is both newer and the current 'correct' recommendation, so is included here
15 | as an option.
16 | """
17 |
18 |
19 | def _color_brightness(color):
20 | # Implementation of color brightness method
21 | brightness = color[0] * 299 + color[1] * 587 + color[2] * 114
22 | brightness = brightness
23 | return brightness
24 |
25 |
26 | def _black_or_white_by_color_brightness(color):
27 | if _color_brightness(color) >= 500:
28 | return "black"
29 | else:
30 | return "white"
31 |
32 |
33 | def _normalized_channel(color):
34 | # Implementation of contrast ratio and relative luminance method
35 | if color <= 0.03928:
36 | return color / 12.92
37 | else:
38 | return ((color + 0.055) / 1.055) ** 2.4
39 |
40 |
41 | def _luminance(color):
42 | rg = _normalized_channel(color[0])
43 | gg = _normalized_channel(color[1])
44 | bg = _normalized_channel(color[2])
45 | return 0.2126 * rg + 0.7152 * gg + 0.0722 * bg
46 |
47 |
48 | def _black_or_white_by_contrast_ratio(color):
49 | l_color = _luminance(color)
50 | l_black = 0.0
51 | l_white = 1.0
52 | b_contrast = (l_color + 0.05) / (l_black + 0.05)
53 | w_contrast = (l_white + 0.05) / (l_color + 0.05)
54 | return "white" if w_contrast >= b_contrast else "black"
55 |
56 |
57 | def get_contrast_text_color(color, use_color_brightness=True):
58 | if use_color_brightness:
59 | contrast_color = _black_or_white_by_color_brightness(color)
60 | else:
61 | contrast_color = _black_or_white_by_contrast_ratio(color)
62 | if contrast_color == "white":
63 | return 1, 1, 1, 1
64 | else:
65 | return 0, 0, 0, 1
66 |
67 |
68 | if __name__ == "__main__":
69 | from kivy.utils import get_color_from_hex
70 |
71 | from kivymd.color_definitions import colors, text_colors
72 |
73 | for c in colors.items():
74 | if c[0] in ["Light", "Dark"]:
75 | continue
76 | color = c[0]
77 | print(f"For the {color} color palette:")
78 | for name, hex_color in c[1].items():
79 | if hex_color:
80 | col = get_color_from_hex(hex_color)
81 | col_bri = get_contrast_text_color(col)
82 | con_rat = get_contrast_text_color(
83 | col, use_color_brightness=False
84 | )
85 | text_color = text_colors[c[0]][name]
86 | print(
87 | f" The {name} hue gives {col_bri} using color "
88 | f"brightness, {con_rat} using contrast ratio, and "
89 | f"{text_color} from the MD spec"
90 | )
91 |
--------------------------------------------------------------------------------
/other/gesture_box.py:
--------------------------------------------------------------------------------
1 | from kivy.gesture import GestureDatabase
2 | from kivy.uix.boxlayout import BoxLayout
3 | from kivy.gesture import Gesture
4 |
5 | gesture_strings = {'swipe_down':'eNp1ln1ME2cYwA9FsBtO2Fwk6Dbix8SJiEvmjGTjothWs4QKQ5hKoB8H11Hb0l5pmSs9R1ZJdlOjpwMkyh/qnMYAf2DEKK0YlbEt8ZMwIYFpsjG/cNlm2HTr2pe73r173/f+edvf73nued7nLm+OTzzgeJECl5BSY62rz6lm3JzHxYhCsk76tV9culP0i1nCDK/VwrGijs6WMpJYxlrNclHyWdMUmS2lVzhdDovHHFOaVeK2wmyvkOzmXI4axi2WiywlzJLuXgygUiPJ6bDauVhQVjQqRYoyxKASlOATdflNkWrjH4fDQkJ99M+9367k/WId8pjYtKkYdo4uv668f+OyHop9VZd/d32wtMlZRPQ/fbvynOWQn+jHHi4NHuz4iOhHF7fUbBjpI/qRfxJ/vfpSFdEPLyne0eVrJfohruXHH56eIPrBwbd8p4bvEv3t+RlpqdPbiP6m/2THo/E7sPdrNeOHMoC/fqlVX5S6l+i/u3i/t+rmCNEPJN/ZPPCMnH854NBev3eL6Pu65hzmjm4j+nNfre3eSk8Sfbc1rWHX2XSiP/60qmTP6v/lf/6Fdt/5x3TMtz5Of9f2ZifJhxpsocZpz8JEf2yiILeglyXVD3XVVrSdHNCTnk+oZ9U39vG5AuztD2aV+jqAD3fnnQ4ur4V8qCRlsleXA/zl945fCKxfCXv3Kxdtzt3A93ddFc78Cfcfqn8+/YXRCeC/F22e220W2POuBR9+fQL4a66B89vbviT6G9nDizTcIOwbf163cLQsHPO3Xl/e3NyfBftdW8y/z9WA+Q1q+zLmHWz0mBghxW12MYxdOSd0tC8XnD7RY6gZ/AhGjx1fpsx8CkuVmR7DUuPM+0RiO9sxrAzD0lHGD2EY5n68E8P0GIbpL9CJsoYxDMPU8F/DsDcisQtin9Jo3I5CNO4TAxpXXxlbE8CcKYn5KpXZy8zrRFldJprraUfjOAMa5+bROBcmt/YJmlubi8Y5A/H9xpmDV3Lld82uzC/ObBUoqzmCso9HUWYNozWsFMrYTLTnagyrwsyewbyTFsw7ZFG9B2MSMyt7izOTMhdvWGJGSsntlFhFWGHtEitXnpt3r8S2grhpENuiuh8vsTIeZaW00ovMSkDL/wLmlJky0zgrVtWVWRGNxm1SzUVmhny0RiFYZ0Dsg4ASVymxjaDRRIjpVXuTmY5CmZZSepZZAY+ydaDuc5hhctdSaC90BO2ZVs1PZu+DdSbE8kDu3xBbg9nHarAmQewdkPsXYAaJvQ3YJMRWADYBsWWqujLLUtWQ2SKwvgyx+WDNhNjUUfyamoEnHokcDYqMx2QUNJzDxriMdjMT/TrtaYldrUKi3bg9+mVNiR5Tzn9685bk'
6 | }
7 |
8 | #This database can compare gestures the user makes to its stored gestures
9 | #and tell us if the user input matches any of them.
10 | gestures = GestureDatabase()
11 | for name, gesture_string in gesture_strings.items():
12 | gesture = gestures.str_to_gesture(gesture_string)
13 | gesture.name = name
14 | gestures.add_gesture(gesture)
15 |
16 | class GestureBox(BoxLayout):
17 |
18 | def __init__(self, **kwargs):
19 | self.register_event_type('on_swipe_down')
20 | super(GestureBox, self).__init__(**kwargs)
21 |
22 | def on_swipe_down(self):
23 | pass
24 |
25 |
26 | #To recognize a gesture, you’ll need to start recording each individual event in the
27 | #touch_down handler, add the data points for each call to touch_move , and then do the
28 | #gesture calculations when all data points have been received in the touch_up handler.
29 |
30 | def on_touch_down(self, touch):
31 | #create an user defined variable and add the touch coordinates
32 | touch.ud['gesture_path'] = [(touch.x, touch.y)]
33 | super(GestureBox, self).on_touch_down(touch)
34 |
35 | def on_touch_move(self, touch):
36 | touch.ud['gesture_path'].append((touch.x, touch.y))
37 | super(GestureBox, self).on_touch_move(touch)
38 |
39 | def on_touch_up(self, touch):
40 | if 'gesture_path' in touch.ud:
41 | #create a gesture object
42 | gesture = Gesture()
43 | #add the movement coordinates
44 | gesture.add_stroke(touch.ud['gesture_path'])
45 | #normalize so thwu willtolerate size variations
46 | gesture.normalize()
47 | #minscore to be attained for a match to be true
48 | match = gestures.find(gesture, minscore=0.4)
49 | if match:
50 | print("{} happened".format(match[1].name))
51 | self.dispatch('on_{}'.format(match[1].name))
52 | super(GestureBox, self).on_touch_up(touch)
53 |
--------------------------------------------------------------------------------
/kivymd/tools/release/argument_parser.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2019-2020 Artem Bulgakov
2 | #
3 | # This file is distributed under the terms of the same license,
4 | # as the Kivy framework.
5 |
6 | import argparse
7 | import sys
8 |
9 |
10 | class ArgumentParserWithHelp(argparse.ArgumentParser):
11 | def parse_args(self, args=None, namespace=None):
12 | # Add help when no arguments specified
13 | if not args and not len(sys.argv) > 1:
14 | self.print_help()
15 | self.exit(1)
16 | return super().parse_args(args, namespace)
17 |
18 | def error(self, message):
19 | # Add full help on error
20 | self.print_help()
21 | self.exit(2, f"\nError: {message}\n")
22 |
23 | def format_help(self):
24 | # Add subparsers usage and help to full help text
25 | formatter = self._get_formatter()
26 |
27 | # Get subparsers
28 | subparsers_actions = [
29 | action
30 | for action in self._actions
31 | if isinstance(action, argparse._SubParsersAction)
32 | ]
33 |
34 | # Description
35 | formatter.add_text(self.description)
36 |
37 | # Usage
38 | formatter.add_usage(
39 | self.usage,
40 | self._actions,
41 | self._mutually_exclusive_groups,
42 | prefix="Usage:\n",
43 | )
44 |
45 | # Subparsers usage
46 | for subparsers_action in subparsers_actions:
47 | for choice, subparser in subparsers_action.choices.items():
48 | formatter.add_usage(
49 | subparser.usage,
50 | subparser._actions,
51 | subparser._mutually_exclusive_groups,
52 | prefix="",
53 | )
54 |
55 | # Positionals, optionals and user-defined groups
56 | for action_group in self._action_groups:
57 | if not any(
58 | [
59 | action in subparsers_actions
60 | for action in action_group._group_actions
61 | ]
62 | ):
63 | formatter.start_section(action_group.title)
64 | formatter.add_text(action_group.description)
65 | formatter.add_arguments(action_group._group_actions)
66 | formatter.end_section()
67 | else:
68 | # Process subparsers differently
69 | # Just show list of choices
70 | formatter.start_section(action_group.title)
71 | # formatter.add_text(action_group.description)
72 | for action in action_group._group_actions:
73 | for choice in action.choices:
74 | formatter.add_text(choice)
75 | formatter.end_section()
76 |
77 | # Subparsers help
78 | for subparsers_action in subparsers_actions:
79 | for choice, subparser in subparsers_action.choices.items():
80 | formatter.start_section(choice)
81 | for action_group in subparser._action_groups:
82 | formatter.start_section(action_group.title)
83 | formatter.add_text(action_group.description)
84 | formatter.add_arguments(action_group._group_actions)
85 | formatter.end_section()
86 | formatter.end_section()
87 |
88 | # Epilog
89 | formatter.add_text(self.epilog)
90 |
91 | # Determine help from format above
92 | return formatter.format_help()
93 |
--------------------------------------------------------------------------------
/kivymd/utils/cropimage.py:
--------------------------------------------------------------------------------
1 | """
2 | Crop Image
3 | ==========
4 | """
5 |
6 |
7 | def crop_image(
8 | cutting_size,
9 | path_to_image,
10 | path_to_save_crop_image,
11 | corner=0,
12 | blur=0,
13 | corner_mode="all",
14 | ):
15 | """Call functions of cropping/blurring/rounding image.
16 |
17 | cutting_size: size to which the image will be cropped;
18 | path_to_image: path to origin image;
19 | path_to_save_crop_image: path to new image;
20 | corner: value of rounding corners;
21 | blur: blur value;
22 | corner_mode: 'all'/'top'/'bottom' - indicates which corners to round out;
23 |
24 | """
25 |
26 | im = _crop_image(cutting_size, path_to_image, path_to_save_crop_image)
27 | if corner:
28 | im = add_corners(im, corner, corner_mode)
29 | if blur:
30 | im = add_blur(im, blur)
31 | try:
32 | im.save(path_to_save_crop_image)
33 | except IOError:
34 | im.save(path_to_save_crop_image, "JPEG")
35 |
36 |
37 | def add_blur(im, mode):
38 | from PIL import ImageFilter
39 |
40 | im = im.filter(ImageFilter.GaussianBlur(mode))
41 |
42 | return im
43 |
44 |
45 | def _crop_image(cutting_size, path_to_image, path_to_save_crop_image):
46 | from PIL import Image, ImageOps
47 |
48 | image = Image.open(path_to_image)
49 | image = ImageOps.fit(image, cutting_size)
50 | image.save(path_to_save_crop_image)
51 |
52 | return image
53 |
54 |
55 | def add_corners(im, corner, corner_mode):
56 | def add_top_corners():
57 | alpha.paste(circle.crop((0, 0, corner, corner)), (0, 0))
58 | alpha.paste(
59 | circle.crop((corner, 0, corner * 2, corner)), (w - corner, 0)
60 | )
61 |
62 | def add_bottom_corners():
63 | alpha.paste(
64 | circle.crop((0, corner, corner, corner * 2)), (0, h - corner)
65 | )
66 | alpha.paste(
67 | circle.crop((corner, corner, corner * 2, corner * 2)),
68 | (w - corner, h - corner),
69 | )
70 |
71 | from PIL import Image, ImageDraw
72 |
73 | circle = Image.new("L", (corner * 2, corner * 2), 0)
74 | draw = ImageDraw.Draw(circle)
75 | draw.ellipse((0, 0, corner * 2, corner * 2), fill=255)
76 | alpha = Image.new("L", im.size, 255)
77 | w, h = im.size
78 |
79 | if corner_mode == "all":
80 | add_top_corners()
81 | add_bottom_corners()
82 | elif corner_mode == "top":
83 | add_top_corners()
84 | if corner_mode == "bottom":
85 | add_bottom_corners()
86 | im.putalpha(alpha)
87 |
88 | return im
89 |
90 |
91 | def prepare_mask(size, antialias=2):
92 | from PIL import Image, ImageDraw
93 |
94 | mask = Image.new("L", (size[0] * antialias, size[1] * antialias), 0)
95 | ImageDraw.Draw(mask).ellipse((0, 0) + mask.size, fill=255)
96 | return mask.resize(size, Image.ANTIALIAS)
97 |
98 |
99 | def _crop_round_image(im, s):
100 | from PIL import Image
101 |
102 | w, h = im.size
103 | k = w // s[0] - h // s[1]
104 | if k > 0:
105 | im = im.crop(((w - h) // 2, 0, (w + h) // 2, h))
106 | elif k < 0:
107 | im = im.crop((0, (h - w) // 2, w, (h + w) // 2))
108 | return im.resize(s, Image.ANTIALIAS)
109 |
110 |
111 | def crop_round_image(cutting_size, path_to_image, path_to_new_image):
112 | from PIL import Image
113 |
114 | im = Image.open(path_to_image)
115 | im = _crop_round_image(im, cutting_size)
116 | im.putalpha(prepare_mask(cutting_size, 4))
117 | im.save(path_to_new_image)
118 |
--------------------------------------------------------------------------------
/theming.py:
--------------------------------------------------------------------------------
1 | from kivy.properties import AliasProperty, ColorProperty
2 |
3 | class ThemeManager():
4 |
5 | background_color =ColorProperty()
6 |
7 | primary_color = ColorProperty()
8 |
9 | secondary_color = ColorProperty()
10 |
11 | tertiary_color = ColorProperty()
12 |
13 | accent_color = ColorProperty()
14 |
15 | text_color = ColorProperty()
16 |
17 | secondary_text_color = ColorProperty()
18 |
19 | def __init__(self, **kwargs):
20 | super().__init__(**kwargs)
21 | self.background_color = [44/255,62/255,80/255, 1]
22 | self.primary_color = [50/255,49/255,61/255,1]
23 | self.secondary_color = [70/255,69/255,81/255,1]
24 | self.tertiary_color = [90/255,89/255,101/255,1]
25 | self.accent_color = [218/255,68/255,83/255, 1]
26 | self.text_color = [1,1,1,1]
27 | self.secondary_text_color = [1,1,1,.5]
28 |
29 |
30 |
31 | def set_theme(self, name):
32 | if name == 'Slate':
33 | self.background_color = [44/255,62/255,80/255, 1]
34 | self.primary_color = [50/255,49/255,61/255,1]
35 | self.secondary_color = [70/255,69/255,81/255,1]
36 | self.tertiary_color = [90/255,89/255,101/255,1]
37 | self.accent_color = [218/255,68/255,83/255, 1]
38 | self.text_color = [1,1,1,1]
39 | self.secondary_text_color = [0,0,0,.5]
40 |
41 | elif name == 'DeadWood':
42 | self.background_color = [34/255,40/255,49/255, 1]
43 | self.primary_color = [48/255,71/255,94/255,1]
44 | self.secondary_color = [68/255,91/255,114/255,1]
45 | self.tertiary_color = [88/255,121/255,134/255,1]
46 | self.accent_color = [242/255,163/255,101/255,1]
47 | self.text_color = [1,1,1,1]
48 | self.secondary_text_color = [1,1,1,.5]
49 |
50 | elif name == 'SnowWhite':
51 | self.background_color = [34/255,40/255,49/255, 1]
52 | self.primary_color = [0.9,0.9,0.9,1]
53 | self.secondary_color = [0.7,0.7,0.7,1]
54 | self.tertiary_color = [0.5,0.5,0.5,1]
55 | self.accent_color = [17/255,153/255,158/255,1]
56 | self.text_color = [0,0,0.1,1]
57 | self.secondary_text_color = [0,0,0.1,.5]
58 |
59 | elif name == 'Candy':
60 | self.background_color = [255/255,182/255,185/255,1]
61 | self.primary_color = [250/255,227/255,217/255,1]
62 | self.secondary_color = [230/255,207/255,197/255,1]
63 | self.tertiary_color = [210/255,197/255,187/255,1]
64 | self.accent_color = [97/255,192/255,191/255,1]
65 | self.text_color = [0,0,0.1,1]
66 | self.secondary_text_color = [0,0,0.1,.5]
67 |
68 | elif name == 'PureWhite':
69 | self.background_color = [0.9,0.9,0.9,1]
70 | self.primary_color = [0.9,0.9,0.9,1]
71 | self.secondary_color = [0.7,0.7,0.7,1]
72 | self.tertiary_color = [0.5,0.5,0.5,1]
73 | self.accent_color = [218/255,68/255,83/255, 1]
74 | self.text_color = [0,0,0.1,1]
75 | self.secondary_text_color = [0,0,0.1,.5]
76 |
77 | elif name == 'PureBlack':
78 | self.background_color = [0,0,0,1]
79 | self.primary_color = [0.1,0.1,0.1,1]
80 | self.secondary_color = [0.2,0.2,0.2,1]
81 | self.tertiary_color = [0.3,0.3,0.3,1]
82 | self.accent_color = [218/255,68/255,83/255, 1]
83 | self.text_color = [1,1,1,1]
84 | self.secondary_text_color = [1,1,1,.5]
85 | def rgb2hex(self,list):
86 | return '#%02x%02x%02x' % (int(list[0]*255),int(list[1]*255),int(list[2]*255))
87 |
--------------------------------------------------------------------------------
/kivymd/uix/dropdownitem.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Dropdown Item
3 | ========================
4 |
5 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dropdown-item.png
6 | :align: center
7 |
8 | Usage
9 | -----
10 |
11 | .. code-block:: python
12 |
13 | from kivy.lang import Builder
14 |
15 | from kivymd.app import MDApp
16 |
17 | KV = '''
18 | Screen
19 |
20 | MDDropDownItem:
21 | id: drop_item
22 | pos_hint: {'center_x': .5, 'center_y': .5}
23 | text: 'Item'
24 | on_release: self.set_item("New Item")
25 | '''
26 |
27 |
28 | class Test(MDApp):
29 | def __init__(self, **kwargs):
30 | super().__init__(**kwargs)
31 | self.screen = Builder.load_string(KV)
32 |
33 | def build(self):
34 | return self.screen
35 |
36 |
37 | Test().run()
38 |
39 | .. seealso::
40 |
41 | `Work with the class MDDropdownMenu see here `_
42 | """
43 |
44 | __all__ = ("MDDropDownItem",)
45 |
46 | from kivy.lang import Builder
47 | from kivy.properties import NumericProperty, StringProperty
48 | from kivy.uix.behaviors import ButtonBehavior
49 | from kivy.uix.widget import Widget
50 |
51 | from kivymd.theming import ThemableBehavior
52 | from kivymd.uix.behaviors import FakeRectangularElevationBehavior
53 | from kivymd.uix.boxlayout import MDBoxLayout
54 |
55 | Builder.load_string(
56 | """
57 | <_Triangle>:
58 | canvas:
59 | Color:
60 | rgba: root.theme_cls.text_color
61 | Triangle:
62 | points:
63 | [ \
64 | self.right-dp(14), self.y+dp(7), \
65 | self.right-dp(7), self.y+dp(7), \
66 | self.right-dp(7), self.y+dp(14) \
67 | ]
68 |
69 |
70 |
71 | orientation: "vertical"
72 | adaptive_size: True
73 | spacing: "5dp"
74 | padding: "5dp", "5dp", "5dp", 0
75 |
76 | MDBoxLayout:
77 | adaptive_size: True
78 | spacing: "10dp"
79 |
80 | Label:
81 | id: label_item
82 | size_hint: None, None
83 | size: self.texture_size
84 | color: root.theme_cls.text_color
85 | font_size: root.font_size
86 |
87 |
88 | _Triangle:
89 | size_hint: None, None
90 | size: "20dp", "20dp"
91 |
92 | MDSeparator:
93 | """
94 | )
95 |
96 |
97 | class _Triangle(ThemableBehavior, Widget):
98 | pass
99 |
100 |
101 | class MDDropDownItem(
102 | ThemableBehavior,
103 | FakeRectangularElevationBehavior,
104 | ButtonBehavior,
105 | MDBoxLayout,
106 | ):
107 | text = StringProperty()
108 | """
109 | Text item.
110 |
111 | :attr:`text` is a :class:`~kivy.properties.StringProperty`
112 | and defaults to `''`.
113 | """
114 |
115 | current_item = StringProperty()
116 | """
117 | Current name item.
118 |
119 | :attr:`current_item` is a :class:`~kivy.properties.StringProperty`
120 | and defaults to `''`.
121 | """
122 |
123 | font_size = NumericProperty("16sp")
124 | """
125 | Item font size.
126 |
127 | :attr:`font_size` is a :class:`~kivy.properties.NumericProperty`
128 | and defaults to `'16sp'`.
129 | """
130 |
131 | def on_text(self, instance, value):
132 | self.ids.label_item.text = value
133 |
134 | def set_item(self, name_item):
135 | """Sets new text for an item."""
136 |
137 | self.ids.label_item.text = name_item
138 | self.current_item = name_item
139 |
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/focus_behavior.py:
--------------------------------------------------------------------------------
1 | """
2 | Behaviors/Focus
3 | ===============
4 |
5 | .. rubric:: Changing the background color when the mouse is on the widget.
6 |
7 | To apply focus behavior, you must create a new class that is inherited from the
8 | widget to which you apply the behavior and from the :class:`FocusBehavior` class.
9 |
10 | Usage
11 | -----
12 |
13 | .. code-block:: python
14 |
15 | from kivy.lang import Builder
16 |
17 | from kivymd.app import MDApp
18 | from kivymd.uix.behaviors import RectangularElevationBehavior, FocusBehavior
19 | from kivymd.uix.boxlayout import MDBoxLayout
20 |
21 | KV = '''
22 | MDScreen:
23 | md_bg_color: 1, 1, 1, 1
24 |
25 | FocusWidget:
26 | size_hint: .5, .3
27 | pos_hint: {"center_x": .5, "center_y": .5}
28 | md_bg_color: app.theme_cls.bg_light
29 |
30 | MDLabel:
31 | text: "Label"
32 | theme_text_color: "Primary"
33 | pos_hint: {"center_y": .5}
34 | halign: "center"
35 | '''
36 |
37 |
38 | class FocusWidget(MDBoxLayout, RectangularElevationBehavior, FocusBehavior):
39 | pass
40 |
41 |
42 | class Test(MDApp):
43 | def build(self):
44 | self.theme_cls.theme_style = "Dark"
45 | return Builder.load_string(KV)
46 |
47 |
48 | Test().run()
49 |
50 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/focus-widget.gif
51 | :align: center
52 |
53 | Color change at focus/defocus
54 |
55 | .. code-block:: kv
56 |
57 | FocusWidget:
58 | focus_color: 1, 0, 1, 1
59 | unfocus_color: 0, 0, 1, 1
60 |
61 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/focus-defocus-color.gif
62 | :align: center
63 | """
64 |
65 | __all__ = ("FocusBehavior",)
66 |
67 | from kivy.app import App
68 | from kivy.properties import BooleanProperty, ColorProperty
69 | from kivy.uix.behaviors import ButtonBehavior
70 |
71 | from kivymd.uix.behaviors import HoverBehavior
72 |
73 |
74 | class FocusBehavior(HoverBehavior, ButtonBehavior):
75 |
76 | focus_behavior = BooleanProperty(True)
77 | """
78 | Using focus when hovering over a widget.
79 |
80 | :attr:`focus_behavior` is a :class:`~kivy.properties.BooleanProperty`
81 | and defaults to `False`.
82 | """
83 |
84 | focus_color = ColorProperty(None)
85 | """
86 | The color of the widget when the mouse enters the bbox of the widget.
87 |
88 | :attr:`focus_color` is a :class:`~kivy.properties.ColorProperty`
89 | and defaults to `None`.
90 | """
91 |
92 | unfocus_color = ColorProperty(None)
93 | """
94 | The color of the widget when the mouse exits the bbox widget.
95 |
96 | :attr:`unfocus_color` is a :class:`~kivy.properties.ColorProperty`
97 | and defaults to `None`.
98 | """
99 |
100 | def on_enter(self):
101 | """Called when mouse enter the bbox of the widget."""
102 |
103 | if hasattr(self, "md_bg_color") and self.focus_behavior:
104 | if hasattr(self, "theme_cls") and not self.focus_color:
105 | self.md_bg_color = self.theme_cls.bg_normal
106 | else:
107 | if not self.focus_color:
108 | self.md_bg_color = App.get_running_app().theme_cls.bg_normal
109 | else:
110 | self.md_bg_color = self.focus_color
111 |
112 | def on_leave(self):
113 | """Called when the mouse exit the widget."""
114 |
115 | if hasattr(self, "md_bg_color") and self.focus_behavior:
116 | if hasattr(self, "theme_cls") and not self.unfocus_color:
117 | self.md_bg_color = self.theme_cls.bg_light
118 | else:
119 | if not self.unfocus_color:
120 | self.md_bg_color = App.get_running_app().theme_cls.bg_light
121 | else:
122 | self.md_bg_color = self.unfocus_color
123 |
--------------------------------------------------------------------------------
/kivymd/toast/kivytoast/kivytoast.py:
--------------------------------------------------------------------------------
1 | """
2 | KivyToast
3 | =========
4 |
5 | .. rubric:: Implementation of toasts for desktop.
6 |
7 | .. code-block:: python
8 |
9 | from kivy.lang import Builder
10 |
11 | from kivymd.app import MDApp
12 | from kivymd.toast import toast
13 |
14 | KV = '''
15 | MDScreen:
16 |
17 | MDToolbar:
18 | title: 'Test Toast'
19 | pos_hint: {'top': 1}
20 | left_action_items: [['menu', lambda x: x]]
21 |
22 | MDRaisedButton:
23 | text: 'TEST KIVY TOAST'
24 | pos_hint: {'center_x': .5, 'center_y': .5}
25 | on_release: app.show_toast()
26 | '''
27 |
28 |
29 | class Test(MDApp):
30 | def show_toast(self):
31 | '''Displays a toast on the screen.'''
32 |
33 | toast('Test Kivy Toast')
34 |
35 | def build(self):
36 | return Builder.load_string(KV)
37 |
38 | Test().run()
39 | """
40 |
41 | from kivy.animation import Animation
42 | from kivy.clock import Clock
43 | from kivy.core.window import Window
44 | from kivy.lang import Builder
45 | from kivy.metrics import dp
46 | from kivy.properties import ListProperty, NumericProperty
47 | from kivy.uix.label import Label
48 |
49 | from kivymd.uix.dialog import BaseDialog
50 |
51 | Builder.load_string(
52 | """
53 | :
54 | size_hint: (None, None)
55 | pos_hint: {"center_x": 0.5, "center_y": 0.1}
56 | opacity: 0
57 | auto_dismiss: True
58 | overlay_color: [0, 0, 0, 0]
59 | canvas:
60 | Color:
61 | rgba: root._md_bg_color
62 | RoundedRectangle:
63 | pos: self.pos
64 | size: self.size
65 | radius: root.radius
66 | """
67 | )
68 |
69 |
70 | class Toast(BaseDialog):
71 | duration = NumericProperty(2.5)
72 | """
73 | The amount of time (in seconds) that the toast is visible on the screen.
74 |
75 | :attr:`duration` is an :class:`~kivy.properties.NumericProperty`
76 | and defaults to `2.5`.
77 | """
78 |
79 | _md_bg_color = ListProperty()
80 |
81 | def __init__(self, **kwargs):
82 | super().__init__(**kwargs)
83 | self.label_toast = Label(size_hint=(None, None), opacity=0)
84 | self.label_toast.bind(texture_size=self.label_check_texture_size)
85 | self.add_widget(self.label_toast)
86 |
87 | def label_check_texture_size(self, instance, texture_size):
88 | texture_width, texture_height = texture_size
89 | if texture_width > Window.width:
90 | instance.text_size = (Window.width - dp(10), None)
91 | instance.texture_update()
92 | texture_width, texture_height = instance.texture_size
93 | self.size = (texture_width + 25, texture_height + 25)
94 |
95 | def toast(self, text_toast):
96 | self.label_toast.text = text_toast
97 | self.open()
98 |
99 | def on_open(self):
100 | self.fade_in()
101 | Clock.schedule_once(self.fade_out, self.duration)
102 |
103 | def fade_in(self):
104 | anim = Animation(opacity=1, duration=0.4)
105 | anim.start(self.label_toast)
106 | anim.start(self)
107 |
108 | def fade_out(self, *args):
109 | anim = Animation(opacity=0, duration=0.4)
110 | anim.bind(on_complete=lambda *x: self.dismiss())
111 | anim.start(self.label_toast)
112 | anim.start(self)
113 |
114 | def on_touch_down(self, touch):
115 | if not self.collide_point(*touch.pos):
116 | if self.auto_dismiss:
117 | self.fade_out()
118 | return False
119 | super().on_touch_down(touch)
120 | return True
121 |
122 |
123 | def toast(text="", background=[0.2, 0.2, 0.2, 1], duration=2.5):
124 | """Displays a toast.
125 |
126 | :attr duration: the amount of time (in seconds) that the toast is visible on the screen
127 | :type duration: float
128 |
129 | :attr background: color ``rgba`` in Kivy format
130 | :type background: list
131 | """
132 |
133 | Toast(duration=duration, _md_bg_color=background).toast(text)
134 |
--------------------------------------------------------------------------------
/kivymd/factory_registers.py:
--------------------------------------------------------------------------------
1 | """
2 | Register KivyMD widgets to use without import
3 | """
4 |
5 | from kivy.factory import Factory
6 |
7 | r = Factory.register
8 | r("MDNavigationRail", module="kivymd.uix.navigationrail")
9 | r("MDSwiper", module="kivymd.uix.swiper")
10 | r("MDCarousel", module="kivymd.uix.carousel")
11 | r("MDFloatLayout", module="kivymd.uix.floatlayout")
12 | r("MDScreen", module="kivymd.uix.screen")
13 | r("MDBoxLayout", module="kivymd.uix.boxlayout")
14 | r("MDRelativeLayout", module="kivymd.uix.relativelayout")
15 | r("MDGridLayout", module="kivymd.uix.gridlayout")
16 | r("MDStackLayout", module="kivymd.uix.stacklayout")
17 | r("MDExpansionPanel", module="kivymd.uix.expansionpanel")
18 | r("MDExpansionPanelOneLine", module="kivymd.uix.expansionpanel")
19 | r("MDExpansionPanelTwoLine", module="kivymd.uix.expansionpanel")
20 | r("MDExpansionPanelThreeLine", module="kivymd.uix.expansionpanel")
21 | r("FitImage", module="kivymd.utils.fitimage")
22 | r("MDBackdrop", module="kivymd.uix.backdrop")
23 | r("MDBanner", module="kivymd.uix.banner")
24 | r("MDTooltip", module="kivymd.uix.tooltip")
25 | r("MDBottomNavigation", module="kivymd.uix.bottomnavigation")
26 | r("MDBottomNavigationItem", module="kivymd.uix.bottomnavigation")
27 | r("MDToggleButton", module="kivymd.uix.behaviors.toggle_behavior")
28 | r("MDFloatingActionButtonSpeedDial", module="kivymd.uix.button")
29 | r("MDIconButton", module="kivymd.uix.button")
30 | r("MDRoundImageButton", module="kivymd.uix.button")
31 | r("MDFlatButton", module="kivymd.uix.button")
32 | r("MDRaisedButton", module="kivymd.uix.button")
33 | r("MDFloatingActionButton", module="kivymd.uix.button")
34 | r("MDRectangleFlatButton", module="kivymd.uix.button")
35 | r("MDTextButton", module="kivymd.uix.button")
36 | r("MDCustomRoundIconButton", module="kivymd.uix.button")
37 | r("MDRoundFlatButton", module="kivymd.uix.button")
38 | r("MDFillRoundFlatButton", module="kivymd.uix.button")
39 | r("MDRectangleFlatIconButton", module="kivymd.uix.button")
40 | r("MDRoundFlatIconButton", module="kivymd.uix.button")
41 | r("MDFillRoundFlatIconButton", module="kivymd.uix.button")
42 | r("MDCard", module="kivymd.uix.card")
43 | r("MDSeparator", module="kivymd.uix.card")
44 | r("MDSelectionList", module="kivymd.uix.selection")
45 | r("MDChip", module="kivymd.uix.chip")
46 | r("MDChipContainer", module="kivymd.uix.chip")
47 | r("SmartTile", module="kivymd.uix.imagelist")
48 | r("SmartTileWithLabel", module="kivymd.uix.imagelist")
49 | r("SmartTileWithStar", module="kivymd.uix.imagelist")
50 | r("MDLabel", module="kivymd.uix.label")
51 | r("MDIcon", module="kivymd.uix.label")
52 | r("MDList", module="kivymd.uix.list")
53 | r("ILeftBody", module="kivymd.uix.list")
54 | r("ILeftBodyTouch", module="kivymd.uix.list")
55 | r("IRightBody", module="kivymd.uix.list")
56 | r("IRightBodyTouch", module="kivymd.uix.list")
57 | r("ContainerSupport", module="kivymd.uix.list")
58 | r("OneLineListItem", module="kivymd.uix.list")
59 | r("TwoLineListItem", module="kivymd.uix.list")
60 | r("ThreeLineListItem", module="kivymd.uix.list")
61 | r("OneLineAvatarListItem", module="kivymd.uix.list")
62 | r("TwoLineAvatarListItem", module="kivymd.uix.list")
63 | r("ThreeLineAvatarListItem", module="kivymd.uix.list")
64 | r("OneLineIconListItem", module="kivymd.uix.list")
65 | r("TwoLineIconListItem", module="kivymd.uix.list")
66 | r("ThreeLineIconListItem", module="kivymd.uix.list")
67 | r("OneLineRightIconListItem", module="kivymd.uix.list")
68 | r("TwoLineRightIconListItem", module="kivymd.uix.list")
69 | r("ThreeLineRightIconListItem", module="kivymd.uix.list")
70 | r("OneLineAvatarIconListItem", module="kivymd.uix.list")
71 | r("TwoLineAvatarIconListItem", module="kivymd.uix.list")
72 | r("ThreeLineAvatarIconListItem", module="kivymd.uix.list")
73 | r("HoverBehavior", module="kivymd.uix.behaviors.hover_behavior")
74 | r("FocusBehavior", module="kivymd.uix.behaviors.focus_behavior")
75 | r("MagicBehavior", module="kivymd.uix.behaviors.magic_behavior")
76 | r("MDNavigationDrawer", module="kivymd.uix.navigationdrawer")
77 | r("MDNavigationLayout", module="kivymd.uix.navigationdrawer")
78 | r("MDProgressBar", module="kivymd.uix.progressbar")
79 | r("MDScrollViewRefreshLayout", module="kivymd.uix.refreshlayout")
80 | r("MDCheckbox", module="kivymd.uix.selectioncontrol")
81 | r("MDSwitch", module="kivymd.uix.selectioncontrol")
82 | r("MDSlider", module="kivymd.uix.slider")
83 | r("MDSpinner", module="kivymd.uix.spinner")
84 | r("MDTabs", module="kivymd.uix.tab")
85 | r("MDTextField", module="kivymd.uix.textfield")
86 | r("MDTextFieldRound", module="kivymd.uix.textfield")
87 | r("MDTextFieldRect", module="kivymd.uix.textfield")
88 | r("MDToolbar", module="kivymd.uix.toolbar")
89 | r("MDBottomAppBar", module="kivymd.uix.toolbar")
90 | r("MDDropDownItem", module="kivymd.uix.dropdownitem")
91 | r("MDCircularLayout", module="kivymd.uix.circularlayout")
92 |
--------------------------------------------------------------------------------
/kivymd/utils/fitimage.py:
--------------------------------------------------------------------------------
1 | """
2 | Fit Image
3 | =========
4 |
5 | Feature to automatically crop a `Kivy` image to fit your layout
6 | Write by Benedikt Zwölfer
7 |
8 | Referene - https://gist.github.com/benni12er/95a45eb168fc33a4fcd2d545af692dad
9 |
10 |
11 | Example:
12 | ========
13 |
14 | .. code-block:: kv
15 |
16 | BoxLayout:
17 | size_hint_y: None
18 | height: "200dp"
19 | orientation: 'vertical'
20 |
21 | FitImage:
22 | size_hint_y: 3
23 | source: 'images/img1.jpg'
24 |
25 | FitImage:
26 | size_hint_y: 1
27 | source: 'images/img2.jpg'
28 |
29 | Example with round corners:
30 | ===========================
31 |
32 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/fitimage-round-corners.png
33 | :align: center
34 |
35 | .. code-block:: python
36 |
37 | from kivy.uix.modalview import ModalView
38 | from kivy.lang import Builder
39 |
40 | from kivymd import images_path
41 | from kivymd.app import MDApp
42 | from kivymd.uix.card import MDCard
43 |
44 | Builder.load_string(
45 | '''
46 | :
47 | elevation: 10
48 | radius: [36, ]
49 |
50 | FitImage:
51 | id: bg_image
52 | source: "images/bg.png"
53 | size_hint_y: .35
54 | pos_hint: {"top": 1}
55 | radius: [36, 36, 0, 0, ]
56 | ''')
57 |
58 |
59 | class Card(MDCard):
60 | pass
61 |
62 |
63 | class Example(MDApp):
64 | def build(self):
65 | modal = ModalView(
66 | size_hint=(0.4, 0.8),
67 | background=f"{images_path}/transparent.png",
68 | overlay_color=(0, 0, 0, 0),
69 | )
70 | modal.add_widget(Card())
71 | modal.open()
72 |
73 |
74 | Example().run()
75 | """
76 |
77 | __all__ = ("FitImage",)
78 |
79 | from kivy.clock import Clock
80 | from kivy.graphics.context_instructions import Color
81 | from kivy.graphics.vertex_instructions import Rectangle
82 | from kivy.lang import Builder
83 | from kivy.properties import BooleanProperty, ListProperty, ObjectProperty
84 | from kivy.uix.boxlayout import BoxLayout
85 | from kivy.uix.image import AsyncImage
86 | from kivy.uix.widget import Widget
87 |
88 | Builder.load_string(
89 | """
90 |
91 | canvas.before:
92 | StencilPush
93 | RoundedRectangle:
94 | size: self.size
95 | pos: self.pos
96 | radius: root.radius
97 | StencilUse
98 |
99 | canvas.after:
100 | StencilUnUse
101 | RoundedRectangle:
102 | size: self.size
103 | pos: self.pos
104 | radius: root.radius
105 | StencilPop
106 | """
107 | )
108 |
109 |
110 | class FitImage(BoxLayout):
111 | source = ObjectProperty()
112 | container = ObjectProperty()
113 | radius = ListProperty([0, 0, 0, 0])
114 | mipmap = BooleanProperty(False)
115 |
116 | def __init__(self, **kwargs):
117 | super().__init__(**kwargs)
118 | Clock.schedule_once(self._late_init)
119 |
120 | def _late_init(self, *args):
121 | self.container = Container(self.source, self.mipmap)
122 | self.bind(source=self.container.setter("source"))
123 | self.add_widget(self.container)
124 |
125 | def reload(self):
126 | self.container.image.reload()
127 |
128 |
129 | class Container(Widget):
130 | source = ObjectProperty()
131 | image = ObjectProperty()
132 |
133 | def __init__(self, source, mipmap, **kwargs):
134 | super().__init__(**kwargs)
135 | self.image = AsyncImage(mipmap=mipmap)
136 | self.image.bind(on_load=self.adjust_size)
137 | self.source = source
138 | self.bind(size=self.adjust_size, pos=self.adjust_size)
139 |
140 | def on_source(self, instance, value):
141 | if isinstance(value, str):
142 | self.image.source = value
143 | else:
144 | self.image.texture = value
145 | self.adjust_size()
146 |
147 | def adjust_size(self, *args):
148 | if not self.parent or not self.image.texture:
149 | return
150 |
151 | (par_x, par_y) = self.parent.size
152 |
153 | if par_x == 0 or par_y == 0:
154 | with self.canvas:
155 | self.canvas.clear()
156 | return
157 |
158 | par_scale = par_x / par_y
159 | (img_x, img_y) = self.image.texture.size
160 | img_scale = img_x / img_y
161 |
162 | if par_scale > img_scale:
163 | (img_x_new, img_y_new) = (img_x, img_x / par_scale)
164 | else:
165 | (img_x_new, img_y_new) = (img_y * par_scale, img_y)
166 |
167 | crop_pos_x = (img_x - img_x_new) / 2
168 | crop_pos_y = (img_y - img_y_new) / 2
169 |
170 | subtexture = self.image.texture.get_region(
171 | crop_pos_x, crop_pos_y, img_x_new, img_y_new
172 | )
173 |
174 | with self.canvas:
175 | self.canvas.clear()
176 | Color(1, 1, 1)
177 | Rectangle(texture=subtexture, pos=self.pos, size=(par_x, par_y))
178 |
--------------------------------------------------------------------------------
/reminderscheduler.py:
--------------------------------------------------------------------------------
1 | import os
2 | import time
3 | from datetime import datetime
4 | from string import Template
5 | try:
6 | from jnius import cast, autoclass
7 |
8 | except KeyError:
9 | os.environ['JDK_HOME'] = "/usr/lib/jvm/java-1.8.0-openjdk-amd64"
10 | os.environ['JAVA_HOME'] = "/usr/lib/jvm/java-1.8.0-openjdk-amd64"
11 | from jnius import autoclass
12 |
13 | #Import necessary Java classes
14 |
15 | mActivity = autoclass('org.kivy.android.PythonActivity').mActivity
16 | Intent = autoclass('android.content.Intent')
17 | AlarmManager = autoclass('android.app.AlarmManager')
18 | PendingIntent = autoclass('android.app.PendingIntent')
19 | Context = autoclass('android.content.Context')
20 | ReminderAlarmReceiver = autoclass('org.org.remindy.ReminderAlarmReceiver')
21 | ReminderRepeatingAlarmReceiver = autoclass('org.org.remindy.ReminderRepeatingAlarmReceiver')
22 | context = mActivity.getApplicationContext()
23 | String = autoclass('java.lang.String')
24 | mapping = {'Y': 'yyyy', 'm': 'MM', 'd': 'dd', 'H': 'HH', 'M': 'mm'}
25 | Calendar = autoclass('java.util.Calendar')
26 | TimeZone = autoclass('java.util.TimeZone')
27 | SimpleDateFormat = autoclass('java.text.SimpleDateFormat')
28 | ParsePosition = autoclass('java.text.ParsePosition')
29 | Date = autoclass('java.util.Date')
30 |
31 | #Create alarm manager object
32 |
33 |
34 | class ReminderScheduler():
35 | #To update a reminder just overwrite existing reminder
36 |
37 | def schedule(reminder_id,title,description,date_to_ring,time_to_ring,current_list,intent_id):
38 | #Create Intent and add required properties to it
39 | newdate = Intent()
40 | newdate.setClass(context, ReminderAlarmReceiver)
41 | newdate.setAction('org.org.remindy.ACTION_START_REMINDER')
42 | newdate.putExtra("TITLE", String(title))
43 | newdate.putExtra("DESCRIPTION", String(description))
44 | newdate.putExtra("IDENTIFICATION", reminder_id)
45 | newdate.putExtra("INTENT_ID", intent_id)
46 | newdate.putExtra("CURRENT_LIST", String(current_list))
47 | newdatepending = PendingIntent.getBroadcast(context,intent_id,newdate,PendingIntent.FLAG_CANCEL_CURRENT)
48 |
49 | #Create datetime string in python in the format for date object of java
50 | datetime_string = datetime.strptime(date_to_ring+ ' '+time_to_ring, "%x %I:%M %p").strftime("%Y-%m-%d %H:%M")
51 |
52 | #Calculate time for reminder to ring
53 | formatted_string = Template(datetime_string.replace('%', '$')).substitute(**mapping)
54 | formatted_string +=":00"
55 | convertor = SimpleDateFormat("yyyy-MM-dd HH:mm:ss") #Convert to java data type
56 | parsed_object = convertor.parse(formatted_string, ParsePosition(0))
57 |
58 | #Create alarm manager
59 | cast(AlarmManager, context.getSystemService(Context.ALARM_SERVICE)).setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,parsed_object.getTime(), newdatepending)
60 |
61 |
62 | def deschedule(id):
63 | deletedate = Intent()
64 | deletedate.setClass(context, ReminderAlarmReceiver)
65 | deletedate.setAction('org.org.remindy.ACTION_START_REMINDER')
66 | newdatepending = PendingIntent.getBroadcast(context,id,deletedate, PendingIntent.FLAG_CANCEL_CURRENT)
67 | cast(AlarmManager, context.getSystemService(Context.ALARM_SERVICE)).cancel(newdatepending)
68 |
69 | def schedule_repeating(reminder_id,title,description,day_to_ring, time_to_ring, current_list, intent_id):
70 |
71 | #Create Intent and add required properties to it
72 | newday = Intent()
73 | newday.setClass(context, ReminderRepeatingAlarmReceiver)
74 | newday.setAction('org.org.remindy.ACTION_START_REMINDER_REPEATING')
75 | newday.putExtra("TITLE", String(title))
76 | newday.putExtra("DESCRIPTION", String(description))
77 | newday.putExtra("IDENTIFICATION", reminder_id)
78 | newday.putExtra("INTENT_ID", intent_id)
79 | newday.putExtra("CURRENT_LIST", String(current_list))
80 | newdaypending = PendingIntent.getBroadcast(context,reminder_id,newday, PendingIntent.FLAG_CANCEL_CURRENT)
81 |
82 | time = datetime.strptime(time_to_ring,"%I:%M %p").strftime("%H:%M")
83 |
84 | calender= Calendar.getInstance()
85 | calender.set(Calendar.DAY_OF_WEEK, day_to_ring)
86 | calender.set(Calendar.HOUR_OF_DAY, int(time[0:2]))
87 | calender.set(Calendar.MINUTE, int(time[3:]))
88 | calender.set(Calendar.SECOND, 0)
89 | calender.set(Calendar.MILLISECOND, 0)
90 | if Calendar.getInstance().getTimeInMillis() > calender.getTimeInMillis():
91 | calender.add(Calendar.DATE, 7)
92 | #We have to reset the alarm every time it rings as there is no other way to set an exact repeating alarm
93 | cast(AlarmManager, context.getSystemService(Context.ALARM_SERVICE)).setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,calender.getTimeInMillis(), newdaypending)
94 |
95 | def deschedule_repeating(id):
96 | deleteday = Intent()
97 | deleteday.setClass(context, ReminderRepeatingAlarmReceiver)
98 | deleteday.setAction('org.org.remindy.ACTION_START_REMINDER_REPEATING')
99 | newdaypending = PendingIntent.getBroadcast(context,id,deleteday, PendingIntent.FLAG_CANCEL_CURRENT)
100 | cast(AlarmManager, context.getSystemService(Context.ALARM_SERVICE)).cancel(newdaypending)
101 |
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/magic_behavior.py:
--------------------------------------------------------------------------------
1 | """
2 | Behaviors/Magic
3 | ===============
4 |
5 | .. rubric:: Magical effects for buttons.
6 |
7 | .. warning:: Magic effects do not work correctly with `KivyMD` buttons!
8 |
9 | To apply magic effects, you must create a new class that is inherited from the
10 | widget to which you apply the effect and from the :attr:`MagicBehavior` class.
11 |
12 | In `KV file`:
13 |
14 | .. code-block:: kv
15 |
16 |
17 |
18 | In `python file`:
19 |
20 | .. code-block:: python
21 |
22 | class MagicButton(MagicBehavior, MDRectangleFlatButton):
23 | pass
24 |
25 | .. rubric:: The :attr:`MagicBehavior` class provides five effects:
26 |
27 | - :attr:`MagicBehavior.wobble`
28 | - :attr:`MagicBehavior.grow`
29 | - :attr:`MagicBehavior.shake`
30 | - :attr:`MagicBehavior.twist`
31 | - :attr:`MagicBehavior.shrink`
32 |
33 | Example:
34 |
35 | .. code-block:: python
36 |
37 | from kivymd.app import MDApp
38 | from kivy.lang import Builder
39 |
40 | KV = '''
41 | #:import MagicBehavior kivymd.uix.behaviors.MagicBehavior
42 |
43 |
44 |
45 |
46 |
47 | FloatLayout:
48 |
49 | MagicButton:
50 | text: "WOBBLE EFFECT"
51 | on_release: self.wobble()
52 | pos_hint: {"center_x": .5, "center_y": .3}
53 |
54 | MagicButton:
55 | text: "GROW EFFECT"
56 | on_release: self.grow()
57 | pos_hint: {"center_x": .5, "center_y": .4}
58 |
59 | MagicButton:
60 | text: "SHAKE EFFECT"
61 | on_release: self.shake()
62 | pos_hint: {"center_x": .5, "center_y": .5}
63 |
64 | MagicButton:
65 | text: "TWIST EFFECT"
66 | on_release: self.twist()
67 | pos_hint: {"center_x": .5, "center_y": .6}
68 |
69 | MagicButton:
70 | text: "SHRINK EFFECT"
71 | on_release: self.shrink()
72 | pos_hint: {"center_x": .5, "center_y": .7}
73 | '''
74 |
75 |
76 | class Example(MDApp):
77 | def build(self):
78 | return Builder.load_string(KV)
79 |
80 |
81 | Example().run()
82 |
83 |
84 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/magic-button.gif
85 | :width: 250 px
86 | :align: center
87 | """
88 |
89 | __all__ = ("MagicBehavior",)
90 |
91 | from kivy.animation import Animation
92 | from kivy.lang import Builder
93 | from kivy.properties import NumericProperty
94 |
95 | Builder.load_string(
96 | """
97 |
98 | translate_x: 0
99 | translate_y: 0
100 | scale_x: 1
101 | scale_y: 1
102 | rotate: 0
103 |
104 | canvas.before:
105 | PushMatrix
106 | Translate:
107 | x: self.translate_x or 0
108 | y: self.translate_y or 0
109 | Rotate:
110 | origin: self.center
111 | angle: self.rotate or 0
112 | Scale:
113 | origin: self.center
114 | x: self.scale_x or 1
115 | y: self.scale_y or 1
116 | canvas.after:
117 | PopMatrix
118 | """
119 | )
120 |
121 |
122 | class MagicBehavior:
123 |
124 | magic_speed = NumericProperty(1)
125 | """
126 | Animation playback speed.
127 |
128 | :attr:`magic_speed` is a :class:`~kivy.properties.NumericProperty`
129 | and defaults to `1`.
130 | """
131 |
132 | def grow(self):
133 | """Grow effect animation."""
134 |
135 | (
136 | Animation(
137 | scale_x=1.2,
138 | scale_y=1.2,
139 | t="out_quad",
140 | d=0.03 / self.magic_speed,
141 | )
142 | + Animation(
143 | scale_x=1, scale_y=1, t="out_elastic", d=0.4 / self.magic_speed
144 | )
145 | ).start(self)
146 |
147 | def shake(self):
148 | """Shake effect animation."""
149 |
150 | (
151 | Animation(translate_x=50, t="out_quad", d=0.02 / self.magic_speed)
152 | + Animation(
153 | translate_x=0, t="out_elastic", d=0.5 / self.magic_speed
154 | )
155 | ).start(self)
156 |
157 | def wobble(self):
158 | """Wobble effect animation."""
159 |
160 | (
161 | (
162 | Animation(scale_y=0.7, t="out_quad", d=0.03 / self.magic_speed)
163 | & Animation(
164 | scale_x=1.4, t="out_quad", d=0.03 / self.magic_speed
165 | )
166 | )
167 | + (
168 | Animation(scale_y=1, t="out_elastic", d=0.5 / self.magic_speed)
169 | & Animation(
170 | scale_x=1, t="out_elastic", d=0.4 / self.magic_speed
171 | )
172 | )
173 | ).start(self)
174 |
175 | def twist(self):
176 | """Twist effect animation."""
177 |
178 | (
179 | Animation(rotate=25, t="out_quad", d=0.05 / self.magic_speed)
180 | + Animation(rotate=0, t="out_elastic", d=0.5 / self.magic_speed)
181 | ).start(self)
182 |
183 | def shrink(self):
184 | """Shrink effect animation."""
185 |
186 | Animation(
187 | scale_x=0.95, scale_y=0.95, t="out_quad", d=0.1 / self.magic_speed
188 | ).start(self)
189 |
190 | def on_touch_up(self, *args):
191 | Animation.stop_all(self)
192 | return super().on_touch_up(*args)
193 |
--------------------------------------------------------------------------------
/scr/ReminderAlarmReceiver.java:
--------------------------------------------------------------------------------
1 | package org.org.remindy;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Intent;
5 | import android.content.Context;
6 | import android.app.NotificationChannel;
7 | import android.app.NotificationManager;
8 | import androidx.core.app.NotificationCompat;
9 | import androidx.core.app.NotificationManagerCompat;
10 | import android.app.Notification;
11 | import android.app.PendingIntent;
12 | import android.os.Build;
13 | import android.os.Bundle;
14 | import org.kivy.android.PythonActivity;
15 | import android.media.RingtoneManager;
16 | import android.net.Uri;
17 | import android.media.AudioAttributes;
18 | import org.remindy.remindy.R;
19 | import org.org.remindy.FullScreenNotify;
20 | import java.lang.Math;
21 |
22 | public class ReminderAlarmReceiver extends BroadcastReceiver{
23 |
24 | private void createNotificationChannel(Context context) {
25 |
26 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
27 | Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
28 |
29 | AudioAttributes att = new AudioAttributes.Builder()
30 | .setUsage(AudioAttributes.USAGE_NOTIFICATION)
31 | .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
32 | .build();
33 |
34 | CharSequence name = "New Reminder";
35 | String description = "New Reminder";
36 | int importance = NotificationManager.IMPORTANCE_HIGH;
37 | NotificationChannel channel = new NotificationChannel("REMINDY", name, importance);
38 | channel.setDescription(description);
39 | channel.setSound(sound, att);
40 | channel.enableLights(true);
41 | channel.enableVibration(true);
42 | NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
43 | notificationManager.createNotificationChannel(channel);
44 | }
45 | }
46 |
47 | private void sendNotification(Context context, Intent intent) {
48 | Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
49 | int notification_id = (int)(Math.random()*(8000-1+1)+1);
50 | Intent newintent = new Intent(context, PythonActivity.class);
51 | Short id = intent.getShortExtra("IDENTIFICATION", (short) 0);
52 | String current_list = intent.getStringExtra("CURRENT_LIST");
53 | newintent.putExtra("LAUNCH_APP_WITH_REMINDER", id);
54 | newintent.putExtra("CURRENT_LIST", current_list);
55 | PendingIntent pendingintent = PendingIntent.getActivity(context,notification_id, newintent, PendingIntent.FLAG_ONE_SHOT);
56 |
57 | Intent mrkcomp = new Intent(context, ReminderMarkComp.class);
58 | mrkcomp.putExtra("CURRENT_LIST", current_list);
59 | mrkcomp.putExtra("IDENTIFICATION", intent.getExtras().getShort("IDENTIFICATION"));
60 | mrkcomp.putExtra("NOTIFICATION_ID", notification_id);
61 | mrkcomp.putExtra("INTENT_ID", intent.getExtras().getShort("INTENT_ID"));
62 | mrkcomp.setAction("org.org.remindy.MRKCOMP");
63 | PendingIntent pendingmrkcomp = PendingIntent.getBroadcast(context,notification_id,mrkcomp, PendingIntent.FLAG_ONE_SHOT);
64 | String title = "Mark As Complete";
65 | NotificationCompat.Action mrkcompaction = new NotificationCompat.Action.Builder( 0, title, pendingmrkcomp).build();
66 |
67 | Intent snooze = new Intent(context, ReminderSnooze.class);
68 | snooze.putExtra("TITLE", intent.getExtras().getString("TITLE"));
69 | snooze.putExtra("DESCRIPTION", intent.getExtras().getString("DESCRIPTION"));
70 | snooze.putExtra("IDENTIFICATION", intent.getExtras().getShort("IDENTIFICATION"));
71 | snooze.putExtra("NOTIFICATION_ID", notification_id);
72 | snooze.putExtra("INTENT_ID", intent.getExtras().getShort("INTENT_ID"));
73 | snooze.putExtra("CURRENT_LIST", current_list);
74 | PendingIntent pendingsnooze = PendingIntent.getBroadcast(context, notification_id, snooze, PendingIntent.FLAG_CANCEL_CURRENT);
75 | NotificationCompat.Action snoozeaction = new NotificationCompat.Action.Builder( 0, "Snooze for 10 mins", pendingsnooze).build();
76 |
77 | // Intent fsintent = new Intent(context,FullScreenNotify.class);
78 | // PendingIntent fspending = PendingIntent.getActivity(context,notification_id,fsintent, PendingIntent.FLAG_ONE_SHOT);
79 |
80 | NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "REMINDY")
81 | .setSmallIcon(R.drawable.ic_launcher)
82 | .setContentTitle(intent.getExtras().getString("TITLE"))
83 | .setContentText(intent.getExtras().getString("DESCRIPTION"))
84 | .setTicker("New Reminder")
85 | .setVibrate(new long[]{0, 300, 0, 400, 0, 500})
86 | .setSound(uri)
87 | .setAutoCancel(true)
88 | .setOnlyAlertOnce(false)
89 | .setPriority(NotificationCompat.PRIORITY_HIGH)
90 | .setContentIntent(pendingintent)
91 | .addAction(mrkcompaction)
92 | .addAction(snoozeaction);
93 | // .setFullScreenIntent(fspending,true);
94 |
95 | NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
96 | notificationManager.notify(notification_id,builder.build());
97 | }
98 |
99 |
100 |
101 | @Override
102 | public void onReceive(Context context, Intent intent) {
103 | this.createNotificationChannel(context);
104 | this.sendNotification(context, intent);
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/kivymd/uix/circularlayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/CircularLayout
3 | =========================
4 |
5 | CircularLayout is a special layout that places widgets around a circle.
6 |
7 | MDCircularLayout
8 | ----------------
9 |
10 | .. rubric:: Usage
11 |
12 | .. code-block::
13 |
14 | from kivy.lang.builder import Builder
15 | from kivy.uix.label import Label
16 |
17 | from kivymd.app import MDApp
18 |
19 | kv = '''
20 | Screen:
21 | MDCircularLayout:
22 | id: container
23 | pos_hint: {"center_x": .5, "center_y": .5}
24 | row_spacing: min(self.size)*0.1
25 | '''
26 |
27 |
28 | class Main(MDApp):
29 | def build(self):
30 | return Builder.load_string(kv)
31 |
32 | def on_start(self):
33 | for x in range(1, 49):
34 | self.root.ids.container.add_widget(
35 | Label(text=f"{x}", color=[0, 0, 0, 1])
36 | )
37 |
38 |
39 | Main().run()
40 |
41 | """
42 |
43 | __all__ = ("MDCircularLayout",)
44 |
45 | from math import atan2, cos, degrees, radians, sin
46 |
47 | from kivy.properties import BooleanProperty, NumericProperty
48 |
49 | from kivymd.uix.floatlayout import MDFloatLayout
50 |
51 |
52 | class MDCircularLayout(MDFloatLayout):
53 |
54 | degree_spacing = NumericProperty(30)
55 | """
56 | The space between children in degree.
57 |
58 | :attr:`degree_spacing` is an :class:`~kivy.properties.NumericProperty`
59 | and defaults to `30`.
60 | """
61 |
62 | circular_radius = NumericProperty(None, allownone=True)
63 | """
64 | Radius of circle. Radius will be the greatest value in the layout if `circular_radius` if not specified.
65 |
66 | :attr:`circular_radius` is an :class:`~kivy.properties.NumericProperty`
67 | and defaults to `None`.
68 | """
69 |
70 | start_from = NumericProperty(60)
71 | """
72 | The positon of first child in degree.
73 |
74 | :attr:`start_from` is an :class:`~kivy.properties.NumericProperty`
75 | and defaults to `60`.
76 | """
77 |
78 | max_degree = NumericProperty(360)
79 | """
80 | Maximum range in degree allowed for each row of widgets before jumping to the next row.
81 |
82 | :attr:`max_degree` is an :class:`~kivy.properties.NumericProperty`
83 | and defaults to `360`.
84 | """
85 |
86 | circular_padding = NumericProperty("25dp")
87 | """
88 | Padding between outer widgets and the edge of the biggest circle.
89 |
90 | :attr:`circular_padding` is an :class:`~kivy.properties.NumericProperty`
91 | and defaults to `25dp`.
92 | """
93 |
94 | row_spacing = NumericProperty("50dp")
95 | """
96 | Space between each row of widget.
97 |
98 | :attr:`row_spacing` is an :class:`~kivy.properties.NumericProperty`
99 | and defaults to `50dp`.
100 | """
101 |
102 | clockwise = BooleanProperty(True)
103 | """
104 | Direction of widgets in circular direction.
105 |
106 | :attr:`clockwise` is an :class:`~kivy.properties.BooleanProperty`
107 | and defaults to `True`.
108 | """
109 |
110 | def __init__(self, **kwargs):
111 | super().__init__(**kwargs)
112 | self.bind(
113 | row_spacing=self._update_layout,
114 | )
115 |
116 | def _update_layout(self, *args):
117 | for index, child in enumerate(reversed(self.children)):
118 | pos = self._point_on_circle(
119 | self._calculate_radius(index),
120 | self._calculate_degree(index),
121 | )
122 | child.center = pos
123 |
124 | def do_layout(self, *largs, **kwargs):
125 | self._update_layout()
126 | return super().do_layout(*largs, **kwargs)
127 |
128 | def _max_per_row(self):
129 | return int(self.max_degree / self.degree_spacing)
130 |
131 | def _calculate_radius(self, index):
132 | """
133 | calculates the radius for given index
134 |
135 | """
136 |
137 | idx = int(index / self._max_per_row())
138 |
139 | if not self.circular_radius:
140 | init_radius = (
141 | min([self.width / 2, self.height / 2]) - self.circular_padding
142 | )
143 | else:
144 | init_radius = self.circular_radius
145 |
146 | if idx != 0:
147 | space = self.row_spacing * idx
148 | init_radius -= space
149 |
150 | return init_radius
151 |
152 | def _calculate_degree(self, index):
153 | """ calculates the angle for given index"""
154 | if self.clockwise:
155 | degree = self.start_from - index * self.degree_spacing
156 | else:
157 | degree = self.start_from + index * self.degree_spacing
158 |
159 | return degree
160 |
161 | def remove_widget(self, widget, **kwargs):
162 | super().remove_widget(widget, **kwargs)
163 | self._update_layout()
164 |
165 | def _point_on_circle(self, radius, degree):
166 | angle = radians(degree)
167 | center = [self.pos[0] + self.width / 2, self.pos[1] + self.height / 2]
168 | x = center[0] + (radius * cos(angle))
169 | y = center[1] + (radius * sin(angle))
170 | return [x, y]
171 |
172 | def get_angle(self, pos):
173 | """
174 | Returns the angle of given pos
175 | """
176 |
177 | center = [self.pos[0] + self.width / 2, self.pos[1] + self.height / 2]
178 | (dx, dy) = (center[0] - pos[0], center[1] - pos[1])
179 | angle = degrees(atan2(float(dy), float(dx)))
180 | angle += 180
181 | return angle
182 |
183 |
184 | if __name__ == "__main__":
185 | from kivy.lang.builder import Builder
186 | from kivy.uix.label import Label
187 |
188 | from kivymd.app import MDApp
189 |
190 | kv = """
191 | Screen:
192 | MDCircularLayout:
193 | id: container
194 | pos_hint: {"center_x": .5, "center_y": .5}
195 | row_spacing: min(self.size)*0.1
196 | """
197 |
198 | class Main(MDApp):
199 | def build(self):
200 | return Builder.load_string(kv)
201 |
202 | def on_start(self):
203 | for x in range(1, 49):
204 | self.root.ids.container.add_widget(
205 | Label(text=f"{x}", color=[0, 0, 0, 1])
206 | )
207 |
208 | Main().run()
209 |
--------------------------------------------------------------------------------
/kivymd/tools/release/update_icons.py:
--------------------------------------------------------------------------------
1 | # Copyright (c) 2019-2020 Artem Bulgakov
2 | #
3 | # This file is distributed under the terms of the same license,
4 | # as the Kivy framework.
5 |
6 | """
7 | Tool for updating Iconic font
8 | =============================
9 |
10 | Downloads archive from https://github.com/Templarian/MaterialDesign-Webfont and
11 | updates font file with icon_definitions.
12 | """
13 |
14 | import json
15 | import os
16 | import re
17 | import shutil
18 | import sys
19 | import zipfile
20 |
21 | import requests
22 |
23 | from kivymd.tools.release.git_commands import git_commit
24 |
25 | # Paths to files in kivymd repository
26 | kivymd_path = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
27 | font_path = os.path.join(
28 | kivymd_path, "fonts", "materialdesignicons-webfont.ttf"
29 | )
30 | icon_definitions_path = os.path.join(kivymd_path, "icon_definitions.py")
31 |
32 | font_version = "master"
33 | # URL to download new archive (set None if already downloaded)
34 | url = (
35 | f"https://github.com/Templarian/MaterialDesign-Webfont"
36 | f"/archive/{font_version}.zip"
37 | )
38 | # url = None
39 |
40 | # Paths to files in loaded archive
41 | temp_path = os.path.join(os.path.dirname(__file__), "temp")
42 | temp_repo_path = os.path.join(
43 | temp_path, f"MaterialDesign-Webfont-{font_version}"
44 | )
45 | temp_font_path = os.path.join(
46 | temp_repo_path, "fonts", "materialdesignicons-webfont.ttf"
47 | )
48 | temp_preview_path = os.path.join(temp_repo_path, "preview.html")
49 |
50 | # Regex
51 | re_icons_json = re.compile(r"(?<=var icons = )[\S ]+(?=;)")
52 | re_additional_icons = re.compile(r"(?<=icons\.push\()[\S ]+(?=\);)")
53 | re_version = re.compile(r"(?<=)[\d.]+(?=)")
54 | re_quote_keys = re.compile(r"([{\s,])(\w+)(:)")
55 | re_icon_definitions = re.compile(r"md_icons = {\n([ ]{4}[\s\S]*,\n)*}")
56 | re_version_in_file = re.compile(r"(?<=LAST UPDATED: Version )[\d.]+(?=\n)")
57 |
58 |
59 | def download_file(url, path):
60 | response = requests.get(url, stream=True)
61 | if response.status_code != 200:
62 | return False
63 | with open(path, "wb") as f:
64 | shutil.copyfileobj(response.raw, f)
65 | return True
66 |
67 |
68 | def unzip_archive(archive_path, dir_path):
69 | with zipfile.ZipFile(archive_path, "r") as zip_ref:
70 | zip_ref.extractall(dir_path)
71 |
72 |
73 | def get_icons_list():
74 | # There is js array with icons in file preview.html
75 | with open(temp_preview_path, "r") as f:
76 | preview_file = f.read()
77 | # Find version
78 | version = re_version.findall(preview_file)[0]
79 | # Load icons
80 | jsons_icons = re_icons_json.findall(preview_file)[0]
81 | json_icons = re_quote_keys.sub(r'\1"\2"\3', jsons_icons)
82 | icons = json.loads(json_icons)
83 | # Find additional icons (like a blank icon)
84 | # jsons_additional_icons = re_additional_icons.findall(preview_file)
85 | # for j in jsons_additional_icons:
86 | # json_additional_icons = re_quote_keys.sub(r'\1"\2"\3', j)
87 | # icons.append(json.loads(json_additional_icons))
88 | return icons, version
89 |
90 |
91 | def make_icon_definitions(icons):
92 | # Make python dict ("name": hex)
93 | icon_definitions = "md_icons = {\n"
94 | for i in icons:
95 | icon_definitions += " " * 4
96 | if len(i["hex"]) != 4:
97 | # Some icons has 5-digit unicode
98 | i["hex"] = "0" * (8 - len(i["hex"])) + i["hex"]
99 | icon_definitions += f'"{i["name"]}": "\\U{i["hex"].upper()}",\n'
100 | else:
101 | icon_definitions += f'"{i["name"]}": "\\u{i["hex"].upper()}",\n'
102 | icon_definitions += " " * 4 + '"blank": " ",\n' # Add blank icon (space)
103 | icon_definitions += "}"
104 | return icon_definitions
105 |
106 |
107 | def export_icon_definitions(icon_definitions, version):
108 | with open(icon_definitions_path, "r") as f:
109 | icon_definitions_file = f.read()
110 | # Change md_icons list
111 | new_icon_definitions = re_icon_definitions.sub(
112 | icon_definitions.replace("\\", "\\\\"), icon_definitions_file, 1
113 | )
114 | # Change version
115 | new_icon_definitions = re_version_in_file.sub(
116 | version, new_icon_definitions, 1
117 | )
118 | with open(icon_definitions_path, "w") as f:
119 | f.write(new_icon_definitions)
120 |
121 |
122 | def update_icons(make_commit: bool = False):
123 | if url is not None:
124 | print(f"Downloading Material Design Icons from {url}")
125 | if download_file(url, "iconic-font.zip"):
126 | print("Archive downloaded")
127 | else:
128 | print("Error: Could not download archive", file=sys.stderr)
129 | else:
130 | print("URL is None. Do not download archive")
131 | if os.path.exists("iconic-font.zip"):
132 | unzip_archive("iconic-font.zip", temp_path)
133 | print("Unzip successful")
134 | os.remove("iconic-font.zip")
135 | if os.path.exists(temp_repo_path):
136 | shutil.copy2(temp_font_path, font_path)
137 | print("Font copied")
138 | icons, version = get_icons_list()
139 | print(f"Version {version}. {len(icons)} icons loaded")
140 | icon_definitions = make_icon_definitions(icons)
141 | export_icon_definitions(icon_definitions, version)
142 | print("File icon_definitions.py updated")
143 | shutil.rmtree(temp_path, ignore_errors=True)
144 |
145 | if make_commit:
146 | git_commit(
147 | f"Update Iconic font (v{version})",
148 | allow_error=True,
149 | add_files=[
150 | "kivymd/icon_definitions.py",
151 | "kivymd/fonts/materialdesignicons-webfont.ttf",
152 | ],
153 | )
154 | print("\nSuccessful. You can now push changes")
155 | else:
156 | print(
157 | f'\nSuccessful. Commit message: "Update Iconic font (v{version})"'
158 | )
159 | else:
160 | print(f"Error: {temp_repo_path} not exists", file=sys.stderr)
161 | exit(1)
162 |
163 |
164 | def main():
165 | make_commit = "--commit" in sys.argv
166 | if "--commit" in sys.argv:
167 | sys.argv.remove("--commit")
168 | update_icons(make_commit=make_commit)
169 |
170 |
171 | if __name__ == "__main__":
172 | main()
173 |
--------------------------------------------------------------------------------
/other/my_gestures.py:
--------------------------------------------------------------------------------
1 | from kivy.gesture import GestureDatabase
2 |
3 | gdb = GestureDatabase()
4 |
5 | cross = gdb.str_to_gesture(
6 | 'eNq1l9tu3DYQhu/1It6bLjicE+cFtrcF/ACBYwv2Iqkt7G7a5u1DDqlT0lZ7I2Mxsj5JP2f4k'
7 | 'xR1OH85//X9+Npfb98uffd7Ow6hO7wM0D0+vD/92T90Q8z/5gN218eH6+3y8aW/5lPqDl8H7g'
8 | '7/KvLot3WDFCnNzw8f5/dbeSyVx+w/Hvuj3NUNUDMoKXzPj0DsTuGIGiRJGCOVbP4pV7E7/Ra'
9 | 'ORJZMwhS1u35++v9WyFvh7rU2ENEMJI1RuLu+NnEEgyhpjEG2xb1y0H3Ek4vbKA6kEmyKEWdx'
10 | 'WPaJsaVN8eidH2Ef8ejiOIqHdbeQLvolaLTFLxlty7ulsVlaNBKChCnmEpp+uRSSIozRBLbl3'
11 | 'dSoe8m7rdF2kkc3FmGSB1FVphYT6qSejY2sOsXtyYRuLOIkHgEtGrZIKJP4Spk13ZG524qzrX'
12 | 'FWLlHmfok/9UvcFndTUe8Rz8OVA7RIYXtAoluKdke3hJU42j0dQ24pwV7ybiptm1oGE+Rz4il'
13 | 'u9w25q8R3qQtnZ2WKd+TutpLeox4pZmt1jHlh3VR3X8nuUceFdIm4qc5uKy9mapCY339jXKb+'
14 | '08tjewlmN5VxH3H3lBcLcASZfzGv4osFPiVk5SnmCb6p766y7qbvvvL0Zg2GKtHGCDjPJ2FKi'
15 | 'cfI2wuNuKsCu2i7qYLzdiP3BXGLYIs1DEAo0hh1eyaJeyq8i7b7KdM26ddNXpPO7SCSTnHbSn'
16 | 'ErxXaQVndSJyeJGQOMMe+RJm1aLrk5bku7kYp7SLuPOvlI6/FHs4+87hH2Fats/p8vff8+beV'
17 | 'Vyl5etTucMA/a7kSE+XAbNHVPmcGK2ZKBsxSciTPUyqAwUmdRKouFCToDqgwLU3MWQmVUmDnD'
18 | '1O7jwsCfOuXFt0JxGKNDaS1rhVwhV5gqpBW0CnEJLaw0G4QKwwrGmlJaQaxw1bp5QRBsBb2iZ'
19 | 'MvczQtSWjGvx09m5uXwmnk1tNKDEGYbZli94TX0aqg1nRrE5Z3WoFdDtWyFBr0aqR2URljLqa'
20 | '1bbNDrsToywth69QfqGIrcaDVoPSoBqkNtbDE1Wi3iqsAtV6gesSdL0vKCalLNdqa5rjpB3vr'
21 | 'z69utfJTmz8qTFclM/z6/3N4cSteSyvT28bW/PL0/935Ffdsd1n9Q7muT+dNw+Xj59lzFU+6W'
22 | 'Y5L8ug5qwTR/PFH5bDz+AM/6Dqo=')
23 |
24 | circle = gdb.str_to_gesture(
25 | 'eNq1WNtyGzcMfd8fiV+iIS4EyB9QXzuTD+g4icbxpLU1ttI2f18QoHa5jpy12qlGAyUw9hA4B'
26 | 'yQh3dx/vf/z++7u8Hz69nSYfumfxzTdfD7C9OHdw+0fh3fTEe2f9kHT84d3z6enx6+HZ/svTz'
27 | 'e/H/N0cxHkg4dNR2lQas8fH+8fTu2x0h6rrzz2a4uajhAZtBS+2yOA0z7tCDMkqjk1y0W1pfN'
28 | '3+zNN+/dpl0pGqmdLJcv0/PH25+uwr5Onu74EMxErVLeGMT3fNXQDT4C1kopbLVBhG92LB91G'
29 | 'h6RJinRb5A2ZF8euM/aP5JyxhVVShbBiJW9ho7OPcMZG1YTzWzTP2LgAm8XyBmx0bJqxsfSkm'
30 | '8UqMzaRluVduW5ju5o4qwkKmFWruM28cGLNcW3eriXOWi5kv8zbNK7GcwmbabtP0LXEWcuB7M'
31 | 'Y3pSVxVuRMiGFJaBOcXEzqYrZtwglLEsluBdOSen7R5LiN7nISzehAwsQZwC3yfwJ3PSnP4FZ'
32 | '31fnNrZX/PS8uKOkCvpBiFkfSF2Sz3PpoC9wVpTqDExXKmkvYmoc274S8nRZ2RXlR1B5u5xGG'
33 | '1bKcK7a5rtz77ILyIihVSVzL2bb8zuB4LefsgnJ+AzjQtTuUXVBeBCVRTKSMbq1HA/u9b7DMo'
34 | 'hpWSLbPFnZFuf4/6NklzYOki57N1rzAQ8YV/HY3Ztc0L5piXR0BMqAj1GItLmELb/OeXdQ87F'
35 | 'KB8QhIOKDXOXGzOb2BGVc1D9sUaNxJNiPM6LQkbpbS9lbKrmpeVAXluRtTTloXdDs2B95z3UY'
36 | 'XV1UWVe2aPydutqAO6HIt7+KqCm0f7A2+Fk1JkNyiTQ+b8C6rzJdpyrkoQUlhUx6IZ61XEi8u'
37 | 'qyzXKSODTSphAcsAjnBlz4irKvN9CjVxsXEwu2UZ9iopXcmLuqgKWwOMb2JJNoh2y284B9Q11'
38 | 'WU6En2NFuRrFVVXVJdhN71QdDhjBIe3a/3xtg3/n54Oh4d5lFdps7zNmjd7Rt2laY9ad3V88X'
39 | 'Q6apluW0TxiAL2Yc7qTkqjs6RwSjgxnOBOhpUTw6krJ7kz06up2D3iETUiNB7L7pT+WLZhf3h'
40 | 'Ji5CIiLyU4zENZ5SlPYWoVSNZTeGMWv25vWnqzhq1amBKYNaotcTjuUdGrSXy8+rMGbWW7E6u'
41 | '66SpRUStJRbgvGZDW0QUXqICjgqqjE6q4dSVM19Yrawi4MJqwUIJyTBqg5TGOpC6F1be9ON6t'
42 | 'tdGVkB+XNA2ZYREjwFfCgmSNJKC8/JBjMbyAN0bzLjS5k3dG9RoLJJK95axY9K52KBAohGShB'
43 | 'eCAgncdIFcABj79nJI8JHzT0L6/kg/CQk+mFd5Q/BBtKoRZNzXZz4g+MC0YhSCD+hqXWhGgCA'
44 | 'n1dcFxWAqdV0uND1gMJWCTIyeBnRy7CtZeLl7KbxRLPaykMObXu1k+1rpIb2VL20Hm9siJFKl'
45 | 'TiTqylu7t4SXx31o35ZW3p4zpZVXLyxNsAq5xBIFH/1syH1FCj76Hs69PSn4KHU8k2w+D5aCZ'
46 | '+lbhKLqGvVJF5+i6hp0yRk3WiLFWSedfepdQOMBCtyFl/GsBe5a9xO4r8axESCNh7UNo+GFVw'
47 | '95YB57VHuaHL0Pebwy7DYPb79IevLcex/W3n7/0dobhWI+X1buzVEoytprhcYN/OVwf/fl1H7'
48 | '0sql+ry83CbbfxP66/3z64iF2m9sJZxjmPT3+fni6ffh08L9w/IixfkGL68PDb8enx8/fPsVS'
49 | 'edrnnc05diDYoIA2CpbUvu7t/gFuoPx3')
50 |
51 | check = gdb.str_to_gesture(
52 | 'eNq1l0tuI0cMhvd9EXsTofgmL6BsA/gAgcYWbGMmtmBpksztwyY1kgZI0rNpbdr+u+pjkX+9+'
53 | 'v718+uf3zbP++Pp68d++vX8PIzp/ukA08Pd2+6P/d10wPwzHzQdH+6Op4/3z/tj/svT/ZeDTP'
54 | 'f/CnmoZtNBZ5Rl/8P769tp7uZzt/iPbr/NraYD9AjmIXzLLoDTdmxgBLsSMMIw5OHzcP6eX9O'
55 | '0/WVsCMFGmCuaGgjBdPy0+/8wXGFkeu4Ig7LzgISbMw/j6fh8hmMMBDIkdBYPimV4pQ7W8EQM'
56 | 'UA4LMhMzCyW5watKgJoOHhxsuIz3wscVb8ExhpIxDoIgvcEzhoaiZ1geA20Rj+UAwlp4LDxd8'
57 | 'OkqO4KHYXLI4oYOwEai4oPRmHiZXr6iXOiY9mXBFUNYacAVDm4uIOCiaXws24plK9oq7PIUr5'
58 | '6iOqsyg+acyOrezJicpTCI3YYy5HtapFNZSldLCcRgCCk4hqniDZ2dHZjCMf1EXh47laNEN2M'
59 | 'fEjkzJFgtK3BLHwEAGTcnlSu7LNPLUbo6+n2m5GbAuVzUr/ShYQzoSBSWi5iXJwyVqWRr4ctX'
60 | '+om1mq+GR7ibAA8dJuHLfC5nGVbjl7dMS/tk1g3tB3OXZyWXsyyrsMtWtlXY5SnHGmwpPwW+s'
61 | '3M15h5CkVvM8FyWcWH3Uce5io00A/8Eu7wUWoVdXoqswi4v5eIlseTWl6e9Cqh6+IUt6OoUwA'
62 | 'JD88KwjC4rJVZAazmpsAa6jFRaA10+qqyBLht1DRu1bNQ1bLSy0S425mWFOc9khtxcnRwuaEW'
63 | '6PZnH8sFp5aPRKuwy0i5GMnsmHJE32dz73a5oG3nJgLyemqDgXKtPu/m2//ix379d7u6m8+Xd'
64 | 'bLrf5jg2Y9picD5OB/NpN4vQIrYYLWKJHiX6aJFblBahRSvRvEUsETuQjRapxe6uHSjPsBK7u'
65 | '0CL0mKUyLKJ25/NLbRaUI+PzwGsRWrxzOr0qKNy5+ydHnVUzsftj7JFdK7cAUSrW3SugrdpRe'
66 | 'eqdluV6Fxdu6hdv6hcCeYabQl7KFG5ElWpiM6itqgtWovWorXYlU6/d234y/71+eWUVud1dRv'
67 | 'z2xT/en06vcwfWiP7QFU51dP7l/3H7u1xX2+gP9F+/MHc7jw1fz98vD99fTxV65yN6YfP81jE'
68 | '8nDMa8j81bD5B2R9zCo=')
69 |
70 | square = gdb.str_to_gesture(
71 | 'eNq1mEluIzcYRvd1EXsT4Z+HC6i3AXyAwG0LttEdW7DUSfr2YZHVEgk4KQGCtZH8RD4OH4eSb'
72 | '1++vfz1c/O0Oxx/vO+mL8v7Hqbbxz1Odzev93/ubqY9lY/ljafD3c3h+P72bXcof8p0+32v0+'
73 | '2HkrtabNrbrPJSf//28nqcq8VcLf+j2u9zqWmPrQdzF36WKkjTFjasKZKMaJwqGTp355/5a56'
74 | '2v8FGREAVLIINymebDl/v/78Zqc3o9LS04EgogK6ECeSlhadFTomIHElsKqoS6/I6dPQL5JiW'
75 | 'aSTKYMZEuS6PKs8L5DD03DB11U51+gnX7EVuGOQUgqDIxHGBnKqc1+XkJXLMyAyXUFkPlGqgp'
76 | 'J/irnmSr7s5kThBIhAB5RJ3jZPOcYpbiIG6elkc81Je3DL222TVzTVMPoVJggFESoEGBIJndy'
77 | 'irWWpYRonyAnfNkk9ZQkQYghuLSlnI7tfIa5i8hDmvZFBSUwdH5ixDgKv6XvNkP+mxbDxgo1S'
78 | '2JIhr3DVPzpOb0IGQ3DTVhTPP8nEH+bpcaqCCJzkHOjlqpISFAp/lZMqMZqIBLnCBvCYqfJKL'
79 | 'EqNyCgkFFNlZjt0qJaD1rS81UTknKuEGqYgRGUZdnsxlnapilrkiKafjurzmKec8Sy12KTPvT'
80 | 'mWn5lle9mS/B2z9MJcaqOSqvC7TflRlkZZ7bM2vNVPFT/PXWJUv8ZO5hkiAQVkz5Wpat9dcVT'
81 | '/JXoNVv8Quoz3Wl43WZDU/x241V1vfq+UrRTFhLicyAxpecG1YTdXOqVLXP4XSRmcHCg/NIPG'
82 | 'AcnOs22uqdk4Vx777dfaaqp2uU+jPWGdkvcpeU7X8HLvXVP10pWJKOdSFksIMSgNXyWuofrpT'
83 | 'yyUKaewgxuCJeJW8ZuqnB6TxIATspkXGJ16r8vkHwMP7bvd6epx3m5/ny0V/uy1X4wamLaWVt'
84 | '+PeY7qfoQ8wG8wGvcKACjMGiDMsj/EDpApRB8gV0lhdKpSxulaoI7QKDQfoDfIAY4Cyyf4lc4'
85 | 'lsJaSV4FotYYDzCd69bC6BfYloU5XUQ88GeYBLA9JD+6BfqX0J1VZtGThVKD72i+cS3k+NUKv'
86 | 'WZkFbhMwfVMu+BOXYHy8lENqcaMuM2vyWp+WB2kJpoLrQNhOqI21Toa3HJAttw5c2fOKFtvGz'
87 | 'jrSNmWikbdAAI11WMw8U23L2HCkOdBkxUk8/msyyCVsj0IeAKAP9aI5R+yJ1+mZqPXVYqPc0f'
88 | 'jUSA82FZk9zmWNqo45hG5WfSB1lWOaCqDMwLDkTD/SXoQy0nTzPu5en52P9f4BO25jbLfTvl8'
89 | 'fjc4VWoDZ4fPu+e79/fdjVL7we0jC+cC63nJJ/7N/fHn88NHdM29xw+VUXOp+Mzm7FcPi6+Re'
90 | 'GcFi7')
91 |
--------------------------------------------------------------------------------
/scr/ReminderRepeatingAlarmReceiver.java:
--------------------------------------------------------------------------------
1 | package org.org.remindy;
2 |
3 | import android.content.BroadcastReceiver;
4 | import android.content.Intent;
5 | import android.content.Context;
6 | import android.app.NotificationChannel;
7 | import android.app.NotificationManager;
8 | import androidx.core.app.NotificationCompat;
9 | import androidx.core.app.NotificationManagerCompat;
10 | import android.app.Notification;
11 | import android.app.PendingIntent;
12 | import android.os.Build;
13 | import android.os.Bundle;
14 | import org.kivy.android.PythonActivity;
15 | import android.media.RingtoneManager;
16 | import android.net.Uri;
17 | import android.media.AudioAttributes;
18 | import org.remindy.remindy.R;
19 | import java.util.Calendar;
20 | import android.app.AlarmManager;
21 | import java.lang.Math;
22 |
23 | public class ReminderRepeatingAlarmReceiver extends BroadcastReceiver{
24 |
25 | private void createNotificationChannel(Context context) {
26 |
27 | if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
28 | Uri sound = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
29 |
30 | AudioAttributes att = new AudioAttributes.Builder()
31 | .setUsage(AudioAttributes.USAGE_NOTIFICATION)
32 | .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
33 | .build();
34 |
35 | CharSequence name = "New Reminder";
36 | String description = "New Reminder";
37 | int importance = NotificationManager.IMPORTANCE_HIGH;
38 | NotificationChannel channel = new NotificationChannel("REMINDY", name, importance);
39 | channel.setDescription(description);
40 | channel.setSound(sound, att);
41 | channel.enableLights(true);
42 | channel.enableVibration(true);
43 | NotificationManager notificationManager = context.getSystemService(NotificationManager.class);
44 | notificationManager.createNotificationChannel(channel);
45 | }
46 | }
47 |
48 | private void sendNotification(Context context, Intent intent) {
49 | Uri uri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
50 | int notification_id = (int)(Math.random()*(8000-1+1)+1);
51 | Intent newintent = new Intent(context, PythonActivity.class);
52 | Short id = intent.getShortExtra("IDENTIFICATION", (short) 0);
53 | String current_list = intent.getStringExtra("CURRENT_LIST");
54 | newintent.putExtra("LAUNCH_APP_WITH_REMINDER", id);
55 | newintent.putExtra("CURRENT_LIST",current_list);
56 | PendingIntent pendingintent = PendingIntent.getActivity(context,notification_id, newintent, PendingIntent.FLAG_ONE_SHOT);
57 |
58 | Intent mrkcomp = new Intent(context, ReminderMarkComp.class);
59 | mrkcomp.putExtra("CURRENT_LIST", current_list);
60 | mrkcomp.putExtra("IDENTIFICATION", intent.getExtras().getShort("IDENTIFICATION"));
61 | mrkcomp.putExtra("NOTIFICATION_ID", notification_id);
62 | mrkcomp.putExtra("INTENT_ID", intent.getExtras().getShort("INTENT_ID"));
63 |
64 | mrkcomp.setAction("org.org.remindy.MRKCOMP");
65 | PendingIntent pendingmrkcomp = PendingIntent.getBroadcast(context,notification_id,mrkcomp, PendingIntent.FLAG_ONE_SHOT);
66 | String title = "Mark As Complete";
67 | NotificationCompat.Action mrkcompaction = new NotificationCompat.Action.Builder( 0, title, pendingmrkcomp).build();
68 |
69 | Intent snooze = new Intent(context, ReminderSnooze.class);
70 | snooze.putExtra("TITLE", intent.getExtras().getString("TITLE"));
71 | snooze.putExtra("DESCRIPTION", intent.getExtras().getString("DESCRIPTION"));
72 | snooze.putExtra("IDENTIFICATION", intent.getExtras().getShort("IDENTIFICATION"));
73 | snooze.putExtra("NOTIFICATION_ID", notification_id);
74 | snooze.putExtra("INTENT_ID", intent.getExtras().getShort("INTENT_ID"));
75 | snooze.putExtra("CURRENT_LIST", current_list);
76 | PendingIntent pendingsnooze = PendingIntent.getBroadcast(context, notification_id, snooze, PendingIntent.FLAG_CANCEL_CURRENT);
77 | NotificationCompat.Action snoozeaction = new NotificationCompat.Action.Builder( 0, "Snooze for 10 mins", pendingsnooze).build();
78 |
79 | NotificationCompat.Builder builder = new NotificationCompat.Builder(context, "REMINDY")
80 | .setSmallIcon(R.drawable.ic_launcher)
81 | .setContentTitle(intent.getExtras().getString("TITLE"))
82 | .setContentText(intent.getExtras().getString("DESCRIPTION"))
83 | .setTicker("New Reminder")
84 | .setVibrate(new long[]{0, 300, 0, 400, 0, 500})
85 | .setSound(uri)
86 | .setAutoCancel(true)
87 | .setOnlyAlertOnce(false)
88 | .setPriority(NotificationCompat.PRIORITY_HIGH)
89 | .setContentIntent(pendingintent)
90 | .addAction(mrkcompaction)
91 | .addAction(snoozeaction);
92 |
93 | NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
94 | notificationManager.notify(192837, builder.build());
95 |
96 | // We then proceed to reschedule the alarm on the system level alarm manager
97 |
98 | PendingIntent newdaypending = PendingIntent.getBroadcast(context, intent.getExtras().getShort("INTENT_ID"), intent, PendingIntent.FLAG_CANCEL_CURRENT);
99 | Calendar calendar = Calendar.getInstance();
100 | Long timetoring = calendar.getTimeInMillis() + 7*24*60*60*1000;
101 | AlarmManager alarmManager=(AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
102 | alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,timetoring, newdaypending);
103 |
104 | }
105 |
106 |
107 |
108 | @Override
109 | public void onReceive(Context context, Intent intent) {
110 | this.createNotificationChannel(context);
111 | this.sendNotification(context, intent);
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/kivymd/utils/hot_reload_viewer.py:
--------------------------------------------------------------------------------
1 | """
2 | HotReloadViewer
3 | ===============
4 |
5 | .. Note:: The :class:`~HotReloadViewer` class is based on
6 | the `KvViewerApp `_ class
7 |
8 | :class:`~HotReloadViewer`, for KV-Viewer, is a simple tool allowing you to
9 | dynamically display a KV file, taking its changes into account
10 | (thanks to watchdog). The idea is to facilitate design using the KV language.
11 |
12 | Usage
13 | -----
14 |
15 | .. code-block:: python
16 |
17 | from kivy.lang import Builder
18 |
19 | from kivymd.app import MDApp
20 |
21 | KV = '''
22 | #:import KivyLexer kivy.extras.highlight.KivyLexer
23 | #:import HotReloadViewer kivymd.utils.hot_reload_viewer.HotReloadViewer
24 |
25 |
26 | BoxLayout:
27 |
28 | CodeInput:
29 | lexer: KivyLexer()
30 | style_name: "native"
31 | on_text: app.update_kv_file(self.text)
32 | size_hint_x: .7
33 |
34 | HotReloadViewer:
35 | size_hint_x: .3
36 | path: app.path_to_kv_file
37 | errors: True
38 | errors_text_color: 1, 1, 0, 1
39 | errors_background_color: app.theme_cls.bg_dark
40 | '''
41 |
42 |
43 | class Example(MDApp):
44 | path_to_kv_file = "kv_file.kv"
45 |
46 | def build(self):
47 | self.theme_cls.theme_style = "Dark"
48 | return Builder.load_string(KV)
49 |
50 | def update_kv_file(self, text):
51 | with open(self.path_to_kv_file, "w") as kv_file:
52 | kv_file.write(text)
53 |
54 |
55 | Example().run()
56 |
57 | This will display the test.kv and automatically update the display when the
58 | file changes.
59 |
60 | .. raw:: html
61 |
62 |
63 |
64 |
65 |
66 |
67 | .. rubric:: This scripts uses watchdog to listen for file changes. To install
68 | watchdog.
69 |
70 | .. code-block:: bash
71 |
72 | pip install watchdog
73 | """
74 |
75 | import os
76 |
77 | from kivy.clock import Clock, mainthread
78 | from kivy.lang import Builder
79 | from kivy.properties import BooleanProperty, ColorProperty, StringProperty
80 | from kivy.uix.scrollview import ScrollView
81 | from watchdog.events import FileSystemEventHandler
82 | from watchdog.observers import Observer
83 |
84 | from kivymd.theming import ThemableBehavior
85 | from kivymd.uix.boxlayout import MDBoxLayout
86 |
87 | Builder.load_string(
88 | """
89 |
90 |
91 | MDLabel:
92 | size_hint_y: None
93 | height: self.texture_size[1]
94 | theme_text_color: "Custom"
95 | text_color:
96 | root.errors_text_color if root.errors_text_color \
97 | else root.theme_cls.text_color
98 | text: root.text
99 | """
100 | )
101 |
102 |
103 | class HotReloadErrorText(ThemableBehavior, ScrollView):
104 | text = StringProperty()
105 | """Text errors.
106 |
107 | :attr:`text` is an :class:`~kivy.properties.StringProperty`
108 | and defaults to `''`.
109 | """
110 |
111 | errors_text_color = ColorProperty(None)
112 | """
113 | Error text color.
114 |
115 | :attr:`errors_text_color` is an :class:`~kivy.properties.ColorProperty`
116 | and defaults to `None`.
117 | """
118 |
119 |
120 | class HotReloadHandler(FileSystemEventHandler):
121 | def __init__(self, callback, target, **kwargs):
122 | super().__init__(**kwargs)
123 | self.callback = callback
124 | self.target = target
125 |
126 | def on_any_event(self, event):
127 | self.callback()
128 |
129 |
130 | class HotReloadViewer(ThemableBehavior, MDBoxLayout):
131 | """
132 | :Events:
133 | :attr:`on_error`
134 | Called when an error occurs in the KV-file that the user is editing.
135 | """
136 |
137 | path = StringProperty()
138 | """Path to KV file.
139 |
140 | :attr:`path` is an :class:`~kivy.properties.StringProperty`
141 | and defaults to `''`.
142 | """
143 |
144 | errors = BooleanProperty(False)
145 | """
146 | Show errors while editing KV-file.
147 |
148 | :attr:`errors` is an :class:`~kivy.properties.BooleanProperty`
149 | and defaults to `False`.
150 | """
151 |
152 | errors_background_color = ColorProperty(None)
153 | """
154 | Error background color.
155 |
156 | :attr:`errors_background_color` is an :class:`~kivy.properties.ColorProperty`
157 | and defaults to `None`.
158 | """
159 |
160 | errors_text_color = ColorProperty(None)
161 | """
162 | Error text color.
163 |
164 | :attr:`errors_text_color` is an :class:`~kivy.properties.ColorProperty`
165 | and defaults to `None`.
166 | """
167 |
168 | _temp_widget = None
169 |
170 | def __init__(self, **kwargs):
171 | self.observer = Observer()
172 | self.error_text = HotReloadErrorText()
173 | super().__init__(**kwargs)
174 | self.register_event_type("on_error")
175 |
176 | @mainthread
177 | def update(self, *args):
178 | """Updates and displays the KV-file that the user edits."""
179 |
180 | Builder.unload_file(self.path)
181 | self.clear_widgets()
182 | try:
183 | self.padding = (0, 0, 0, 0)
184 | self.md_bg_color = (0, 0, 0, 0)
185 | self._temp_widget = Builder.load_file(self.path)
186 | self.add_widget(self._temp_widget)
187 | except Exception as error:
188 | self.show_error(error)
189 | self.dispatch("on_error", error)
190 |
191 | def show_error(self, error):
192 | """Displays text with a current error."""
193 |
194 | if self._temp_widget and not self.errors:
195 | self.add_widget(self._temp_widget)
196 | return
197 | else:
198 | if self.errors_background_color:
199 | self.md_bg_color = self.errors_background_color
200 | self.padding = ("4dp", "4dp", "4dp", "4dp")
201 | self.error_text.text = (
202 | error.message
203 | if getattr(error, r"message", None)
204 | else str(error)
205 | )
206 | self.add_widget(self.error_text)
207 |
208 | def on_error(self, *args):
209 | """
210 | Called when an error occurs in the KV-file that the user is editing.
211 | """
212 |
213 | def on_errors_text_color(self, instance, value):
214 | self.error_text.errors_text_color = value
215 |
216 | def on_path(self, instance, value):
217 | value = os.path.abspath(value)
218 | self.observer.schedule(
219 | HotReloadHandler(self.update, value), os.path.dirname(value)
220 | )
221 | self.observer.start()
222 | Clock.schedule_once(self.update, 1)
223 |
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/toggle_behavior.py:
--------------------------------------------------------------------------------
1 | """
2 | Behaviors/ToggleButton
3 | ======================
4 |
5 | This behavior must always be inherited after the button's Widget class since it
6 | works with the inherited properties of the button class.
7 |
8 | example:
9 |
10 | .. code-block:: python
11 |
12 | class MyToggleButtonWidget(MDFlatButton, MDToggleButton):
13 | # [...]
14 | pass
15 |
16 |
17 | .. code-block:: python
18 |
19 | from kivy.lang import Builder
20 |
21 | from kivymd.app import MDApp
22 | from kivymd.uix.behaviors.toggle_behavior import MDToggleButton
23 | from kivymd.uix.button import MDRectangleFlatButton
24 |
25 | KV = '''
26 | Screen:
27 |
28 | MDBoxLayout:
29 | adaptive_size: True
30 | pos_hint: {"center_x": .5, "center_y": .5}
31 |
32 | MyToggleButton:
33 | text: "Show ads"
34 | group: "x"
35 |
36 | MyToggleButton:
37 | text: "Do not show ads"
38 | group: "x"
39 |
40 | MyToggleButton:
41 | text: "Does not matter"
42 | group: "x"
43 | '''
44 |
45 |
46 | class MyToggleButton(MDRectangleFlatButton, MDToggleButton):
47 | def __init__(self, **kwargs):
48 | super().__init__(**kwargs)
49 | self.background_down = self.theme_cls.primary_light
50 |
51 |
52 | class Test(MDApp):
53 | def build(self):
54 | return Builder.load_string(KV)
55 |
56 |
57 | Test().run()
58 |
59 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-1.gif
60 | :align: center
61 |
62 | .. code-block:: python
63 |
64 | class MyToggleButton(MDFillRoundFlatButton, MDToggleButton):
65 | def __init__(self, **kwargs):
66 | self.background_down = MDApp.get_running_app().theme_cls.primary_dark
67 | super().__init__(**kwargs)
68 |
69 | .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/toggle-button-2.gif
70 | :align: center
71 |
72 | You can inherit the ``MyToggleButton`` class only from the following classes
73 | ----------------------------------------------------------------------------
74 |
75 | - :class:`~kivymd.uix.button.MDRaisedButton`
76 | - :class:`~kivymd.uix.button.MDFlatButton`
77 | - :class:`~kivymd.uix.button.MDRectangleFlatButton`
78 | - :class:`~kivymd.uix.button.MDRectangleFlatIconButton`
79 | - :class:`~kivymd.uix.button.MDRoundFlatButton`
80 | - :class:`~kivymd.uix.button.MDRoundFlatIconButton`
81 | - :class:`~kivymd.uix.button.MDFillRoundFlatButton`
82 | - :class:`~kivymd.uix.button.MDFillRoundFlatIconButton`
83 | """
84 |
85 | __all__ = ("MDToggleButton",)
86 |
87 | from kivy.properties import BooleanProperty, ColorProperty
88 | from kivy.uix.behaviors import ToggleButtonBehavior
89 |
90 | from kivymd.uix.button import (
91 | MDFillRoundFlatButton,
92 | MDFillRoundFlatIconButton,
93 | MDFlatButton,
94 | MDRaisedButton,
95 | MDRectangleFlatButton,
96 | MDRectangleFlatIconButton,
97 | MDRoundFlatButton,
98 | MDRoundFlatIconButton,
99 | )
100 |
101 |
102 | class MDToggleButton(ToggleButtonBehavior):
103 | background_normal = ColorProperty(None)
104 | """
105 | Color of the button in ``rgba`` format for the 'normal' state.
106 |
107 | :attr:`background_normal` is a :class:`~kivy.properties.ColorProperty`
108 | and is defaults to `None`.
109 | """
110 |
111 | background_down = ColorProperty(None)
112 | """
113 | Color of the button in ``rgba`` format for the 'down' state.
114 |
115 | :attr:`background_down` is a :class:`~kivy.properties.ColorProperty`
116 | and is defaults to `None`.
117 | """
118 |
119 | font_color_normal = ColorProperty(None)
120 | """
121 | Color of the font's button in ``rgba`` format for the 'normal' state.
122 |
123 | :attr:`font_color_normal` is a :class:`~kivy.properties.ColorProperty`
124 | and is defaults to `None`.
125 | """
126 |
127 | font_color_down = ColorProperty([1, 1, 1, 1])
128 | """
129 | Color of the font's button in ``rgba`` format for the 'down' state.
130 |
131 | :attr:`font_color_down` is a :class:`~kivy.properties.ColorProperty`
132 | and is defaults to `[1, 1, 1, 1]`.
133 | """
134 |
135 | __is_filled = BooleanProperty(False)
136 |
137 | def __init__(self, **kwargs):
138 | super().__init__(**kwargs)
139 | classinfo = (
140 | MDRaisedButton,
141 | MDFlatButton,
142 | MDRectangleFlatButton,
143 | MDRectangleFlatIconButton,
144 | MDRoundFlatButton,
145 | MDRoundFlatIconButton,
146 | MDFillRoundFlatButton,
147 | MDFillRoundFlatIconButton,
148 | )
149 | # Do the object inherited from the "supported" buttons?
150 | if not issubclass(self.__class__, classinfo):
151 | raise ValueError(
152 | f"Class {self.__class__} must be inherited from one of the classes in the list {classinfo}"
153 | )
154 | if (
155 | not self.background_normal
156 | ): # This means that if the value == [] or None will return True.
157 | # If the object inherits from buttons with background:
158 | if isinstance(
159 | self,
160 | (
161 | MDRaisedButton,
162 | MDFillRoundFlatButton,
163 | MDFillRoundFlatIconButton,
164 | ),
165 | ):
166 | self.__is_filled = True
167 | self.background_normal = self.theme_cls.primary_color
168 | # If not the background_normal must be the same as the inherited one:
169 | else:
170 | self.background_normal = self.md_bg_color[:]
171 | # If no background_down is setted:
172 | if (
173 | not self.background_down
174 | ): # This means that if the value == [] or None will return True.
175 | self.background_down = (
176 | self.theme_cls.primary_dark
177 | ) # get the primary_color dark from theme_cls
178 | if not self.font_color_normal:
179 | self.font_color_normal = self.theme_cls.primary_color
180 | # Alternative to bind the function to the property.
181 | # self.bind(state=self._update_bg)
182 | self.fbind("state", self._update_bg)
183 |
184 | def _update_bg(self, ins, val):
185 | """Updates the color of the background."""
186 |
187 | if val == "down":
188 | self.md_bg_color = self.background_down
189 | if (
190 | self.__is_filled is False
191 | ): # If the background is transparent, and the button it toggled,
192 | # the font color must be withe [1, 1, 1, 1].
193 | self.text_color = self.font_color_down
194 | if self.group:
195 | self._release_group(self)
196 | else:
197 | self.md_bg_color = self.background_normal
198 | if (
199 | self.__is_filled is False
200 | ): # If the background is transparent, the font color must be the
201 | # primary color.
202 | self.text_color = self.font_color_normal
203 |
--------------------------------------------------------------------------------
/kivymd/uix/refreshlayout.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Refresh Layout
3 | =========================
4 |
5 | Example
6 | -------
7 |
8 | .. code-block:: python
9 |
10 | from kivymd.app import MDApp
11 | from kivy.clock import Clock
12 | from kivy.lang import Builder
13 | from kivy.factory import Factory
14 | from kivy.properties import StringProperty
15 |
16 | from kivymd.uix.button import MDIconButton
17 | from kivymd.icon_definitions import md_icons
18 | from kivymd.uix.list import ILeftBodyTouch, OneLineIconListItem
19 | from kivymd.theming import ThemeManager
20 | from kivymd.utils import asynckivy
21 |
22 | Builder.load_string('''
23 |
24 | text: root.text
25 |
26 | IconLeftSampleWidget:
27 | icon: root.icon
28 |
29 |
30 |
31 |
32 | BoxLayout:
33 | orientation: 'vertical'
34 |
35 | MDToolbar:
36 | title: app.title
37 | md_bg_color: app.theme_cls.primary_color
38 | background_palette: 'Primary'
39 | elevation: 10
40 | left_action_items: [['menu', lambda x: x]]
41 |
42 | MDScrollViewRefreshLayout:
43 | id: refresh_layout
44 | refresh_callback: app.refresh_callback
45 | root_layout: root
46 |
47 | MDGridLayout:
48 | id: box
49 | adaptive_height: True
50 | cols: 1
51 | ''')
52 |
53 |
54 | class IconLeftSampleWidget(ILeftBodyTouch, MDIconButton):
55 | pass
56 |
57 |
58 | class ItemForList(OneLineIconListItem):
59 | icon = StringProperty()
60 |
61 |
62 | class Example(MDApp):
63 | title = 'Example Refresh Layout'
64 | screen = None
65 | x = 0
66 | y = 15
67 |
68 | def build(self):
69 | self.screen = Factory.Example()
70 | self.set_list()
71 |
72 | return self.screen
73 |
74 | def set_list(self):
75 | async def set_list():
76 | names_icons_list = list(md_icons.keys())[self.x:self.y]
77 | for name_icon in names_icons_list:
78 | await asynckivy.sleep(0)
79 | self.screen.ids.box.add_widget(
80 | ItemForList(icon=name_icon, text=name_icon))
81 | asynckivy.start(set_list())
82 |
83 | def refresh_callback(self, *args):
84 | '''A method that updates the state of your application
85 | while the spinner remains on the screen.'''
86 |
87 | def refresh_callback(interval):
88 | self.screen.ids.box.clear_widgets()
89 | if self.x == 0:
90 | self.x, self.y = 15, 30
91 | else:
92 | self.x, self.y = 0, 15
93 | self.set_list()
94 | self.screen.ids.refresh_layout.refresh_done()
95 | self.tick = 0
96 |
97 | Clock.schedule_once(refresh_callback, 1)
98 |
99 |
100 | Example().run()
101 | """
102 |
103 | from kivy.animation import Animation
104 | from kivy.core.window import Window
105 | from kivy.effects.dampedscroll import DampedScrollEffect
106 | from kivy.lang import Builder
107 | from kivy.metrics import dp
108 | from kivy.properties import ColorProperty, NumericProperty, ObjectProperty
109 | from kivy.uix.floatlayout import FloatLayout
110 | from kivy.uix.scrollview import ScrollView
111 |
112 | from kivymd.theming import ThemableBehavior
113 |
114 | Builder.load_string(
115 | """
116 | #:import Window kivy.core.window.Window
117 |
118 |
119 |
120 |
121 | AnchorLayout:
122 | id: body_spinner
123 | size_hint: None, None
124 | size: dp(46), dp(46)
125 | y: Window.height
126 | pos_hint: {'center_x': .5}
127 | anchor_x: 'center'
128 | anchor_y: 'center'
129 |
130 | canvas:
131 | Clear
132 | Color:
133 | rgba: root.theme_cls.primary_dark
134 | Ellipse:
135 | pos: self.pos
136 | size: self.size
137 |
138 | MDSpinner:
139 | id: spinner
140 | size_hint: None, None
141 | size: dp(30), dp(30)
142 | color: 1, 1, 1, 1
143 | """
144 | )
145 |
146 |
147 | class _RefreshScrollEffect(DampedScrollEffect):
148 | """This class is simply based on DampedScrollEffect.
149 | If you need any documentation please look at kivy.effects.dampedscrolleffect.
150 | """
151 |
152 | min_scroll_to_reload = NumericProperty("-100dp")
153 | """Minimum overscroll value to reload."""
154 |
155 | def on_overscroll(self, scrollview, overscroll):
156 | if overscroll < self.min_scroll_to_reload:
157 | scroll_view = self.target_widget.parent
158 | scroll_view._did_overscroll = True
159 | return True
160 | else:
161 | return False
162 |
163 |
164 | class MDScrollViewRefreshLayout(ScrollView):
165 | root_layout = ObjectProperty()
166 | """The spinner will be attached to this layout."""
167 |
168 | def __init__(self, **kargs):
169 | super().__init__(**kargs)
170 | self.effect_cls = _RefreshScrollEffect
171 | self._work_spinnrer = False
172 | self._did_overscroll = False
173 | self.refresh_spinner = None
174 |
175 | def on_touch_up(self, *args):
176 | if self._did_overscroll and not self._work_spinnrer:
177 | if self.refresh_callback:
178 | self.refresh_callback()
179 | if not self.refresh_spinner:
180 | self.refresh_spinner = RefreshSpinner(_refresh_layout=self)
181 | self.root_layout.add_widget(self.refresh_spinner)
182 | self.refresh_spinner.start_anim_spinner()
183 | self._work_spinnrer = True
184 | self._did_overscroll = False
185 | return True
186 |
187 | return super().on_touch_up(*args)
188 |
189 | def refresh_done(self):
190 | if self.refresh_spinner:
191 | self.refresh_spinner.hide_anim_spinner()
192 |
193 |
194 | class RefreshSpinner(ThemableBehavior, FloatLayout):
195 | spinner_color = ColorProperty([1, 1, 1, 1])
196 |
197 | _refresh_layout = ObjectProperty()
198 | """kivymd.refreshlayout.MDScrollViewRefreshLayout object."""
199 |
200 | def start_anim_spinner(self):
201 | spinner = self.ids.body_spinner
202 | Animation(
203 | y=spinner.y - self.theme_cls.standard_increment * 2 + dp(10),
204 | d=0.8,
205 | t="out_elastic",
206 | ).start(spinner)
207 |
208 | def hide_anim_spinner(self):
209 | spinner = self.ids.body_spinner
210 | anim = Animation(y=Window.height, d=0.8, t="out_elastic")
211 | anim.bind(on_complete=self.set_spinner)
212 | anim.start(spinner)
213 |
214 | def set_spinner(self, *args):
215 | body_spinner = self.ids.body_spinner
216 | body_spinner.size = (dp(46), dp(46))
217 | body_spinner.y = Window.height
218 | body_spinner.opacity = 1
219 | spinner = self.ids.spinner
220 | spinner.size = (dp(30), dp(30))
221 | spinner.opacity = 1
222 | self._refresh_layout._work_spinnrer = False
223 | self._refresh_layout._did_overscroll = False
224 |
--------------------------------------------------------------------------------
/kivymd/uix/behaviors/backgroundcolor_behavior.py:
--------------------------------------------------------------------------------
1 | """
2 | Behaviors/Background Color
3 | ==========================
4 |
5 | .. note:: The following classes are intended for in-house use of the library.
6 | """
7 |
8 | __all__ = ("BackgroundColorBehavior", "SpecificBackgroundColorBehavior")
9 |
10 | from kivy.lang import Builder
11 | from kivy.properties import (
12 | BoundedNumericProperty,
13 | ColorProperty,
14 | ListProperty,
15 | NumericProperty,
16 | OptionProperty,
17 | ReferenceListProperty,
18 | StringProperty,
19 | VariableListProperty,
20 | )
21 | from kivy.utils import get_color_from_hex
22 |
23 | from kivymd.color_definitions import hue, palette, text_colors
24 |
25 | from .elevation import CommonElevationBehavior
26 |
27 | Builder.load_string(
28 | """
29 | #:import RelativeLayout kivy.uix.relativelayout.RelativeLayout
30 |
31 |
32 |
33 | canvas.before:
34 | PushMatrix
35 | Rotate:
36 | angle: self.angle
37 | origin: self._background_origin
38 | Color:
39 | rgba: self.md_bg_color
40 | RoundedRectangle:
41 | group: "Background_instruction"
42 | size: self.size
43 | pos: self.pos if not isinstance(self, RelativeLayout) else (0, 0)
44 | radius: root.radius
45 | source: root.background
46 | PopMatrix
47 | """,
48 | filename="BackgroundColorBehavior.kv",
49 | )
50 |
51 |
52 | class BackgroundColorBehavior(CommonElevationBehavior):
53 | background = StringProperty()
54 | """
55 | Background image path.
56 |
57 | :attr:`background` is a :class:`~kivy.properties.StringProperty`
58 | and defaults to `None`.
59 | """
60 |
61 | r = BoundedNumericProperty(1.0, min=0.0, max=1.0)
62 | """
63 | The value of ``red`` in the ``rgba`` palette.
64 |
65 | :attr:`r` is an :class:`~kivy.properties.BoundedNumericProperty`
66 | and defaults to `1.0`.
67 | """
68 |
69 | g = BoundedNumericProperty(1.0, min=0.0, max=1.0)
70 | """
71 | The value of ``green`` in the ``rgba`` palette.
72 |
73 | :attr:`g` is an :class:`~kivy.properties.BoundedNumericProperty`
74 | and defaults to `1.0`.
75 | """
76 |
77 | b = BoundedNumericProperty(1.0, min=0.0, max=1.0)
78 | """
79 | The value of ``blue`` in the ``rgba`` palette.
80 |
81 | :attr:`b` is an :class:`~kivy.properties.BoundedNumericProperty`
82 | and defaults to `1.0`.
83 | """
84 |
85 | a = BoundedNumericProperty(0.0, min=0.0, max=1.0)
86 | """
87 | The value of ``alpha channel`` in the ``rgba`` palette.
88 |
89 | :attr:`a` is an :class:`~kivy.properties.BoundedNumericProperty`
90 | and defaults to `0.0`.
91 | """
92 |
93 | radius = VariableListProperty([0], length=4)
94 | """
95 | Canvas radius.
96 |
97 | .. code-block:: python
98 |
99 | # Top left corner slice.
100 | MDBoxLayout:
101 | md_bg_color: app.theme_cls.primary_color
102 | radius: [25, 0, 0, 0]
103 |
104 | :attr:`radius` is an :class:`~kivy.properties.VariableListProperty`
105 | and defaults to `[0, 0, 0, 0]`.
106 | """
107 |
108 | md_bg_color = ReferenceListProperty(r, g, b, a)
109 | """
110 | The background color of the widget (:class:`~kivy.uix.widget.Widget`)
111 | that will be inherited from the :attr:`BackgroundColorBehavior` class.
112 |
113 | For example:
114 |
115 | .. code-block:: kv
116 |
117 | Widget:
118 | canvas:
119 | Color:
120 | rgba: 0, 1, 1, 1
121 | Rectangle:
122 | size: self.size
123 | pos: self.pos
124 |
125 | similar to code:
126 |
127 | .. code-block:: kv
128 |
129 |
130 | md_bg_color: 0, 1, 1, 1
131 |
132 | :attr:`md_bg_color` is an :class:`~kivy.properties.ReferenceListProperty`
133 | and defaults to :attr:`r`, :attr:`g`, :attr:`b`, :attr:`a`.
134 | """
135 |
136 | angle = NumericProperty(0)
137 | background_origin = ListProperty(None)
138 |
139 | _background_x = NumericProperty(0)
140 | _background_y = NumericProperty(0)
141 | _background_origin = ReferenceListProperty(
142 | _background_x,
143 | _background_y,
144 | )
145 |
146 | def __init__(self, **kwarg):
147 | super().__init__(**kwarg)
148 | self.bind(pos=self.update_background_origin)
149 |
150 | def update_background_origin(self, *args):
151 | if self.background_origin:
152 | self._background_origin = self.background_origin
153 | else:
154 | self._background_origin = self.center
155 |
156 |
157 | class SpecificBackgroundColorBehavior(BackgroundColorBehavior):
158 | background_palette = OptionProperty(
159 | "Primary", options=["Primary", "Accent", *palette]
160 | )
161 | """
162 | See :attr:`kivymd.color_definitions.palette`.
163 |
164 | :attr:`background_palette` is an :class:`~kivy.properties.OptionProperty`
165 | and defaults to `'Primary'`.
166 | """
167 |
168 | background_hue = OptionProperty("500", options=hue)
169 | """
170 | See :attr:`kivymd.color_definitions.hue`.
171 |
172 | :attr:`background_hue` is an :class:`~kivy.properties.OptionProperty`
173 | and defaults to `'500'`.
174 | """
175 |
176 | specific_text_color = ColorProperty([0, 0, 0, 0.87])
177 | """
178 | :attr:`specific_text_color` is an :class:`~kivy.properties.ColorProperty`
179 | and defaults to `[0, 0, 0, 0.87]`.
180 | """
181 |
182 | specific_secondary_text_color = ColorProperty([0, 0, 0, 0.87])
183 | """
184 | :attr:`specific_secondary_text_color`is an :class:`~kivy.properties.ColorProperty`
185 | and defaults to `[0, 0, 0, 0.87]`.
186 | """
187 |
188 | def __init__(self, **kwargs):
189 | super().__init__(**kwargs)
190 | if hasattr(self, "theme_cls"):
191 | self.theme_cls.bind(
192 | primary_palette=self._update_specific_text_color
193 | )
194 | self.theme_cls.bind(accent_palette=self._update_specific_text_color)
195 | self.theme_cls.bind(theme_style=self._update_specific_text_color)
196 | self.bind(background_hue=self._update_specific_text_color)
197 | self.bind(background_palette=self._update_specific_text_color)
198 | self._update_specific_text_color(None, None)
199 |
200 | def _update_specific_text_color(self, instance, value):
201 | if hasattr(self, "theme_cls"):
202 | palette = {
203 | "Primary": self.theme_cls.primary_palette,
204 | "Accent": self.theme_cls.accent_palette,
205 | }.get(self.background_palette, self.background_palette)
206 | else:
207 | palette = {"Primary": "Blue", "Accent": "Amber"}.get(
208 | self.background_palette, self.background_palette
209 | )
210 | color = get_color_from_hex(text_colors[palette][self.background_hue])
211 | secondary_color = color[:]
212 | # Check for black text (need to adjust opacity).
213 | if (color[0] + color[1] + color[2]) == 0:
214 | color[3] = 0.87
215 | secondary_color[3] = 0.54
216 | else:
217 | secondary_color[3] = 0.7
218 | self.specific_text_color = color
219 | self.specific_secondary_text_color = secondary_color
220 |
--------------------------------------------------------------------------------
/kivymd/uix/carousel.py:
--------------------------------------------------------------------------------
1 | """
2 | Components/Carousel
3 | =====================
4 |
5 | :class:`~kivy.uix.boxlayout.Carousel` class equivalent. Simplifies working
6 | with some widget properties. For example:
7 |
8 |
9 | Carousel
10 | ---------
11 |
12 | .. code-block:: python
13 |
14 | kv='''
15 | YourCarousel:
16 | BoxLayout:
17 | [...]
18 | BoxLayout:
19 | [...]
20 | BoxLayout:
21 | [...]
22 | '''
23 | builder.load_string(kv)
24 |
25 | class YourCarousel(Carousel):
26 | def __init__(self,*kwargs):
27 | self.register_event_type("on_slide_progress")
28 | self.register_event_type("on_slide_complete")
29 |
30 | def on_touch_down(self, *args):
31 | ["Code to detect when the slide changes"]
32 |
33 | def on_touch_up(self, *args):
34 | ["Code to detect when the slide changes"]
35 |
36 | def Calculate_slide_pos(self, *args):
37 | ["Code to calculate the current position of the slide"]
38 |
39 | def do_custom_animation(self, *args)
40 | ["Code to recreate an animation"]
41 |
42 |
43 | MDCarousel
44 | -----------
45 |
46 | .. code-block:: kv
47 |
48 | MDCarousel:
49 | on_slide_progress:
50 | do_something()
51 | on_slide_complete:
52 | do_something()
53 |
54 | """
55 | # TODO: Add documentation.
56 |
57 | from kivy.animation import Animation
58 | from kivy.uix.carousel import Carousel
59 |
60 |
61 | class MDCarousel(Carousel):
62 | """
63 | based on kivy's carousel.
64 |
65 | .. seealso::
66 | `kivy.uix.carousel.Carousel `_
67 | """
68 |
69 | _scrolling = False
70 |
71 | def __init__(self, **kwargs):
72 | super().__init__(**kwargs)
73 | self.register_event_type("on_slide_progress")
74 | self.register_event_type("on_slide_complete")
75 |
76 | def on_slide_progress(self, *args):
77 | """
78 | Event launched when the Slide animation is progress.
79 | rememebr to bind and unbid to this method.
80 | """
81 | pass
82 |
83 | def on_slide_complete(self, *args):
84 | """
85 | Event launched when the Slide animation is complete.
86 | rememebr to bind and unbid to this method.
87 | """
88 | pass
89 |
90 | def _position_visible_slides(self, *args):
91 | slides, index = self.slides, self.index
92 | no_of_slides = len(slides) - 1
93 | if not slides:
94 | return
95 | x, y, width, height = self.x, self.y, self.width, self.height
96 | _offset, direction = self._offset, self.direction
97 | _prev, _next, _current = self._prev, self._next, self._current
98 | get_slide_container = self.get_slide_container
99 | last_slide = get_slide_container(slides[-1])
100 | first_slide = get_slide_container(slides[0])
101 | skip_next = False
102 | _loop = self.loop
103 |
104 | if direction[0] in ["r", "l"]:
105 | xoff = x + _offset
106 | x_prev = {"l": xoff + width, "r": xoff - width}
107 | x_next = {"l": xoff - width, "r": xoff + width}
108 | if _prev:
109 | _prev.pos = (x_prev[direction[0]], y)
110 | elif _loop and _next and index == 0:
111 | if (_offset > 0 and direction[0] == "r") or (
112 | _offset < 0 and direction[0] == "l"
113 | ):
114 | last_slide.pos = (x_prev[direction[0]], y)
115 | skip_next = True
116 | if _current:
117 | _current.pos = (xoff, y)
118 |
119 | if self._scrolling:
120 | self.dispatch("on_slide_progress", (xoff, y))
121 |
122 | if skip_next:
123 | return
124 | if _next:
125 | _next.pos = (x_next[direction[0]], y)
126 | elif _loop and _prev and index == no_of_slides:
127 | if (_offset < 0 and direction[0] == "r") or (
128 | _offset > 0 and direction[0] == "l"
129 | ):
130 | first_slide.pos = (x_next[direction[0]], y)
131 | if direction[0] in ["t", "b"]:
132 | yoff = y + _offset
133 | y_prev = {"t": yoff - height, "b": yoff + height}
134 | y_next = {"t": yoff + height, "b": yoff - height}
135 | if _prev:
136 | _prev.pos = (x, y_prev[direction[0]])
137 | elif _loop and _next and index == 0:
138 | if (_offset > 0 and direction[0] == "t") or (
139 | _offset < 0 and direction[0] == "b"
140 | ):
141 | last_slide.pos = (x, y_prev[direction[0]])
142 | skip_next = True
143 | if _current:
144 | _current.pos = (x, yoff)
145 | if skip_next:
146 | return
147 | if _next:
148 | _next.pos = (x, y_next[direction[0]])
149 | elif _loop and _prev and index == no_of_slides:
150 | if (_offset < 0 and direction[0] == "t") or (
151 | _offset > 0 and direction[0] == "b"
152 | ):
153 | first_slide.pos = (x, y_next[direction[0]])
154 |
155 | def on_touch_down(self, touch):
156 | self._scrolling = True
157 | return super().on_touch_down(touch)
158 |
159 | def on_touch_up(self, touch):
160 | self._scrolling = False
161 | return super().on_touch_up(touch)
162 |
163 | def _start_animation(self, *args, **kwargs):
164 | # compute target offset for ease back, next or prev
165 | new_offset = 0
166 | direction = kwargs.get("direction", self.direction)[0]
167 | is_horizontal = direction in "rl"
168 | extent = self.width if is_horizontal else self.height
169 | min_move = kwargs.get("min_move", self.min_move)
170 | _offset = kwargs.get("offset", self._offset)
171 |
172 | if _offset < min_move * -extent:
173 | new_offset = -extent
174 | elif _offset > min_move * extent:
175 | new_offset = extent
176 |
177 | # if new_offset is 0, it wasnt enough to go next/prev
178 | dur = self.anim_move_duration
179 | if new_offset == 0:
180 | dur = self.anim_cancel_duration
181 |
182 | # detect edge cases if not looping
183 | len_slides = len(self.slides)
184 | index = self.index
185 | if not self.loop or len_slides == 1:
186 | is_first = index == 0
187 | is_last = index == len_slides - 1
188 | if direction in "rt":
189 | towards_prev = new_offset > 0
190 | towards_next = new_offset < 0
191 | else:
192 | towards_prev = new_offset < 0
193 | towards_next = new_offset > 0
194 | if (is_first and towards_prev) or (is_last and towards_next):
195 | new_offset = 0
196 |
197 | anim = Animation(_offset=new_offset, d=dur, t=self.anim_type)
198 | anim.cancel_all(self)
199 |
200 | def _cmp(*args):
201 | self.dispatch(
202 | "on_slide_complete",
203 | self.previous_slide,
204 | self.current_slide,
205 | self.next_slide,
206 | )
207 | if self._skip_slide is not None:
208 | self.index = self._skip_slide
209 | self._skip_slide = None
210 |
211 | anim.bind(on_complete=_cmp)
212 | anim.start(self)
213 |
--------------------------------------------------------------------------------