working condition
This commit is contained in:
parent
417e54da96
commit
511e0b0379
Binary file not shown.
@ -1,13 +1,13 @@
|
||||
[app]
|
||||
|
||||
# (str) Title of your application
|
||||
title = My Application
|
||||
title = Uptime Check
|
||||
|
||||
# (str) Package name
|
||||
package.name = myapp
|
||||
package.name = uptimecheck
|
||||
|
||||
# (str) Package domain (needed for android/ios packaging)
|
||||
package.domain = org.test
|
||||
package.domain = local.meko
|
||||
|
||||
# (str) Source code where the main.py live
|
||||
source.dir = .
|
||||
@ -37,7 +37,7 @@ version = 0.1
|
||||
|
||||
# (list) Application requirements
|
||||
# comma separated e.g. requirements = sqlite3,kivy
|
||||
requirements = python3,kivy
|
||||
requirements = python3,kivy,requests
|
||||
|
||||
# (str) Custom source folders for requirements
|
||||
# Sets custom source for any requirements with recipes
|
||||
|
Binary file not shown.
@ -0,0 +1,7 @@
|
||||
Copyright 2020 Nattōsai Mitō
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,57 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: asyncgui
|
||||
Version: 0.6.3
|
||||
Summary: A thin layer that helps to wrap a callback-style API in an async/await-style API
|
||||
Home-page: https://github.com/gottadiveintopython/asyncgui
|
||||
License: MIT
|
||||
Keywords: async
|
||||
Author: Nattōsai Mitō
|
||||
Author-email: flow4re2c@gmail.com
|
||||
Requires-Python: >=3.8.1,<4.0.0
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Programming Language :: Python :: 3.8
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Requires-Dist: exceptiongroup (>=1.0.4,<2.0.0) ; python_version < "3.11"
|
||||
Project-URL: Repository, https://github.com/gottadiveintopython/asyncgui
|
||||
Description-Content-Type: text/markdown
|
||||
|
||||
# AsyncGui
|
||||
|
||||
A thin layer that helps to wrap a callback-style API in an async/await-style API.
|
||||
|
||||
An async library that focuses on fast reaction.
|
||||
|
||||
[Documentation](https://asyncgui.github.io/asyncgui/)
|
||||
|
||||
## Installation
|
||||
|
||||
Pin the minor version.
|
||||
|
||||
```text
|
||||
poetry add asyncgui@~0.6
|
||||
pip install "asyncgui>=0.6,<0.7"
|
||||
```
|
||||
|
||||
## Tested on
|
||||
|
||||
- CPython 3.8
|
||||
- CPython 3.9
|
||||
- CPython 3.10
|
||||
- CPython 3.11
|
||||
- CPython 3.12 (3.12.1 or later)
|
||||
|
||||
## Async libraries that rely on this
|
||||
|
||||
- [asynckivy](https://github.com/asyncgui/asynckivy)
|
||||
- [asynctkinter](https://github.com/asyncgui/asynctkinter)
|
||||
- [asyncpygame](https://github.com/asyncgui/asyncpygame)
|
||||
|
@ -0,0 +1,7 @@
|
||||
__pycache__/asyncgui.cpython-311.pyc,,
|
||||
asyncgui-0.6.3.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
asyncgui-0.6.3.dist-info/LICENSE,sha256=zdEfMrLu9-uJk1Y-D7fn_gqgODq71StrNs47LvNE5b0,1055
|
||||
asyncgui-0.6.3.dist-info/METADATA,sha256=OTiDgXiKJm39p7OP5DZQ6ZtiY6UU2tawUD1QfFIvbFs,1729
|
||||
asyncgui-0.6.3.dist-info/RECORD,,
|
||||
asyncgui-0.6.3.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
|
||||
asyncgui.py,sha256=89sbdDMVyRooyYsy7IqG7cLm8DJVY5U67K1kYQngBGE,27963
|
@ -0,0 +1,4 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: poetry-core 1.6.1
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
945
kivy_venv/lib/python3.11/site-packages/asyncgui.py
Normal file
945
kivy_venv/lib/python3.11/site-packages/asyncgui.py
Normal file
@ -0,0 +1,945 @@
|
||||
__all__ = (
|
||||
# core (exceptions)
|
||||
'ExceptionGroup', 'BaseExceptionGroup', 'InvalidStateError', 'Cancelled',
|
||||
|
||||
# core
|
||||
'Aw_or_Task', 'start', 'Task', 'TaskState', 'disable_cancellation', 'open_cancel_scope', 'CancelScope',
|
||||
'dummy_task', 'current_task', '_current_task', 'sleep_forever', '_sleep_forever',
|
||||
|
||||
# structured concurrency
|
||||
'wait_all', 'wait_any', 'and_', 'or_', 'wait_all_cm', 'wait_any_cm', 'move_on_when',
|
||||
'run_as_main', 'run_as_daemon',
|
||||
'open_nursery', 'Nursery',
|
||||
|
||||
# bridge between async-world and sync-world
|
||||
'AsyncBox', 'AsyncEvent',
|
||||
|
||||
# deprecated
|
||||
'Event', 'run_as_primary', 'run_as_secondary',
|
||||
)
|
||||
import types
|
||||
import typing as T
|
||||
from inspect import getcoroutinestate, CORO_CREATED, CORO_SUSPENDED, isawaitable
|
||||
import sys
|
||||
import itertools
|
||||
from functools import cached_property, partial
|
||||
import enum
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Core
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
if sys.version_info < (3, 11):
|
||||
from exceptiongroup import BaseExceptionGroup, ExceptionGroup
|
||||
else:
|
||||
BaseExceptionGroup = BaseExceptionGroup #: :meta private:
|
||||
ExceptionGroup = ExceptionGroup #: :meta private:
|
||||
|
||||
potential_bug_msg = \
|
||||
r"This may be a bug of this library. Please make a minimal code that reproduces the bug, and open an issue at " \
|
||||
r"the GitHub repository, then post the code there. (https://github.com/asyncgui/asyncgui)."
|
||||
|
||||
|
||||
class InvalidStateError(Exception):
|
||||
"""The operation is not allowed in the current state."""
|
||||
|
||||
|
||||
class _Cancelled(BaseException):
|
||||
@cached_property
|
||||
def level(self) -> int:
|
||||
return self.args[0]
|
||||
|
||||
|
||||
Cancelled = (_Cancelled, GeneratorExit, )
|
||||
'''
|
||||
Exception class that represents cancellation.
|
||||
See :ref:`dealing-with-cancellation`.
|
||||
|
||||
.. warning::
|
||||
|
||||
Actually, this is not an exception class but a tuple of exception classes for now.
|
||||
But that's an implementation detail, and it might become an actual class in the future;
|
||||
therefore, your code must be compatible in both cases.
|
||||
|
||||
:meta hide-value:
|
||||
'''
|
||||
|
||||
|
||||
class TaskState(enum.Enum):
|
||||
'''
|
||||
Enum class that represents the Task state.
|
||||
'''
|
||||
|
||||
CREATED = enum.auto()
|
||||
'''
|
||||
Waiting to start execution.
|
||||
|
||||
:meta hide-value:
|
||||
'''
|
||||
|
||||
STARTED = enum.auto()
|
||||
'''
|
||||
Currently running or suspended.
|
||||
|
||||
:meta hide-value:
|
||||
'''
|
||||
|
||||
CANCELLED = enum.auto()
|
||||
'''
|
||||
The execution has been cancelled.
|
||||
The cause of cancellation can be either :meth:`Task.cancel` or an unhandled exception.
|
||||
|
||||
:meta hide-value:
|
||||
'''
|
||||
|
||||
FINISHED = enum.auto()
|
||||
'''
|
||||
The execution has been completed.
|
||||
|
||||
:meta hide-value:
|
||||
'''
|
||||
|
||||
|
||||
_next_Task_uid = itertools.count().__next__
|
||||
|
||||
|
||||
class Task:
|
||||
__slots__ = (
|
||||
'_uid', '_root_coro', '_state', '_result', '_on_end',
|
||||
'_exc_caught', '_suppresses_exc',
|
||||
'_cancel_disabled', '_cancel_depth', '_cancel_level',
|
||||
)
|
||||
|
||||
def __init__(self, aw: T.Awaitable, /):
|
||||
if not isawaitable(aw):
|
||||
raise ValueError(str(aw) + " is not awaitable.")
|
||||
self._uid = _next_Task_uid()
|
||||
self._cancel_disabled = 0
|
||||
self._root_coro = self._wrapper(aw)
|
||||
self._state = TaskState.CREATED
|
||||
self._on_end = None
|
||||
self._cancel_depth = 0
|
||||
self._cancel_level = None
|
||||
self._exc_caught = None
|
||||
self._suppresses_exc = False
|
||||
|
||||
def __str__(self):
|
||||
return f'Task(state={self._state.name}, uid={self._uid})'
|
||||
|
||||
@property
|
||||
def uid(self) -> int:
|
||||
'''
|
||||
An unique integer assigned to the task.
|
||||
This exists solely for inspection purposes.
|
||||
'''
|
||||
return self._uid
|
||||
|
||||
@property
|
||||
def root_coro(self) -> T.Coroutine:
|
||||
'''
|
||||
The starting point of the coroutine chain for the task.
|
||||
This exists solely for inspection purposes.
|
||||
'''
|
||||
return self._root_coro
|
||||
|
||||
@property
|
||||
def state(self) -> TaskState:
|
||||
'''
|
||||
The current state of the task.
|
||||
This exists solely for inspection purposes.
|
||||
'''
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def finished(self) -> bool:
|
||||
'''Whether the task has been completed.'''
|
||||
return self._state is TaskState.FINISHED
|
||||
|
||||
@property
|
||||
def cancelled(self) -> bool:
|
||||
'''Whether the task has been cancelled.'''
|
||||
return self._state is TaskState.CANCELLED
|
||||
|
||||
@property
|
||||
def result(self) -> T.Any:
|
||||
'''Result of the task. If the task is not finished, :exc:`InvalidStateError` will be raised. '''
|
||||
state = self._state
|
||||
if state is TaskState.FINISHED:
|
||||
return self._result
|
||||
elif state is TaskState.CANCELLED:
|
||||
raise InvalidStateError(f"{self} was cancelled")
|
||||
else:
|
||||
raise InvalidStateError(f"Result of {self} is not ready")
|
||||
|
||||
async def _wrapper(self, aw, /):
|
||||
try:
|
||||
self._state = TaskState.STARTED
|
||||
self._result = await aw
|
||||
except _Cancelled as e:
|
||||
self._state = TaskState.CANCELLED
|
||||
assert e.level == 0, potential_bug_msg
|
||||
assert self._cancel_level == 0, potential_bug_msg
|
||||
except Exception as e:
|
||||
self._state = TaskState.CANCELLED
|
||||
self._exc_caught = e
|
||||
if not self._suppresses_exc:
|
||||
raise
|
||||
except: # noqa: E722
|
||||
self._state = TaskState.CANCELLED
|
||||
raise
|
||||
else:
|
||||
self._state = TaskState.FINISHED
|
||||
finally:
|
||||
assert self._cancel_depth == 0, potential_bug_msg
|
||||
if (on_end := self._on_end) is not None:
|
||||
on_end(self)
|
||||
|
||||
def cancel(self, _level=0, /):
|
||||
'''Cancel the task as soon as possible.'''
|
||||
if self._cancel_level is None:
|
||||
self._cancel_level = _level
|
||||
state = getcoroutinestate(self._root_coro)
|
||||
if state is CORO_SUSPENDED:
|
||||
if not self._cancel_disabled:
|
||||
self._actual_cancel()
|
||||
elif state is CORO_CREATED:
|
||||
self._root_coro.close()
|
||||
self._state = TaskState.CANCELLED
|
||||
else:
|
||||
self._cancel_level = min(self._cancel_level, _level)
|
||||
|
||||
def _actual_cancel(self):
|
||||
try:
|
||||
self._root_coro.throw(_Cancelled(self._cancel_level))(self)
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
self._cancel_if_needed()
|
||||
|
||||
close = cancel
|
||||
'''An alias for :meth:`cancel`.'''
|
||||
|
||||
@property
|
||||
def _cancel_requested(self) -> bool:
|
||||
return self._cancel_level is not None
|
||||
|
||||
@property
|
||||
def _is_cancellable(self) -> bool:
|
||||
'''Whether the task can be cancelled immediately.'''
|
||||
return (not self._cancel_disabled) and getcoroutinestate(self._root_coro) is CORO_SUSPENDED
|
||||
|
||||
def _cancel_if_needed(self, getcoroutinestate=getcoroutinestate, CORO_SUSPENDED=CORO_SUSPENDED):
|
||||
if (self._cancel_level is None) or self._cancel_disabled or \
|
||||
(getcoroutinestate(self._root_coro) is not CORO_SUSPENDED):
|
||||
pass
|
||||
else:
|
||||
self._actual_cancel()
|
||||
|
||||
def _step(self, *args, **kwargs):
|
||||
coro = self._root_coro
|
||||
if getcoroutinestate(coro) is not CORO_SUSPENDED:
|
||||
return
|
||||
try:
|
||||
coro.send((args, kwargs, ))(self)
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
self._cancel_if_needed()
|
||||
|
||||
def _throw_exc(self, exc):
|
||||
'''停止中のTaskへ例外を投げる。Taskが停止中ではない場合は :exc:`InvalidStateError` が起こる。'''
|
||||
coro = self._root_coro
|
||||
if getcoroutinestate(coro) is not CORO_SUSPENDED:
|
||||
raise InvalidStateError("Throwing an exception to an unstarted/running/closed task is not allowed.")
|
||||
try:
|
||||
coro.throw(exc)(self)
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
self._cancel_if_needed()
|
||||
|
||||
|
||||
Aw_or_Task = T.Union[T.Awaitable, Task]
|
||||
|
||||
|
||||
def start(aw: Aw_or_Task, /) -> Task:
|
||||
'''*Immediately* start a Task/Awaitable.
|
||||
|
||||
If the argument is a :class:`Task`, itself will be returned. If it's an :class:`typing.Awaitable`,
|
||||
it will be wrapped in a Task, and that Task will be returned.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async def async_func():
|
||||
...
|
||||
|
||||
task = start(async_func())
|
||||
'''
|
||||
if isawaitable(aw):
|
||||
task = Task(aw)
|
||||
elif isinstance(aw, Task):
|
||||
task = aw
|
||||
if task._state is not TaskState.CREATED:
|
||||
raise ValueError(f"{task} has already started")
|
||||
else:
|
||||
raise ValueError("Argument must be either a Task or an awaitable.")
|
||||
|
||||
try:
|
||||
task._root_coro.send(None)(task)
|
||||
except StopIteration:
|
||||
pass
|
||||
else:
|
||||
task._cancel_if_needed()
|
||||
|
||||
return task
|
||||
|
||||
|
||||
class CancelScope:
|
||||
'''
|
||||
An equivalence of :class:`trio.CancelScope`.
|
||||
You should not directly instantiate this, use :func:`open_cancel_scope`.
|
||||
'''
|
||||
__slots__ = ('_task', '_level', 'cancelled_caught', 'cancel_called', )
|
||||
|
||||
def __init__(self, task: Task, /):
|
||||
self._task = task
|
||||
self.cancelled_caught = False #: Whether the scope caught a corresponding :class:`Cancelled` instance.
|
||||
self.cancel_called = False #: Whether the :meth:`cancel` has been called.
|
||||
|
||||
def __enter__(self) -> 'CancelScope':
|
||||
t = self._task
|
||||
t._cancel_depth = self._level = t._cancel_depth + 1
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc, __):
|
||||
# LOAD_FAST
|
||||
task = self._task
|
||||
level = task._cancel_level
|
||||
scope_level = self._level
|
||||
|
||||
self._task = None
|
||||
task._cancel_depth -= 1
|
||||
if level is not None:
|
||||
if level == scope_level:
|
||||
task._cancel_level = None
|
||||
else:
|
||||
assert level < scope_level, potential_bug_msg
|
||||
if exc_type is not _Cancelled:
|
||||
return
|
||||
level = exc.level
|
||||
if level == scope_level:
|
||||
self.cancelled_caught = True
|
||||
return True
|
||||
else:
|
||||
assert level < scope_level, potential_bug_msg
|
||||
|
||||
@property
|
||||
def closed(self) -> bool:
|
||||
'''
|
||||
Whether this scope has been closed.
|
||||
The cause of the closure of the scope can be either an exception occurred or the scope exited gracefully,
|
||||
'''
|
||||
return self._task is None
|
||||
|
||||
def cancel(self):
|
||||
'''Cancel the execution inside this scope as soon as possible. '''
|
||||
if self.cancel_called:
|
||||
return
|
||||
self.cancel_called = True
|
||||
if not self.closed:
|
||||
self._task.cancel(self._level)
|
||||
|
||||
|
||||
class open_cancel_scope:
|
||||
'''
|
||||
Same as :class:`trio.CancelScope` except this one returns an async context manager.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with open_cancel_scope() as scope:
|
||||
...
|
||||
'''
|
||||
__slots__ = ('_scope', )
|
||||
|
||||
async def __aenter__(self) -> T.Awaitable[CancelScope]:
|
||||
self._scope = CancelScope(await current_task())
|
||||
return self._scope.__enter__()
|
||||
|
||||
async def __aexit__(self, *args):
|
||||
return self._scope.__exit__(*args)
|
||||
|
||||
|
||||
def _current_task(task):
|
||||
return task._step(task)
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def current_task(_f=_current_task) -> T.Awaitable[Task]:
|
||||
'''Returns the Task instance corresponding to the caller.
|
||||
|
||||
.. code-block::
|
||||
|
||||
task = await current_task()
|
||||
'''
|
||||
return (yield _f)[0][0]
|
||||
|
||||
|
||||
class disable_cancellation:
|
||||
'''
|
||||
Return an async context manager that protects its code-block from cancellation.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with disable_cancellation():
|
||||
await something # <- never gets cancelled
|
||||
'''
|
||||
|
||||
__slots__ = ('_task', )
|
||||
|
||||
async def __aenter__(self):
|
||||
self._task = task = await current_task()
|
||||
task._cancel_disabled += 1
|
||||
|
||||
async def __aexit__(self, *__):
|
||||
self._task._cancel_disabled -= 1
|
||||
|
||||
|
||||
def _sleep_forever(task):
|
||||
pass
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def sleep_forever(_f=_sleep_forever) -> T.Awaitable:
|
||||
'''
|
||||
.. code-block::
|
||||
|
||||
await sleep_forever()
|
||||
'''
|
||||
yield _f
|
||||
|
||||
|
||||
dummy_task = Task(sleep_forever())
|
||||
'''
|
||||
An already closed task.
|
||||
This can be utilized to prevent the need for the common null validation mentioned below.
|
||||
|
||||
*Before:*
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3, 6,7
|
||||
|
||||
class MyClass:
|
||||
def __init__(self):
|
||||
self._task = None
|
||||
|
||||
def restart(self):
|
||||
if self._task is not None:
|
||||
self._task.cancel()
|
||||
self._task = asyncgui.start(self.main())
|
||||
|
||||
async def main(self):
|
||||
...
|
||||
|
||||
*After:*
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3, 6
|
||||
|
||||
class MyClass:
|
||||
def __init__(self):
|
||||
self._task = asyncgui.dummy_task
|
||||
|
||||
def restart(self):
|
||||
self._task.cancel()
|
||||
self._task = asyncgui.start(self.main())
|
||||
|
||||
async def main(self):
|
||||
...
|
||||
'''
|
||||
dummy_task.cancel()
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Bridge between async-world and sync-world
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class AsyncEvent:
|
||||
'''
|
||||
.. code-block::
|
||||
|
||||
async def async_fn(e):
|
||||
args, kwargs = await e.wait()
|
||||
assert args == (2, )
|
||||
assert kwargs == {'crow': 'raven', }
|
||||
|
||||
args, kwargs = await e.wait()
|
||||
assert args == (3, )
|
||||
assert kwargs == {'toad': 'frog', }
|
||||
|
||||
e = AsyncEvent()
|
||||
e.fire(1, crocodile='alligator')
|
||||
start(async_fn(e))
|
||||
e.fire(2, crow='raven')
|
||||
e.fire(3, toad='frog')
|
||||
|
||||
.. warning::
|
||||
|
||||
This class is not designed for inter-task synchronization, unlike :class:`asyncio.Event`.
|
||||
When multiple tasks simultaneously try to wait for the same event to fire, it will raise an exception.
|
||||
'''
|
||||
__slots__ = ('_callback', )
|
||||
|
||||
def __init__(self):
|
||||
self._callback = None
|
||||
|
||||
def fire(self, *args, **kwargs):
|
||||
if (f := self._callback) is not None:
|
||||
f(*args, **kwargs)
|
||||
|
||||
@types.coroutine
|
||||
def wait(self):
|
||||
if self._callback is not None:
|
||||
raise InvalidStateError("There's already a task waiting for the event to fire.")
|
||||
try:
|
||||
return (yield self._attach_task)
|
||||
finally:
|
||||
self._callback = None
|
||||
|
||||
def _attach_task(self, task):
|
||||
self._callback = task._step
|
||||
|
||||
|
||||
class AsyncBox:
|
||||
'''
|
||||
.. code-block::
|
||||
|
||||
async def async_fn(b1, b2):
|
||||
args, kwargs = await b1.get()
|
||||
assert args == (1, )
|
||||
assert kwargs == {'crow': 'raven', }
|
||||
|
||||
args, kwargs = await b2.get()
|
||||
assert args == (2, )
|
||||
assert kwargs == {'frog': 'toad', }
|
||||
|
||||
args, kwargs = await b1.get()
|
||||
assert args == (1, )
|
||||
assert kwargs == {'crow': 'raven', }
|
||||
|
||||
b1 = AsyncBox()
|
||||
b2 = AsyncBox()
|
||||
b1.put(1, crow='raven')
|
||||
start(async_fn(b1, b2))
|
||||
b2.put(2, frog='toad')
|
||||
|
||||
.. warning::
|
||||
|
||||
This class is not designed for inter-task synchronization, unlike :class:`asyncio.Event`.
|
||||
When multiple tasks simultaneously try to get an item from the same box, it will raise an exception.
|
||||
'''
|
||||
__slots__ = ('_item', '_callback', )
|
||||
|
||||
def __init__(self):
|
||||
self._item = None
|
||||
self._callback = None
|
||||
|
||||
@property
|
||||
def is_empty(self) -> bool:
|
||||
'''Whether the box is empty.'''
|
||||
return self._item is None
|
||||
|
||||
def put(self, *args, **kwargs):
|
||||
'''Put an item into the box if it's empty.'''
|
||||
if self._item is None:
|
||||
self.put_or_update(*args, **kwargs)
|
||||
|
||||
def update(self, *args, **kwargs):
|
||||
'''Replace the item in the box if there is one already.'''
|
||||
if self._item is not None:
|
||||
self.put_or_update(*args, **kwargs)
|
||||
|
||||
def put_or_update(self, *args, **kwargs):
|
||||
self._item = (args, kwargs, )
|
||||
if (callback := self._callback) is not None:
|
||||
callback(*args, **kwargs)
|
||||
|
||||
@types.coroutine
|
||||
def get(self):
|
||||
'''Get the item from the box if there is one. Otherwise, wait until it's put.'''
|
||||
if self._callback is not None:
|
||||
raise InvalidStateError("There's already a task waiting for an item to be put in the box.")
|
||||
if self._item is None:
|
||||
try:
|
||||
return (yield self._attach_task)
|
||||
finally:
|
||||
self._callback = None
|
||||
else:
|
||||
return self._item
|
||||
|
||||
def clear(self):
|
||||
'''Remove the item from the box if there is one.'''
|
||||
self._item = None
|
||||
|
||||
_attach_task = AsyncEvent._attach_task
|
||||
|
||||
|
||||
class Event:
|
||||
'''
|
||||
Similar to :class:`asyncio.Event`.
|
||||
The differences are:
|
||||
|
||||
* :meth:`set` accepts any number of arguments but doesn't use them at all so it can be used as a callback function
|
||||
in any library.
|
||||
* :attr:`is_set` is a property not a function.
|
||||
|
||||
.. code-block::
|
||||
|
||||
e = Event()
|
||||
any_library.register_callback(e.set)
|
||||
|
||||
.. deprecated:: 0.6.2
|
||||
|
||||
This class is deprecated, and will be removed before 1.0.0.
|
||||
Use :class:`asyncgui_ext.synctools.event.Event` instead.
|
||||
'''
|
||||
|
||||
__slots__ = ('_flag', '_waiting_tasks', )
|
||||
|
||||
def __init__(self):
|
||||
self._flag = False
|
||||
self._waiting_tasks = []
|
||||
|
||||
@property
|
||||
def is_set(self) -> bool:
|
||||
return self._flag
|
||||
|
||||
def set(self, *args, **kwargs):
|
||||
'''
|
||||
Set the event.
|
||||
Unlike asyncio's, all tasks waiting for this event to be set will be resumed *immediately*.
|
||||
'''
|
||||
if self._flag:
|
||||
return
|
||||
self._flag = True
|
||||
tasks = self._waiting_tasks
|
||||
self._waiting_tasks = []
|
||||
for t in tasks:
|
||||
if t is not None:
|
||||
t._step()
|
||||
|
||||
def clear(self):
|
||||
'''Unset the event.'''
|
||||
self._flag = False
|
||||
|
||||
@types.coroutine
|
||||
def wait(self) -> T.Awaitable:
|
||||
'''
|
||||
Wait for the event to be set.
|
||||
Return *immediately* if it's already set.
|
||||
'''
|
||||
if self._flag:
|
||||
return
|
||||
try:
|
||||
tasks = self._waiting_tasks
|
||||
idx = len(tasks)
|
||||
yield tasks.append
|
||||
finally:
|
||||
tasks[idx] = None
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Structured concurrency
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
class TaskCounter:
|
||||
'''
|
||||
(internal)
|
||||
数値が零になった事を通知する仕組みを持つカウンター。
|
||||
親taskが自分の子task達の終了を待つのに用いる。
|
||||
'''
|
||||
|
||||
__slots__ = ('_box', '_n_tasks', )
|
||||
|
||||
def __init__(self, initial=0, /):
|
||||
self._n_tasks = initial
|
||||
self._box = AsyncBox()
|
||||
|
||||
def increase(self):
|
||||
self._n_tasks += 1
|
||||
|
||||
def decrease(self):
|
||||
n = self._n_tasks - 1
|
||||
assert n >= 0, potential_bug_msg
|
||||
self._n_tasks = n
|
||||
if not n:
|
||||
self._box.put()
|
||||
|
||||
async def to_be_zero(self) -> T.Awaitable:
|
||||
if self._n_tasks:
|
||||
box = self._box
|
||||
box._item = None
|
||||
await box.get()
|
||||
|
||||
def __bool__(self):
|
||||
return not not self._n_tasks # 'not not' is not a typo
|
||||
|
||||
|
||||
async def _wait_xxx(debug_msg, on_child_end, *aws: T.Iterable[Aw_or_Task]) -> T.Awaitable[T.Sequence[Task]]:
|
||||
children = tuple(v if isinstance(v, Task) else Task(v) for v in aws)
|
||||
if not children:
|
||||
return children
|
||||
counter = TaskCounter(len(children))
|
||||
parent = await current_task()
|
||||
|
||||
try:
|
||||
with CancelScope(parent) as scope:
|
||||
on_child_end = partial(on_child_end, scope, counter)
|
||||
for c in children:
|
||||
c._suppresses_exc = True
|
||||
c._on_end = on_child_end
|
||||
start(c)
|
||||
await counter.to_be_zero()
|
||||
finally:
|
||||
if counter:
|
||||
for c in children:
|
||||
c.cancel()
|
||||
if counter:
|
||||
try:
|
||||
parent._cancel_disabled += 1
|
||||
await counter.to_be_zero()
|
||||
finally:
|
||||
parent._cancel_disabled -= 1
|
||||
exceptions = tuple(e for c in children if (e := c._exc_caught) is not None)
|
||||
if exceptions:
|
||||
raise ExceptionGroup(debug_msg, exceptions)
|
||||
if (parent._cancel_level is not None) and (not parent._cancel_disabled):
|
||||
await sleep_forever()
|
||||
assert False, potential_bug_msg
|
||||
return children
|
||||
|
||||
|
||||
def _on_child_end__ver_all(scope, counter, child):
|
||||
counter.decrease()
|
||||
if child._exc_caught is not None:
|
||||
scope.cancel()
|
||||
|
||||
|
||||
def _on_child_end__ver_any(scope, counter, child):
|
||||
counter.decrease()
|
||||
if child._exc_caught is not None or child.finished:
|
||||
scope.cancel()
|
||||
|
||||
|
||||
_wait_xxx_type = T.Callable[..., T.Awaitable[T.Sequence[Task]]]
|
||||
wait_all: _wait_xxx_type = partial(_wait_xxx, "wait_all()", _on_child_end__ver_all)
|
||||
'''
|
||||
Run multiple tasks concurrently, and wait for **all** of them to **end**. When any of them raises an exception, the
|
||||
others will be cancelled, and the exception will be propagated to the caller, like :class:`trio.Nursery`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
tasks = await wait_all(async_fn1(), async_fn2(), async_fn3())
|
||||
if tasks[0].finished:
|
||||
print("The return value of async_fn1() :", tasks[0].result)
|
||||
'''
|
||||
wait_any: _wait_xxx_type = partial(_wait_xxx, "wait_any()", _on_child_end__ver_any)
|
||||
'''
|
||||
Run multiple tasks concurrently, and wait for **any** of them to **finish**. As soon as that happens, the others will be
|
||||
cancelled. When any of them raises an exception, the others will be cancelled, and the exception will be propagated to
|
||||
the caller, like :class:`trio.Nursery`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
tasks = await wait_any(async_fn1(), async_fn2(), async_fn3())
|
||||
if tasks[0].finished:
|
||||
print("The return value of async_fn1() :", tasks[0].result)
|
||||
'''
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def _wait_xxx_cm(debug_msg, on_child_end, wait_bg, aw: Aw_or_Task):
|
||||
counter = TaskCounter(1)
|
||||
fg_task = await current_task()
|
||||
bg_task = aw if isinstance(aw, Task) else Task(aw)
|
||||
exc = None
|
||||
|
||||
try:
|
||||
with CancelScope(fg_task) as scope:
|
||||
bg_task._on_end = partial(on_child_end, scope, counter)
|
||||
bg_task._suppresses_exc = True
|
||||
yield start(bg_task)
|
||||
if wait_bg:
|
||||
await counter.to_be_zero()
|
||||
except Exception as e:
|
||||
exc = e
|
||||
finally:
|
||||
bg_task.cancel()
|
||||
if counter:
|
||||
try:
|
||||
fg_task._cancel_disabled += 1
|
||||
await counter.to_be_zero()
|
||||
finally:
|
||||
fg_task._cancel_disabled -= 1
|
||||
excs = tuple(
|
||||
e for e in (exc, bg_task._exc_caught, )
|
||||
if e is not None
|
||||
)
|
||||
if excs:
|
||||
raise ExceptionGroup(debug_msg, excs)
|
||||
if (fg_task._cancel_level is not None) and (not fg_task._cancel_disabled):
|
||||
await sleep_forever()
|
||||
assert False, potential_bug_msg
|
||||
|
||||
|
||||
_wait_xxx_cm_type = T.Callable[[Aw_or_Task], T.AsyncContextManager[Task]]
|
||||
wait_all_cm: _wait_xxx_cm_type = partial(_wait_xxx_cm, "wait_all_cm()", _on_child_end__ver_all, True)
|
||||
'''
|
||||
The context manager form of :func:`wait_all`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with wait_all_cm(async_fn()) as bg_task:
|
||||
...
|
||||
'''
|
||||
wait_any_cm: _wait_xxx_cm_type = partial(_wait_xxx_cm, "wait_any_cm()", _on_child_end__ver_any, False)
|
||||
'''
|
||||
The context manager form of :func:`wait_any`, an equivalence of :func:`trio_util.move_on_when`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with wait_any_cm(async_fn()) as bg_task:
|
||||
...
|
||||
'''
|
||||
run_as_main: _wait_xxx_cm_type = partial(_wait_xxx_cm, "run_as_main()", _on_child_end__ver_any, True)
|
||||
'''
|
||||
.. code-block::
|
||||
|
||||
async with run_as_main(async_fn()) as task:
|
||||
...
|
||||
|
||||
.. note::
|
||||
|
||||
You need to use its older name, ``run_as_primary``, if you are using ``asyncgui`` 0.6.2 or older.
|
||||
'''
|
||||
run_as_daemon: _wait_xxx_cm_type = partial(_wait_xxx_cm, "run_as_daemon()", _on_child_end__ver_all, False)
|
||||
'''
|
||||
.. code-block::
|
||||
|
||||
async with run_as_daemon(async_fn()) as bg_task:
|
||||
...
|
||||
'''
|
||||
|
||||
|
||||
class Nursery:
|
||||
'''
|
||||
Similar to :class:`trio.Nursery`.
|
||||
You should not directly instantiate this, use :func:`open_nursery`.
|
||||
'''
|
||||
|
||||
__slots__ = ('_closed', '_children', '_scope', '_counters', '_callbacks', '_gc_in_every', '_n_until_gc', )
|
||||
|
||||
def __init__(self, scope, counter, daemon_counter, gc_in_every):
|
||||
self._gc_in_every = self._n_until_gc = gc_in_every
|
||||
self._closed = False
|
||||
self._children = []
|
||||
self._scope = scope
|
||||
self._counters = (daemon_counter, counter, )
|
||||
self._callbacks = (
|
||||
partial(_on_child_end__ver_all, scope, daemon_counter),
|
||||
partial(_on_child_end__ver_all, scope, counter),
|
||||
)
|
||||
|
||||
def start(self, aw: Aw_or_Task, /, *, daemon=False) -> Task:
|
||||
'''
|
||||
*Immediately* start a Task/Awaitable under the supervision of the nursery.
|
||||
|
||||
If the argument is a :class:`Task`, itself will be returned. If it's an :class:`typing.Awaitable`,
|
||||
it will be wrapped in a Task, and that Task will be returned.
|
||||
|
||||
The ``daemon`` parameter acts like the one in the :mod:`threading` module.
|
||||
When only daemon tasks are left, they get cancelled, and the nursery closes.
|
||||
'''
|
||||
if self._closed:
|
||||
raise InvalidStateError("Nursery has been already closed")
|
||||
if not self._n_until_gc:
|
||||
self._collect_garbage()
|
||||
self._n_until_gc = self._gc_in_every
|
||||
self._n_until_gc -= 1
|
||||
child = aw if isinstance(aw, Task) else Task(aw)
|
||||
child._suppresses_exc = True
|
||||
child._on_end = self._callbacks[not daemon]
|
||||
self._counters[not daemon].increase()
|
||||
self._children.append(child)
|
||||
return start(child)
|
||||
|
||||
def _collect_garbage(self, STARTED=TaskState.STARTED):
|
||||
self._children = [
|
||||
c for c in self._children
|
||||
if c.state is STARTED or c._exc_caught is not None
|
||||
]
|
||||
|
||||
def close(self):
|
||||
'''Cancel all the child tasks in the nursery as soon as possible. '''
|
||||
self._closed = True
|
||||
self._scope.cancel()
|
||||
|
||||
@property
|
||||
def closed(self) -> bool:
|
||||
return self._closed
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def open_nursery(*, _gc_in_every=1000) -> T.AsyncIterator[Nursery]:
|
||||
'''
|
||||
Similar to :func:`trio.open_nursery`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with open_nursery() as nursery:
|
||||
nursery.start(async_fn1())
|
||||
nursery.start(async_fn2(), daemon=True)
|
||||
'''
|
||||
exc = None
|
||||
parent = await current_task()
|
||||
counter = TaskCounter()
|
||||
daemon_counter = TaskCounter()
|
||||
|
||||
try:
|
||||
with CancelScope(parent) as scope:
|
||||
nursery = Nursery(scope, counter, daemon_counter, _gc_in_every)
|
||||
yield nursery
|
||||
await counter.to_be_zero()
|
||||
except Exception as e:
|
||||
exc = e
|
||||
finally:
|
||||
nursery._closed = True
|
||||
children = nursery._children
|
||||
for c in children:
|
||||
c.cancel()
|
||||
try:
|
||||
parent._cancel_disabled += 1
|
||||
await daemon_counter.to_be_zero()
|
||||
await counter.to_be_zero()
|
||||
finally:
|
||||
parent._cancel_disabled -= 1
|
||||
excs = tuple(
|
||||
e for e in itertools.chain((exc, ), (c._exc_caught for c in children))
|
||||
if e is not None
|
||||
)
|
||||
if excs:
|
||||
raise ExceptionGroup("Nursery", excs)
|
||||
if (parent._cancel_level is not None) and (not parent._cancel_disabled):
|
||||
await sleep_forever()
|
||||
assert False, potential_bug_msg
|
||||
|
||||
|
||||
# -----------------------------------------------------------------------------
|
||||
# Aliases
|
||||
# -----------------------------------------------------------------------------
|
||||
run_as_primary = run_as_main
|
||||
run_as_secondary = run_as_daemon
|
||||
and_ = wait_all #: An alias for :func:`wait_all`.
|
||||
or_ = wait_any #: An alias for :func:`wait_any`.
|
||||
move_on_when = wait_any_cm #: An alias for :func:`wait_any_cm`.
|
@ -0,0 +1 @@
|
||||
pip
|
@ -0,0 +1,7 @@
|
||||
Copyright 2019 gottadiveintopython
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
@ -0,0 +1,177 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: asynckivy
|
||||
Version: 0.6.4
|
||||
Summary: Async library for Kivy
|
||||
Home-page: https://github.com/asyncgui/asynckivy
|
||||
License: MIT
|
||||
Keywords: async,kivy
|
||||
Author: Nattōsai Mitō
|
||||
Author-email: flow4re2c@gmail.com
|
||||
Requires-Python: >=3.9,<4.0
|
||||
Classifier: Development Status :: 5 - Production/Stable
|
||||
Classifier: Intended Audience :: Developers
|
||||
Classifier: License :: OSI Approved :: MIT License
|
||||
Classifier: Operating System :: OS Independent
|
||||
Classifier: Programming Language :: Python
|
||||
Classifier: Programming Language :: Python :: 3
|
||||
Classifier: Programming Language :: Python :: 3.9
|
||||
Classifier: Programming Language :: Python :: 3.10
|
||||
Classifier: Programming Language :: Python :: 3.11
|
||||
Classifier: Programming Language :: Python :: 3.12
|
||||
Classifier: Topic :: Software Development :: Libraries
|
||||
Requires-Dist: asyncgui (>=0.6,<0.7)
|
||||
Project-URL: Repository, https://github.com/asyncgui/asynckivy
|
||||
Description-Content-Type: text/markdown
|
||||
|
||||
# AsyncKivy
|
||||
|
||||
[Youtube](https://www.youtube.com/playlist?list=PLNdhqAjzeEGjTpmvNck4Uykps8s9LmRTJ)
|
||||
[日本語doc](README_jp.md)
|
||||
|
||||
`asynckivy` is an async library that saves you from ugly callback-style code,
|
||||
like most of async libraries do.
|
||||
Let's say you want to do:
|
||||
|
||||
1. `print('A')`
|
||||
1. wait for 1sec
|
||||
1. `print('B')`
|
||||
1. wait for a button to be pressed
|
||||
1. `print('C')`
|
||||
|
||||
in that order.
|
||||
Your code would look like this:
|
||||
|
||||
```python
|
||||
from kivy.clock import Clock
|
||||
|
||||
def what_you_want_to_do(button):
|
||||
print('A')
|
||||
|
||||
def one_sec_later(__):
|
||||
print('B')
|
||||
button.bind(on_press=on_button_press)
|
||||
Clock.schedule_once(one_sec_later, 1)
|
||||
|
||||
def on_button_press(button):
|
||||
button.unbind(on_press=on_button_press)
|
||||
print('C')
|
||||
|
||||
what_you_want_to_do(...)
|
||||
```
|
||||
|
||||
It's not easy to understand.
|
||||
If you use `asynckivy`, the code above will become:
|
||||
|
||||
```python
|
||||
import asynckivy as ak
|
||||
|
||||
async def what_you_want_to_do(button):
|
||||
print('A')
|
||||
await ak.sleep(1)
|
||||
print('B')
|
||||
await ak.event(button, 'on_press')
|
||||
print('C')
|
||||
|
||||
ak.start(what_you_want_to_do(...))
|
||||
```
|
||||
|
||||
## Installation
|
||||
|
||||
Pin the minor version.
|
||||
|
||||
```text
|
||||
poetry add asynckivy@~0.6
|
||||
pip install "asynckivy>=0.6,<0.7"
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
import asynckivy as ak
|
||||
|
||||
async def some_task(button):
|
||||
# waits for 2 seconds to elapse
|
||||
dt = await ak.sleep(2)
|
||||
print(f'{dt} seconds have elapsed')
|
||||
|
||||
# waits for a button to be pressed
|
||||
await ak.event(button, 'on_press')
|
||||
|
||||
# waits for the value of 'button.x' to change
|
||||
__, x = await ak.event(button, 'x')
|
||||
print(f'button.x is now {x}')
|
||||
|
||||
# waits for the value of 'button.x' to become greater than 100
|
||||
if button.x <= 100:
|
||||
__, x = await ak.event(button, 'x', filter=lambda __, x: x>100)
|
||||
print(f'button.x is now {x}')
|
||||
|
||||
# waits for either 5 seconds to elapse or a button to be pressed.
|
||||
# i.e. waits at most 5 seconds for a button to be pressed
|
||||
tasks = await ak.wait_any(
|
||||
ak.sleep(5),
|
||||
ak.event(button, 'on_press'),
|
||||
)
|
||||
print("Timeout" if tasks[0].finished else "The button was pressed")
|
||||
|
||||
# same as the above
|
||||
async with ak.move_on_after(5) as bg_task:
|
||||
await ak.event(button, 'on_press')
|
||||
print("Timeout" if bg_task.finished else "The button was pressed")
|
||||
|
||||
# waits for both 5 seconds to elapse and a button to be pressed.
|
||||
tasks = await ak.wait_all(
|
||||
ak.sleep(5),
|
||||
ak.event(button, 'on_press'),
|
||||
)
|
||||
|
||||
# nest as you want.
|
||||
# waits for a button to be pressed, and either 5 seconds to elapse or 'other_async_func' to complete.
|
||||
tasks = await ak.wait_all(
|
||||
ak.event(button, 'on_press'),
|
||||
ak.wait_any(
|
||||
ak.sleep(5),
|
||||
other_async_func(),
|
||||
),
|
||||
)
|
||||
child_tasks = tasks[1].result
|
||||
print("5 seconds elapsed" if child_tasks[0].finished else "other_async_func has completed")
|
||||
|
||||
ak.start(some_task(some_button))
|
||||
```
|
||||
|
||||
For more details, read the [documentation](https://asyncgui.github.io/asynckivy/).
|
||||
|
||||
## Tested on
|
||||
|
||||
- CPython 3.8 + Kivy 2.3.0
|
||||
- CPython 3.9 + Kivy 2.3.0
|
||||
- CPython 3.10 + Kivy 2.3.0
|
||||
- CPython 3.11 + Kivy 2.3.0
|
||||
- CPython 3.12 + Kivy 2.3.0 (3.12.0 is not supported due to [this issue](https://github.com/python/cpython/issues/111058))
|
||||
|
||||
## Why this even exists
|
||||
|
||||
Kivy supports two legitimate async libraries, [asyncio][asyncio] and [Trio][trio], starting from version 2.0.0, so developing another one seems like [reinventing the wheel][reinventing].
|
||||
Actually, I started this one just to learn how the async/await syntax works, so it initially was "reinventing the wheel".
|
||||
|
||||
But after playing with Trio and Kivy for a while, I noticed that Trio is not suitable for the situation where fast reactions are required e.g. touch events.
|
||||
The same is true of asyncio.
|
||||
You can confirm that by running `investigation/why_xxx_is_not_suitable_for_handling_touch_events.py`, and mashing a mouse button as quickly as possible.
|
||||
You'll see sometimes `up` is not paired with `down`.
|
||||
You'll see the coordinates aren't relative to the `RelativeLayout` even though the `target` belongs to it.
|
||||
|
||||
The cause of those problems is that `trio.Event.set()` and `asyncio.Event.set()` don't *immediately* resume the tasks waiting for the `Event` to be set.
|
||||
They just schedule the tasks to resume.
|
||||
Same thing can be said to `nursery.start_soon()` and `asyncio.create_task()`.
|
||||
|
||||
Trio and asyncio are async **I/O** libraries after all.
|
||||
They probably don't have to immediately resumes/starts tasks, which I think necessary for touch handling in Kivy.
|
||||
(If you fail to handle touches promptly, their state might undergo changes, leaving no time to wait for tasks to resume/start).
|
||||
Their core design might not be suitable for GUI in the first place.
|
||||
That's why I'm still developing this `asynckivy` library to this day.
|
||||
|
||||
[asyncio]:https://docs.python.org/3/library/asyncio.html
|
||||
[trio]:https://trio.readthedocs.io/en/stable/
|
||||
[reinventing]:https://en.wikipedia.org/wiki/Reinventing_the_wheel
|
||||
|
@ -0,0 +1,31 @@
|
||||
asynckivy-0.6.4.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
asynckivy-0.6.4.dist-info/LICENSE,sha256=2jxtLdIltPBFl7vb9bLmquYKRJiyidCvO_DhOgFWIe8,1059
|
||||
asynckivy-0.6.4.dist-info/METADATA,sha256=P3n9htW_NrrBuy5BHojYoUgkePfNn2y4h__APrwdK5w,5876
|
||||
asynckivy-0.6.4.dist-info/RECORD,,
|
||||
asynckivy-0.6.4.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
|
||||
asynckivy/__init__.py,sha256=Ttzd2FLPuQEAPrNINViuIK8Yj4i5swu2wKKkl0vCMoA,1285
|
||||
asynckivy/__pycache__/__init__.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_anim_attrs.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_anim_with_xxx.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_animation.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_event.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_exceptions.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_interpolate.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_n_frames.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_sleep.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_threading.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_touch.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/_utils.cpython-311.pyc,,
|
||||
asynckivy/__pycache__/vanim.cpython-311.pyc,,
|
||||
asynckivy/_anim_attrs.py,sha256=VCWAPMFtwZU4HOdfhcFDR1JIvjMDW-nuaSvn2MAnu3Q,3838
|
||||
asynckivy/_anim_with_xxx.py,sha256=IzJ-NYCJI9mFgOH1oRtZ0VLcsIY7TNjf88VuaoU9Lo4,3516
|
||||
asynckivy/_animation.py,sha256=6J2vwvXXJJegLk48nx4KrHYrZM5uZiulE6pTH4n9A4U,3589
|
||||
asynckivy/_event.py,sha256=_1O6bKZXZKkV5a-i4Qo3pmZHU1jCobf6bwIS9TUJG-U,1711
|
||||
asynckivy/_exceptions.py,sha256=Pg2qkGaVbF2OgVrfcxqOPobEgvavAPYr4RZRDtvyV-o,764
|
||||
asynckivy/_interpolate.py,sha256=ojjQhiND4-rkTol5q79R2eblXL-2XhQPQMzWovSkDoU,2252
|
||||
asynckivy/_n_frames.py,sha256=Rwtc-9nVBGT-IT5dRwQBowAS0ENBEnrzQKxVhPp4qoE,868
|
||||
asynckivy/_sleep.py,sha256=qiNN_4PUJiz8pxnLqUykHSLcZhSLuLnHnfekTTEKDWQ,3354
|
||||
asynckivy/_threading.py,sha256=onV5x3H0qfDYzHs3PRIprxlJR3dpSbdZWjjChRXI35E,1621
|
||||
asynckivy/_touch.py,sha256=C_Z3qoYNVPE-KWYrc56Q4Uj79sLK2V0L_6Pj6ZTdPYU,7669
|
||||
asynckivy/_utils.py,sha256=qr4__ywCImXrfNdxnxAfn7PLux1KGAwWud_Pzb9ixVo,7705
|
||||
asynckivy/vanim.py,sha256=-9kRfu3yJsKX8Z4xp8Wm6cOfUxzg54oeohUDV1FKktA,608
|
@ -0,0 +1,4 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: poetry-core 1.9.0
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
42
kivy_venv/lib/python3.11/site-packages/asynckivy/__init__.py
Normal file
42
kivy_venv/lib/python3.11/site-packages/asynckivy/__init__.py
Normal file
@ -0,0 +1,42 @@
|
||||
__all__ = (
|
||||
'MotionEventAlreadyEndedError',
|
||||
'anim_attrs',
|
||||
'anim_attrs_abbr',
|
||||
'anim_with_dt',
|
||||
'anim_with_dt_et',
|
||||
'anim_with_dt_et_ratio',
|
||||
'anim_with_et',
|
||||
'anim_with_ratio',
|
||||
'animate',
|
||||
'create_texture_from_text',
|
||||
'event',
|
||||
'fade_transition',
|
||||
'interpolate',
|
||||
'move_on_after',
|
||||
'n_frames',
|
||||
'repeat_sleeping',
|
||||
'rest_of_touch_events',
|
||||
'run_in_executor',
|
||||
'run_in_thread',
|
||||
'sleep',
|
||||
'sleep_free',
|
||||
'suppress_event',
|
||||
'sync_attr',
|
||||
'sync_attrs',
|
||||
'touch_up_event',
|
||||
'transform',
|
||||
'watch_touch',
|
||||
)
|
||||
|
||||
from asyncgui import *
|
||||
from ._exceptions import MotionEventAlreadyEndedError
|
||||
from ._sleep import sleep, sleep_free, repeat_sleeping, move_on_after
|
||||
from ._event import event
|
||||
from ._anim_with_xxx import anim_with_dt, anim_with_et, anim_with_ratio, anim_with_dt_et, anim_with_dt_et_ratio
|
||||
from ._animation import animate
|
||||
from ._anim_attrs import anim_attrs, anim_attrs_abbr
|
||||
from ._interpolate import interpolate, fade_transition
|
||||
from ._touch import watch_touch, rest_of_touch_events, rest_of_touch_moves, touch_up_event
|
||||
from ._threading import run_in_executor, run_in_thread
|
||||
from ._n_frames import n_frames
|
||||
from ._utils import transform, suppress_event, create_texture_from_text, sync_attr, sync_attrs
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
114
kivy_venv/lib/python3.11/site-packages/asynckivy/_anim_attrs.py
Normal file
114
kivy_venv/lib/python3.11/site-packages/asynckivy/_anim_attrs.py
Normal file
@ -0,0 +1,114 @@
|
||||
__all__ = ('anim_attrs', 'anim_attrs_abbr', )
|
||||
import typing as T
|
||||
import types
|
||||
from functools import partial
|
||||
import kivy.clock
|
||||
from kivy.animation import AnimationTransition
|
||||
import asyncgui
|
||||
|
||||
|
||||
def _update(setattr, zip, min, obj, duration, transition, output_seq_type, anim_params, task, p_time, dt):
|
||||
time = p_time[0] + dt
|
||||
p_time[0] = time
|
||||
|
||||
# calculate progression
|
||||
progress = min(1., time / duration)
|
||||
t = transition(progress)
|
||||
|
||||
# apply progression on obj
|
||||
for attr_name, org_value, slope, is_seq in anim_params:
|
||||
if is_seq:
|
||||
new_value = output_seq_type(
|
||||
slope_elem * t + org_elem
|
||||
for org_elem, slope_elem in zip(org_value, slope)
|
||||
)
|
||||
setattr(obj, attr_name, new_value)
|
||||
else:
|
||||
setattr(obj, attr_name, slope * t + org_value)
|
||||
|
||||
# time to stop ?
|
||||
if progress >= 1.:
|
||||
task._step()
|
||||
return False
|
||||
|
||||
|
||||
_update = partial(_update, setattr, zip, min)
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def _anim_attrs(
|
||||
obj, duration, step, transition, output_seq_type, animated_properties,
|
||||
getattr=getattr, isinstance=isinstance, tuple=tuple, str=str, partial=partial, native_seq_types=(tuple, list),
|
||||
zip=zip, Clock=kivy.clock.Clock, AnimationTransition=AnimationTransition,
|
||||
_update=_update, _current_task=asyncgui._current_task, _sleep_forever=asyncgui._sleep_forever, /):
|
||||
if isinstance(transition, str):
|
||||
transition = getattr(AnimationTransition, transition)
|
||||
|
||||
# get current values & calculate slopes
|
||||
anim_params = tuple(
|
||||
(
|
||||
org_value := getattr(obj, attr_name),
|
||||
is_seq := isinstance(org_value, native_seq_types),
|
||||
(
|
||||
org_value := tuple(org_value),
|
||||
slope := tuple(goal_elem - org_elem for goal_elem, org_elem in zip(goal_value, org_value)),
|
||||
) if is_seq else (slope := goal_value - org_value),
|
||||
) and (attr_name, org_value, slope, is_seq, )
|
||||
for attr_name, goal_value in animated_properties.items()
|
||||
)
|
||||
|
||||
try:
|
||||
clock_event = Clock.schedule_interval(
|
||||
partial(_update, obj, duration, transition, output_seq_type, anim_params, (yield _current_task)[0][0],
|
||||
[0., ]),
|
||||
step,
|
||||
)
|
||||
yield _sleep_forever
|
||||
finally:
|
||||
clock_event.cancel()
|
||||
|
||||
|
||||
def anim_attrs(obj, *, duration=1.0, step=0, transition=AnimationTransition.linear, output_seq_type=tuple,
|
||||
**animated_properties) -> T.Awaitable:
|
||||
'''
|
||||
Animates attibutes of any object.
|
||||
|
||||
.. code-block::
|
||||
|
||||
import types
|
||||
|
||||
obj = types.SimpleNamespace(x=0, size=(200, 300))
|
||||
await anim_attrs(obj, x=100, size=(400, 400))
|
||||
|
||||
The ``output_seq_type`` parameter:
|
||||
|
||||
.. code-block::
|
||||
|
||||
obj = types.SimpleNamespace(size=(200, 300))
|
||||
await anim_attrs(obj, size=(400, 400), output_seq_type=list)
|
||||
assert type(obj.size) is list
|
||||
|
||||
.. warning::
|
||||
|
||||
Unlike :class:`kivy.animation.Animation`, this one does not support dictionary-type and nested-sequence.
|
||||
|
||||
.. code-block::
|
||||
|
||||
await anim_attrs(obj, pos_hint={'x': 1.}) # not supported
|
||||
await anim_attrs(obj, nested_sequence=[[10, 20, ]]) # not supported
|
||||
|
||||
await anim_attrs(obj, color=(1, 0, 0, 1), pos=(100, 200)) # OK
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
return _anim_attrs(obj, duration, step, transition, output_seq_type, animated_properties)
|
||||
|
||||
|
||||
def anim_attrs_abbr(obj, *, d=1.0, s=0, t=AnimationTransition.linear, output_seq_type=tuple,
|
||||
**animated_properties) -> T.Awaitable:
|
||||
'''
|
||||
:func:`anim_attrs` cannot animate attributes named ``step``, ``duration`` and ``transition`` but this one can.
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
return _anim_attrs(obj, d, s, t, output_seq_type, animated_properties)
|
@ -0,0 +1,146 @@
|
||||
__all__ = (
|
||||
'anim_with_dt', 'anim_with_et', 'anim_with_ratio', 'anim_with_dt_et', 'anim_with_dt_et_ratio',
|
||||
)
|
||||
|
||||
from ._sleep import repeat_sleeping
|
||||
|
||||
|
||||
async def anim_with_dt(*, step=0):
|
||||
'''
|
||||
An async form of :meth:`kivy.clock.Clock.schedule_interval`. The following callback-style code:
|
||||
|
||||
.. code-block::
|
||||
|
||||
def callback(dt):
|
||||
print(dt)
|
||||
if some_condition:
|
||||
return False
|
||||
|
||||
Clock.schedule_interval(callback, 0.1)
|
||||
|
||||
is equivalent to the following async-style code:
|
||||
|
||||
.. code-block::
|
||||
|
||||
async for dt in anim_with_dt(step=0.1):
|
||||
print(dt)
|
||||
if some_condition:
|
||||
break
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
async with repeat_sleeping(step=step) as sleep:
|
||||
while True:
|
||||
yield await sleep()
|
||||
|
||||
|
||||
async def anim_with_et(*, step=0):
|
||||
'''
|
||||
Same as :func:`anim_with_dt` except this one generates the total elapsed time of the loop instead of the elapsed
|
||||
time between frames.
|
||||
|
||||
.. code-block::
|
||||
|
||||
timeout = 3.0
|
||||
async for et in anim_with_et(...):
|
||||
...
|
||||
if et > timeout:
|
||||
break
|
||||
|
||||
You can calculate ``et`` by yourself if you want to:
|
||||
|
||||
.. code-block::
|
||||
|
||||
et = 0.
|
||||
timeout = 3.0
|
||||
async for dt in anim_with_dt(...):
|
||||
et += dt
|
||||
...
|
||||
if et > timeout:
|
||||
break
|
||||
|
||||
which should be as performant as the former.
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
et = 0.
|
||||
async with repeat_sleeping(step=step) as sleep:
|
||||
while True:
|
||||
et += await sleep()
|
||||
yield et
|
||||
|
||||
|
||||
async def anim_with_dt_et(*, step=0):
|
||||
'''
|
||||
:func:`anim_with_dt` and :func:`anim_with_et` combined.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async for dt, et in anim_with_dt_et(...):
|
||||
...
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
et = 0.
|
||||
async with repeat_sleeping(step=step) as sleep:
|
||||
while True:
|
||||
dt = await sleep()
|
||||
et += dt
|
||||
yield dt, et
|
||||
|
||||
|
||||
async def anim_with_ratio(*, duration=1., step=0):
|
||||
'''
|
||||
Same as :func:`anim_with_et` except this one generates the total progression ratio of the loop.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async for p in anim_with_ratio(duration=3.0):
|
||||
print(p * 100, "%")
|
||||
|
||||
If you want to progress at a non-consistant rate, :class:`kivy.animation.AnimationTransition` may be helpful.
|
||||
|
||||
.. code-block::
|
||||
|
||||
from kivy.animation import AnimationTransition
|
||||
|
||||
in_cubic = AnimationTransition.in_cubic
|
||||
|
||||
async for p in anim_with_ratio(duration=3.0):
|
||||
p = in_cubic(p)
|
||||
print(p * 100, "%")
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
async with repeat_sleeping(step=step) as sleep:
|
||||
if not duration:
|
||||
await sleep()
|
||||
yield 1.0
|
||||
return
|
||||
et = 0.
|
||||
while et < duration:
|
||||
et += await sleep()
|
||||
yield et / duration
|
||||
|
||||
|
||||
async def anim_with_dt_et_ratio(*, duration=1., step=0):
|
||||
'''
|
||||
:func:`anim_with_dt`, :func:`anim_with_et` and :func:`anim_with_ratio` combined.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async for dt, et, p in anim_with_dt_et_ratio(...):
|
||||
...
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
async with repeat_sleeping(step=step) as sleep:
|
||||
if not duration:
|
||||
dt = await sleep()
|
||||
yield dt, dt, 1.0
|
||||
return
|
||||
et = 0.
|
||||
while et < duration:
|
||||
dt = await sleep()
|
||||
et += dt
|
||||
yield dt, et, et / duration
|
115
kivy_venv/lib/python3.11/site-packages/asynckivy/_animation.py
Normal file
115
kivy_venv/lib/python3.11/site-packages/asynckivy/_animation.py
Normal file
@ -0,0 +1,115 @@
|
||||
__all__ = ('animate', )
|
||||
import typing as T
|
||||
import types
|
||||
from functools import partial
|
||||
from kivy.clock import Clock
|
||||
from kivy.animation import AnimationTransition
|
||||
from asyncgui import _sleep_forever, _current_task
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def animate(obj, *, duration=1.0, step=0, transition=AnimationTransition.linear, **animated_properties) -> T.Awaitable:
|
||||
'''
|
||||
Animates attibutes of any object. This is basically an async form of :class:`kivy.animation.Animation`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
import types
|
||||
|
||||
obj = types.SimpleNamespace(x=0, size=(200, 300, ))
|
||||
await animate(obj, x=100, size=(400, 400))
|
||||
|
||||
Kivy has two compound animations, :class:`kivy.animation.Sequence` and :class:`kivy.animation.Parallel`.
|
||||
You can achieve the same functionality as them in asynckivy as follows:
|
||||
|
||||
.. code-block::
|
||||
|
||||
import asynckivy as ak
|
||||
|
||||
async def sequential_animation(widget):
|
||||
await ak.animate(widget, x=100)
|
||||
await ak.animate(widget, x=0)
|
||||
|
||||
async def parallel_animation(widget):
|
||||
await ak.wait_all(
|
||||
ak.animate(widget, x=100),
|
||||
ak.animate(widget, y=100, duration=2),
|
||||
)
|
||||
|
||||
.. deprecated:: 0.6.1
|
||||
|
||||
This will be removed before version 1.0.0.
|
||||
Use :func:`asynckivy.anim_attrs` or :func:`asynckivy.anim_attrs_abbr` instead.
|
||||
'''
|
||||
if not duration:
|
||||
for key, value in animated_properties.items():
|
||||
setattr(obj, key, value)
|
||||
return
|
||||
if isinstance(transition, str):
|
||||
transition = getattr(AnimationTransition, transition)
|
||||
|
||||
# get current values
|
||||
properties = {}
|
||||
for key, value in animated_properties.items():
|
||||
original_value = getattr(obj, key)
|
||||
if isinstance(original_value, (tuple, list)):
|
||||
original_value = original_value[:]
|
||||
elif isinstance(original_value, dict):
|
||||
original_value = original_value.copy()
|
||||
properties[key] = (original_value, value)
|
||||
|
||||
try:
|
||||
clock_event = Clock.schedule_interval(
|
||||
partial(_update, obj, duration, transition, properties, (yield _current_task)[0][0], [0., ]),
|
||||
step,
|
||||
)
|
||||
yield _sleep_forever
|
||||
finally:
|
||||
clock_event.cancel()
|
||||
|
||||
|
||||
def _calculate(isinstance, list, tuple, dict, range, len, a, b, t):
|
||||
'''The logic of this function is identical to 'kivy.animation.Animation._calculate()'
|
||||
'''
|
||||
if isinstance(a, list) or isinstance(a, tuple):
|
||||
if isinstance(a, list):
|
||||
tp = list
|
||||
else:
|
||||
tp = tuple
|
||||
return tp([_calculate(a[x], b[x], t) for x in range(len(a))])
|
||||
elif isinstance(a, dict):
|
||||
d = {}
|
||||
for x in a:
|
||||
if x not in b:
|
||||
# User requested to animate only part of the dict.
|
||||
# Copy the rest
|
||||
d[x] = a[x]
|
||||
else:
|
||||
d[x] = _calculate(a[x], b[x], t)
|
||||
return d
|
||||
else:
|
||||
return (a * (1. - t)) + (b * t)
|
||||
|
||||
|
||||
def _update(setattr, _calculate, obj, duration, transition, properties, task, p_time, dt):
|
||||
time = p_time[0] + dt
|
||||
p_time[0] = time
|
||||
|
||||
# calculate progression
|
||||
progress = min(1., time / duration)
|
||||
t = transition(progress)
|
||||
|
||||
# apply progression on obj
|
||||
for key, values in properties.items():
|
||||
a, b = values
|
||||
value = _calculate(a, b, t)
|
||||
setattr(obj, key, value)
|
||||
|
||||
# time to stop ?
|
||||
if progress >= 1.:
|
||||
task._step()
|
||||
return False
|
||||
|
||||
|
||||
_calculate = partial(_calculate, isinstance, list, tuple, dict, range, len)
|
||||
_update = partial(_update, setattr, _calculate)
|
57
kivy_venv/lib/python3.11/site-packages/asynckivy/_event.py
Normal file
57
kivy_venv/lib/python3.11/site-packages/asynckivy/_event.py
Normal file
@ -0,0 +1,57 @@
|
||||
__all__ = ('event', )
|
||||
|
||||
import typing as T
|
||||
import types
|
||||
from functools import partial
|
||||
from asyncgui import _current_task, _sleep_forever
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def event(event_dispatcher, event_name, *, filter=None, stop_dispatching=False) -> T.Awaitable[tuple]:
|
||||
'''
|
||||
Returns an awaitable that can be used to wait for:
|
||||
|
||||
* a Kivy event to occur.
|
||||
* a Kivy property's value to change.
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Wait for a button to be pressed.
|
||||
await event(button, 'on_press')
|
||||
|
||||
# Wait for an 'on_touch_down' event to occur.
|
||||
__, touch = await event(widget, 'on_touch_down')
|
||||
|
||||
# Wait for 'widget.x' to change.
|
||||
__, x = await ak.event(widget, 'x')
|
||||
|
||||
|
||||
The ``filter`` parameter:
|
||||
|
||||
.. code-block::
|
||||
|
||||
# Wait for an 'on_touch_down' event to occur inside a widget.
|
||||
__, touch = await event(widget, 'on_touch_down', filter=lambda w, t: w.collide_point(*t.opos))
|
||||
|
||||
# Wait for 'widget.x' to become greater than 100.
|
||||
if widget.x <= 100:
|
||||
await event(widget, 'x', filter=lambda __, x: x > 100)
|
||||
|
||||
The ``stop_dispatching`` parameter:
|
||||
|
||||
It only works for events not for properties.
|
||||
See :ref:`kivys-event-system` for details.
|
||||
'''
|
||||
task = (yield _current_task)[0][0]
|
||||
bind_id = event_dispatcher.fbind(event_name, partial(_callback, filter, task, stop_dispatching))
|
||||
assert bind_id # check if binding succeeded
|
||||
try:
|
||||
return (yield _sleep_forever)[0]
|
||||
finally:
|
||||
event_dispatcher.unbind_uid(event_name, bind_id)
|
||||
|
||||
|
||||
def _callback(filter, task, stop_dispatching, *args, **kwargs):
|
||||
if (filter is None) or filter(*args, **kwargs):
|
||||
task._step(*args)
|
||||
return stop_dispatching
|
@ -0,0 +1,27 @@
|
||||
__all__ = (
|
||||
'MotionEventAlreadyEndedError',
|
||||
)
|
||||
|
||||
|
||||
class MotionEventAlreadyEndedError(Exception):
|
||||
'''
|
||||
This error occurs when an already-ended touch is passed to an asynckivy API that expects an ongoing touch.
|
||||
For instance:
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 4
|
||||
|
||||
import asynckivy as ak
|
||||
|
||||
class MyWidget(Widget):
|
||||
def on_touch_up(self, touch): # not 'on_touch_down', oops!
|
||||
ak.start(self.handle_touch(touch))
|
||||
return True
|
||||
|
||||
async def handle_touch(self, touch):
|
||||
try:
|
||||
async for __ in ak.rest_of_touch_events(widget, touch):
|
||||
...
|
||||
except ak.MotionEventAlreadyEndedError:
|
||||
...
|
||||
'''
|
@ -0,0 +1,75 @@
|
||||
__all__ = ('interpolate', 'fade_transition', )
|
||||
import typing as T
|
||||
from contextlib import asynccontextmanager
|
||||
from kivy.animation import AnimationTransition
|
||||
|
||||
from ._anim_with_xxx import anim_with_ratio
|
||||
|
||||
|
||||
linear = AnimationTransition.linear
|
||||
|
||||
|
||||
async def interpolate(start, end, *, duration=1.0, step=0, transition=linear) -> T.AsyncIterator:
|
||||
'''
|
||||
Interpolates between the values ``start`` and ``end`` in an async-manner.
|
||||
Inspired by wasabi2d's interpolate_.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async for v in interpolate(0, 100, duration=1.0, step=.3):
|
||||
print(int(v))
|
||||
|
||||
============ ======
|
||||
elapsed time output
|
||||
============ ======
|
||||
0 sec 0
|
||||
0.3 sec 30
|
||||
0.6 sec 60
|
||||
0.9 sec 90
|
||||
**1.2 sec** 100
|
||||
============ ======
|
||||
|
||||
.. _interpolate: https://wasabi2d.readthedocs.io/en/stable/coros.html#clock.coro.interpolate
|
||||
'''
|
||||
if isinstance(transition, str):
|
||||
transition = getattr(AnimationTransition, transition)
|
||||
|
||||
slope = end - start
|
||||
yield transition(0.) * slope + start
|
||||
async for p in anim_with_ratio(step=step, duration=duration):
|
||||
if p >= 1.0:
|
||||
break
|
||||
yield transition(p) * slope + start
|
||||
yield transition(1.) * slope + start
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def fade_transition(*widgets, duration=1.0, step=0) -> T.AsyncContextManager:
|
||||
'''
|
||||
Returns an async context manager that:
|
||||
|
||||
* fades-out the given widgets on ``__aenter__``.
|
||||
* fades-in the given widgets on ``__aexit__``.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with fade_transition(widget1, widget2):
|
||||
...
|
||||
|
||||
The ``widgets`` don't have to be actual Kivy widgets.
|
||||
Anything that has an attribute named ``opacity`` would work.
|
||||
'''
|
||||
half_duration = duration / 2.
|
||||
org_opas = tuple(w.opacity for w in widgets)
|
||||
try:
|
||||
async for p in anim_with_ratio(duration=half_duration, step=step):
|
||||
p = 1.0 - p
|
||||
for w, o in zip(widgets, org_opas):
|
||||
w.opacity = p * o
|
||||
yield
|
||||
async for p in anim_with_ratio(duration=half_duration, step=step):
|
||||
for w, o in zip(widgets, org_opas):
|
||||
w.opacity = p * o
|
||||
finally:
|
||||
for w, o in zip(widgets, org_opas):
|
||||
w.opacity = o
|
@ -0,0 +1,43 @@
|
||||
__all__ = ('n_frames', )
|
||||
|
||||
import typing as T
|
||||
import types
|
||||
from kivy.clock import Clock
|
||||
from asyncgui import _current_task, _sleep_forever
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def n_frames(n: int) -> T.Awaitable:
|
||||
'''
|
||||
Waits for a specified number of frames.
|
||||
|
||||
.. code-block::
|
||||
|
||||
await n_frames(2)
|
||||
|
||||
If you want to wait for one frame, :func:`asynckivy.sleep` is preferable for a performance reason.
|
||||
|
||||
.. code-block::
|
||||
|
||||
await sleep(0)
|
||||
'''
|
||||
if n < 0:
|
||||
raise ValueError(f"Waiting for {n} frames doesn't make sense.")
|
||||
if not n:
|
||||
return
|
||||
|
||||
task = (yield _current_task)[0][0]
|
||||
|
||||
def callback(dt):
|
||||
nonlocal n
|
||||
n -= 1
|
||||
if not n:
|
||||
task._step()
|
||||
return False
|
||||
|
||||
clock_event = Clock.schedule_interval(callback, 0)
|
||||
|
||||
try:
|
||||
yield _sleep_forever
|
||||
finally:
|
||||
clock_event.cancel()
|
125
kivy_venv/lib/python3.11/site-packages/asynckivy/_sleep.py
Normal file
125
kivy_venv/lib/python3.11/site-packages/asynckivy/_sleep.py
Normal file
@ -0,0 +1,125 @@
|
||||
__all__ = ('sleep', 'sleep_free', 'repeat_sleeping', 'move_on_after', )
|
||||
|
||||
import typing as T
|
||||
import types
|
||||
|
||||
from kivy.clock import Clock
|
||||
from asyncgui import _current_task, _sleep_forever, move_on_when, Task, Cancelled
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def sleep(duration) -> T.Awaitable[float]:
|
||||
'''
|
||||
An async form of :meth:`kivy.clock.Clock.schedule_once`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
dt = await sleep(5) # wait for 5 seconds
|
||||
'''
|
||||
task = (yield _current_task)[0][0]
|
||||
clock_event = Clock.create_trigger(task._step, duration, False, False)
|
||||
clock_event()
|
||||
|
||||
try:
|
||||
return (yield _sleep_forever)[0][0]
|
||||
except Cancelled:
|
||||
clock_event.cancel()
|
||||
raise
|
||||
|
||||
|
||||
@types.coroutine
|
||||
def sleep_free(duration) -> T.Awaitable[float]:
|
||||
'''
|
||||
An async form of :meth:`kivy.clock.Clock.schedule_once_free`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
dt = await sleep_free(5) # wait for 5 seconds
|
||||
'''
|
||||
task = (yield _current_task)[0][0]
|
||||
clock_event = Clock.create_trigger_free(task._step, duration, False, False)
|
||||
clock_event()
|
||||
|
||||
try:
|
||||
return (yield _sleep_forever)[0][0]
|
||||
except Cancelled:
|
||||
clock_event.cancel()
|
||||
raise
|
||||
|
||||
|
||||
class repeat_sleeping:
|
||||
'''
|
||||
Returns an async context manager that provides an efficient way to repeat sleeping.
|
||||
|
||||
When there is a piece of code like this:
|
||||
|
||||
.. code-block::
|
||||
|
||||
while True:
|
||||
await sleep(0)
|
||||
...
|
||||
|
||||
it can be translated to:
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with repeat_sleeping(step=0) as sleep:
|
||||
while True:
|
||||
await sleep()
|
||||
...
|
||||
|
||||
The latter is more suitable for situations requiring frequent sleeps, such as moving an object in every frame.
|
||||
|
||||
**Restriction**
|
||||
|
||||
You are not allowed to perform any kind of async operations inside the with-block except you can
|
||||
``await`` the return value of the function that is bound to the identifier of the as-clause.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with repeat_sleeping(step=0) as sleep:
|
||||
await sleep() # OK
|
||||
await something_else # NOT ALLOWED
|
||||
async with async_context_manager: # NOT ALLOWED
|
||||
...
|
||||
async for __ in async_iterator: # NOT ALLOWED
|
||||
...
|
||||
'''
|
||||
|
||||
__slots__ = ('_step', '_trigger', )
|
||||
|
||||
@types.coroutine
|
||||
def _sleep(_f=_sleep_forever):
|
||||
return (yield _f)[0][0]
|
||||
|
||||
def __init__(self, *, step=0):
|
||||
self._step = step
|
||||
|
||||
@types.coroutine
|
||||
def __aenter__(self, _sleep=_sleep) -> T.Awaitable[T.Callable[[], T.Awaitable[float]]]:
|
||||
task = (yield _current_task)[0][0]
|
||||
self._trigger = Clock.create_trigger(task._step, self._step, True, False)
|
||||
self._trigger()
|
||||
return _sleep
|
||||
|
||||
async def __aexit__(self, exc_type, exc_val, exc_tb):
|
||||
self._trigger.cancel()
|
||||
|
||||
|
||||
def move_on_after(seconds: float) -> T.AsyncContextManager[Task]:
|
||||
'''
|
||||
Returns an async context manager that applies a time limit to its code block,
|
||||
like :func:`trio.move_on_after` does.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with move_on_after(seconds) as bg_task:
|
||||
...
|
||||
if bg_task.finished:
|
||||
print("The code block was interrupted due to a timeout")
|
||||
else:
|
||||
print("The code block exited gracefully.")
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
return move_on_when(sleep(seconds))
|
@ -0,0 +1,64 @@
|
||||
__all__ = ('run_in_thread', 'run_in_executor', )
|
||||
import typing as T
|
||||
from threading import Thread
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
from kivy.clock import Clock
|
||||
import asyncgui
|
||||
|
||||
|
||||
def _wrapper(func, ev):
|
||||
ret = None
|
||||
exc = None
|
||||
try:
|
||||
ret = func()
|
||||
except Exception as e:
|
||||
exc = e
|
||||
finally:
|
||||
Clock.schedule_once(lambda __: ev.fire(ret, exc))
|
||||
|
||||
|
||||
async def run_in_thread(func, *, daemon=None) -> T.Awaitable:
|
||||
'''
|
||||
Creates a new thread, runs a function within it, then waits for the completion of that function.
|
||||
|
||||
.. code-block::
|
||||
|
||||
return_value = await run_in_thread(func)
|
||||
|
||||
See :ref:`io-in-asynckivy` for details.
|
||||
'''
|
||||
ev = asyncgui.AsyncEvent()
|
||||
Thread(
|
||||
name='asynckivy.run_in_thread',
|
||||
target=_wrapper, daemon=daemon, args=(func, ev, ),
|
||||
).start()
|
||||
ret, exc = (await ev.wait())[0]
|
||||
if exc is not None:
|
||||
raise exc
|
||||
return ret
|
||||
|
||||
|
||||
async def run_in_executor(executor: ThreadPoolExecutor, func) -> T.Awaitable:
|
||||
'''
|
||||
Runs a function within a :class:`concurrent.futures.ThreadPoolExecutor`, and waits for the completion of the
|
||||
function.
|
||||
|
||||
.. code-block::
|
||||
|
||||
executor = ThreadPoolExecutor()
|
||||
...
|
||||
return_value = await run_in_executor(executor, func)
|
||||
|
||||
See :ref:`io-in-asynckivy` for details.
|
||||
'''
|
||||
ev = asyncgui.AsyncEvent()
|
||||
future = executor.submit(_wrapper, func, ev)
|
||||
try:
|
||||
ret, exc = (await ev.wait())[0]
|
||||
except asyncgui.Cancelled:
|
||||
future.cancel()
|
||||
raise
|
||||
assert future.done()
|
||||
if exc is not None:
|
||||
raise exc
|
||||
return ret
|
196
kivy_venv/lib/python3.11/site-packages/asynckivy/_touch.py
Normal file
196
kivy_venv/lib/python3.11/site-packages/asynckivy/_touch.py
Normal file
@ -0,0 +1,196 @@
|
||||
__all__ = ('watch_touch', 'rest_of_touch_moves', 'rest_of_touch_events', 'touch_up_event', )
|
||||
|
||||
import typing as T
|
||||
import types
|
||||
from functools import partial
|
||||
from asyncgui import wait_any, current_task
|
||||
from ._exceptions import MotionEventAlreadyEndedError
|
||||
from ._sleep import sleep
|
||||
from ._event import event
|
||||
|
||||
|
||||
class watch_touch:
|
||||
'''
|
||||
Returns an async context manager that provides an easy way to handle touch events.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with watch_touch(widget, touch) as in_progress:
|
||||
while await in_progress():
|
||||
print('on_touch_move')
|
||||
print('on_touch_up')
|
||||
|
||||
The ``await in_progress()`` waits for either an ``on_touch_move`` event or an ``on_touch_up`` event to occur, and
|
||||
returns True or False respectively when they occurred.
|
||||
|
||||
**Caution**
|
||||
|
||||
* You are not allowed to perform any kind of async operations inside the with-block except ``await in_progress()``.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async with watch_touch(widget, touch) as in_progress:
|
||||
await in_progress() # OK
|
||||
await something_else # NOT ALLOWED
|
||||
async with async_context_manager: # NOT ALLOWED
|
||||
...
|
||||
async for __ in async_iterator: # NOT ALLOWED
|
||||
...
|
||||
|
||||
* If the ``widget`` is the type of widget that grabs touches by itself, such as :class:`kivy.uix.button.Button`,
|
||||
you probably want to set the ``stop_dispatching`` parameter to True in most cases.
|
||||
* There are widgets/behaviors that can simulate a touch (e.g. :class:`kivy.uix.scrollview.ScrollView`,
|
||||
:class:`kivy.uix.behaviors.DragBehavior` and ``kivy_garden.draggable.KXDraggableBehavior``).
|
||||
If many such widgets are in the parent stack of the ``widget``, this API might mistakenly raise a
|
||||
:exc:`asynckivy.MotionEventAlreadyEndedError`. If that happens, increase the ``timeout`` parameter.
|
||||
'''
|
||||
__slots__ = ('_widget', '_touch', '_stop_dispatching', '_timeout', '_uid_up', '_uid_move', '_no_cleanup', )
|
||||
|
||||
def __init__(self, widget, touch, *, stop_dispatching=False, timeout=1.):
|
||||
self._widget = widget
|
||||
self._touch = touch
|
||||
self._stop_dispatching = stop_dispatching
|
||||
self._timeout = timeout
|
||||
self._no_cleanup = False
|
||||
|
||||
def _on_touch_up_sd(step, touch, w, t):
|
||||
if t is touch:
|
||||
if t.grab_current is w:
|
||||
t.ungrab(w)
|
||||
step(False)
|
||||
return True
|
||||
|
||||
def _on_touch_move_sd(step, touch, w, t):
|
||||
if t is touch:
|
||||
if t.grab_current is w:
|
||||
step(True)
|
||||
return True
|
||||
|
||||
def _on_touch_up(step, touch, w, t):
|
||||
if t.grab_current is w and t is touch:
|
||||
t.ungrab(w)
|
||||
step(False)
|
||||
return True
|
||||
|
||||
def _on_touch_move(step, touch, w, t):
|
||||
if t.grab_current is w and t is touch:
|
||||
step(True)
|
||||
return True
|
||||
|
||||
_callbacks = ((_on_touch_up_sd, _on_touch_move_sd, ), (_on_touch_up, _on_touch_move, ), )
|
||||
del _on_touch_up, _on_touch_move, _on_touch_up_sd, _on_touch_move_sd
|
||||
|
||||
@staticmethod
|
||||
@types.coroutine
|
||||
def _true_if_touch_move_false_if_touch_up() -> bool:
|
||||
return (yield lambda step_coro: None)[0][0]
|
||||
|
||||
@staticmethod
|
||||
@types.coroutine
|
||||
def _always_false() -> bool:
|
||||
return False
|
||||
yield # just to make this function a generator function
|
||||
|
||||
async def __aenter__(self) -> T.Awaitable[T.Callable[[], T.Awaitable[bool]]]:
|
||||
touch = self._touch
|
||||
widget = self._widget
|
||||
if touch.time_end != -1:
|
||||
# `on_touch_up` might have been already fired so we need to find out it actually was or not.
|
||||
tasks = await wait_any(
|
||||
sleep(self._timeout),
|
||||
event(widget, 'on_touch_up', filter=lambda w, t: t is touch),
|
||||
)
|
||||
if tasks[0].finished:
|
||||
raise MotionEventAlreadyEndedError(f"MotionEvent(uid={touch.uid}) has already ended")
|
||||
self._no_cleanup = True
|
||||
return self._always_false
|
||||
step = (await current_task())._step
|
||||
on_touch_up, on_touch_move = self._callbacks[not self._stop_dispatching]
|
||||
touch.grab(widget)
|
||||
self._uid_up = widget.fbind('on_touch_up', partial(on_touch_up, step, touch))
|
||||
self._uid_move = widget.fbind('on_touch_move', partial(on_touch_move, step, touch))
|
||||
assert self._uid_up
|
||||
assert self._uid_move
|
||||
return self._true_if_touch_move_false_if_touch_up
|
||||
|
||||
async def __aexit__(self, *args):
|
||||
if self._no_cleanup:
|
||||
return
|
||||
w = self._widget
|
||||
self._touch.ungrab(w)
|
||||
w.unbind_uid('on_touch_up', self._uid_up)
|
||||
w.unbind_uid('on_touch_move', self._uid_move)
|
||||
|
||||
|
||||
async def touch_up_event(widget, touch, *, stop_dispatching=False, timeout=1.) -> T.Awaitable:
|
||||
'''
|
||||
*(experimental state)*
|
||||
|
||||
Returns an awaitable that can be used to wait for the ``on_touch_up`` event of the given ``touch`` to occur.
|
||||
|
||||
.. code-block::
|
||||
|
||||
__, touch = await event(widget, 'on_touch_down')
|
||||
...
|
||||
await touch_up_event(widget, touch)
|
||||
|
||||
You might wonder what the differences are compared to the code below.
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 3
|
||||
|
||||
__, touch = await event(widget, 'on_touch_down')
|
||||
...
|
||||
await event(widget, 'on_touch_up', filter=lambda w, t: t is touch)
|
||||
|
||||
The latter has two problems:
|
||||
If the ``on_touch_up`` event of the ``touch`` occurred before the highlighted line,
|
||||
the execution will halt indefinitely at that point.
|
||||
Even if the event didn't occur before that line, the execution still might halt because
|
||||
`Kivy does not guarantee`_ that all touch events are delivered to all widgets.
|
||||
|
||||
This API takes care of both problems in the same way as :func:`watch_touch`.
|
||||
If the ``on_touch_up`` event has already occurred, it raises a :exc:`MotionEventAlreadyEndedError` exception.
|
||||
And it grabs/ungrabs the ``touch`` so that it won't miss any touch events.
|
||||
|
||||
Needless to say, if you want to wait for both ``on_touch_move`` and ``on_touch_up`` events at the same time,
|
||||
use :func:`watch_touch` or :func:`rest_of_touch_events` instead.
|
||||
|
||||
.. _Kivy does not guarantee: https://kivy.org/doc/stable/guide/inputs.html#grabbing-touch-events
|
||||
'''
|
||||
touch.grab(widget)
|
||||
try:
|
||||
awaitable = event(
|
||||
widget, 'on_touch_up', stop_dispatching=stop_dispatching,
|
||||
filter=lambda w, t: t.grab_current is w and t is touch,
|
||||
)
|
||||
if touch.time_end == -1:
|
||||
await awaitable
|
||||
else:
|
||||
tasks = await wait_any(sleep(timeout), awaitable)
|
||||
if tasks[0].finished:
|
||||
raise MotionEventAlreadyEndedError(f"MotionEvent(uid={touch.uid}) has already ended")
|
||||
finally:
|
||||
touch.ungrab(widget)
|
||||
|
||||
|
||||
async def rest_of_touch_events(widget, touch, *, stop_dispatching=False, timeout=1.) -> T.AsyncIterator[None]:
|
||||
'''
|
||||
Returns an async iterator that iterates the number of times ``on_touch_move`` occurs,
|
||||
and ends the iteration when ``on_touch_up`` occurs.
|
||||
|
||||
.. code-block::
|
||||
|
||||
async for __ in rest_of_touch_events(widget, touch):
|
||||
print('on_touch_move')
|
||||
print('on_touch_up')
|
||||
|
||||
This is a wrapper for :class:`watch_touch`. Although this one, I believe, is more intuitive than
|
||||
:class:`watch_touch`, it has a couple of disadvantages - see :ref:`the-problem-with-async-generators`.
|
||||
'''
|
||||
async with watch_touch(widget, touch, stop_dispatching=stop_dispatching, timeout=timeout) as in_progress:
|
||||
while await in_progress():
|
||||
yield
|
||||
|
||||
|
||||
rest_of_touch_moves = rest_of_touch_events
|
256
kivy_venv/lib/python3.11/site-packages/asynckivy/_utils.py
Normal file
256
kivy_venv/lib/python3.11/site-packages/asynckivy/_utils.py
Normal file
@ -0,0 +1,256 @@
|
||||
__all__ = ('transform', 'suppress_event', 'create_texture_from_text', 'sync_attr', 'sync_attrs', )
|
||||
import typing as T
|
||||
from contextlib import contextmanager
|
||||
from functools import partial
|
||||
|
||||
from kivy.event import EventDispatcher
|
||||
from kivy.graphics import PushMatrix, PopMatrix, InstructionGroup
|
||||
from kivy.graphics.texture import Texture
|
||||
from kivy.core.text import Label as CoreLabel
|
||||
from kivy.core.text.markup import MarkupLabel as CoreMarkupLabel
|
||||
|
||||
|
||||
@contextmanager
|
||||
def transform(widget, *, use_outer_canvas=False) -> T.ContextManager[InstructionGroup]:
|
||||
'''
|
||||
Returns a context manager that sandwiches the ``widget``'s existing canvas instructions between
|
||||
a :class:`kivy.graphics.PushMatrix` and a :class:`kivy.graphics.PopMatrix`, and inserts an
|
||||
:class:`kivy.graphics.InstructionGroup` right next to the ``PushMatrix``. Those three instructions will be removed
|
||||
when the context manager exits.
|
||||
|
||||
This may be useful when you want to animate a widget.
|
||||
|
||||
**Usage**
|
||||
|
||||
.. code-block::
|
||||
|
||||
from kivy.graphics import Rotate
|
||||
|
||||
async def rotate_widget(widget, *, angle=360.):
|
||||
with transform(widget) as ig: # <- InstructionGroup
|
||||
ig.add(rotate := Rotate(origin=widget.center))
|
||||
await anim_attrs(rotate, angle=angle)
|
||||
|
||||
If the position or size of the ``widget`` changes during the animation, you might need :class:`sync_attr`.
|
||||
|
||||
**The use_outer_canvas parameter**
|
||||
|
||||
While the context manager is active, the content of the widget's canvas would be:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
# ... represents existing instructions
|
||||
|
||||
Widget:
|
||||
canvas.before:
|
||||
...
|
||||
canvas:
|
||||
PushMatrix
|
||||
InstructionGroup
|
||||
...
|
||||
PopMatrix
|
||||
canvas.after:
|
||||
...
|
||||
|
||||
but if ``use_outer_canvas`` is True, it would be:
|
||||
|
||||
.. code-block:: yaml
|
||||
|
||||
Widget:
|
||||
canvas.before:
|
||||
PushMatrix
|
||||
InstructionGroup
|
||||
...
|
||||
canvas:
|
||||
...
|
||||
canvas.after:
|
||||
...
|
||||
PopMatrix
|
||||
'''
|
||||
|
||||
c = widget.canvas
|
||||
if use_outer_canvas:
|
||||
before = c.before
|
||||
after = c.after
|
||||
push_mat_idx = 0
|
||||
ig_idx = 1
|
||||
else:
|
||||
c.before # ensure 'canvas.before' exists
|
||||
|
||||
# Index starts from 1 because 'canvas.before' is sitting at index 0 and we usually want it to remain first.
|
||||
# See https://github.com/kivy/kivy/issues/7945 for details.
|
||||
push_mat_idx = 1
|
||||
ig_idx = 2
|
||||
before = after = c
|
||||
|
||||
push_mat = PushMatrix()
|
||||
ig = InstructionGroup()
|
||||
pop_mat = PopMatrix()
|
||||
|
||||
before.insert(push_mat_idx, push_mat)
|
||||
before.insert(ig_idx, ig)
|
||||
after.add(pop_mat)
|
||||
try:
|
||||
yield ig
|
||||
finally:
|
||||
after.remove(pop_mat)
|
||||
before.remove(ig)
|
||||
before.remove(push_mat)
|
||||
|
||||
|
||||
class suppress_event:
|
||||
'''
|
||||
Returns a context manager that prevents the callback functions (including the default handler) bound to an event
|
||||
from being called.
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 4
|
||||
|
||||
from kivy.uix.button import Button
|
||||
|
||||
btn = Button()
|
||||
btn.bind(on_press=lambda __: print("pressed"))
|
||||
with suppress_event(btn, 'on_press'):
|
||||
btn.dispatch('on_press')
|
||||
|
||||
The above code prints nothing because the callback function won't be called.
|
||||
|
||||
Strictly speaking, this context manager doesn't prevent all callback functions from being called.
|
||||
It only prevents the callback functions that were bound to an event before the context manager enters.
|
||||
Thus, the following code prints ``pressed``.
|
||||
|
||||
.. code-block::
|
||||
:emphasize-lines: 5
|
||||
|
||||
from kivy.uix.button import Button
|
||||
|
||||
btn = Button()
|
||||
with suppress_event(btn, 'on_press'):
|
||||
btn.bind(on_press=lambda __: print("pressed"))
|
||||
btn.dispatch('on_press')
|
||||
|
||||
.. warning::
|
||||
|
||||
You need to be careful when you suppress an ``on_touch_xxx`` event.
|
||||
See :ref:`kivys-event-system` for details.
|
||||
'''
|
||||
__slots__ = ('_dispatcher', '_name', '_bind_uid', '_filter', )
|
||||
|
||||
def __init__(self, event_dispatcher, event_name, *, filter=lambda *args, **kwargs: True):
|
||||
self._dispatcher = event_dispatcher
|
||||
self._name = event_name
|
||||
self._filter = filter
|
||||
|
||||
def __enter__(self):
|
||||
self._bind_uid = self._dispatcher.fbind(self._name, self._filter)
|
||||
|
||||
def __exit__(self, *args):
|
||||
self._dispatcher.unbind_uid(self._name, self._bind_uid)
|
||||
|
||||
|
||||
def create_texture_from_text(*, markup=False, **label_kwargs) -> Texture:
|
||||
'''
|
||||
.. code-block::
|
||||
|
||||
from kivy.metrics import sp
|
||||
|
||||
texture = create_texture_from_text(
|
||||
text='Hello',
|
||||
font_size=sp(50),
|
||||
font_name='Roboto',
|
||||
color=(1, 0, 0, 1),
|
||||
)
|
||||
|
||||
The keyword arguments are similar to :external:kivy:doc:`api-kivy.uix.label` 's.
|
||||
'''
|
||||
core_cls = CoreMarkupLabel if markup else CoreLabel
|
||||
core = core_cls(**label_kwargs)
|
||||
core.refresh()
|
||||
return core.texture
|
||||
|
||||
|
||||
class sync_attr:
|
||||
'''
|
||||
Returns a context manager that creates one-directional binding between attributes.
|
||||
|
||||
.. code-block::
|
||||
|
||||
import types
|
||||
|
||||
widget = Widget()
|
||||
obj = types.SimpleNamespace()
|
||||
|
||||
with sync_attr(from_=(widget, 'x'), to_=(obj, 'xx')):
|
||||
widget.x = 10
|
||||
assert obj.xx == 10 # synchronized
|
||||
obj.xx = 20
|
||||
assert widget.x == 10 # but not the other way around
|
||||
|
||||
This can be particularly useful when combined with :func:`transform`.
|
||||
|
||||
.. code-block::
|
||||
|
||||
from kivy.graphics import Rotate
|
||||
|
||||
async def rotate_widget(widget, *, angle=360.):
|
||||
with transform(widget) as ig:
|
||||
ig.add(rotate := Rotate(origin=widget.center))
|
||||
with sync_attr(from_=(widget, 'center'), to_=(rotate, 'origin')):
|
||||
await anim_attrs(rotate, angle=angle)
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
__slots__ = ('_from', '_to', '_bind_uid', )
|
||||
|
||||
def __init__(self, from_: T.Tuple[EventDispatcher, str], to_: T.Tuple[T.Any, str]):
|
||||
self._from = from_
|
||||
self._to = to_
|
||||
|
||||
def _sync(setattr, obj, attr_name, event_dispatcher, new_value):
|
||||
setattr(obj, attr_name, new_value)
|
||||
|
||||
def __enter__(self, partial=partial, sync=partial(_sync, setattr)):
|
||||
self._bind_uid = self._from[0].fbind(self._from[1], partial(sync, *self._to))
|
||||
|
||||
def __exit__(self, *args):
|
||||
self._from[0].unbind_uid(self._from[1], self._bind_uid)
|
||||
|
||||
del _sync
|
||||
|
||||
|
||||
class sync_attrs:
|
||||
'''
|
||||
When multiple :class:`sync_attr` calls take the same ``from_`` argument, they can be merged into a single
|
||||
:class:`sync_attrs` call. For instance, the following code:
|
||||
|
||||
.. code-block::
|
||||
|
||||
with sync_attr((widget, 'x'), (obj1, 'x')), sync_attr((widget, 'x'), (obj2, 'xx')):
|
||||
...
|
||||
|
||||
can be replaced with the following one:
|
||||
|
||||
.. code-block::
|
||||
|
||||
with sync_attrs((widget, 'x'), (obj1, 'x'), (obj2, 'xx')):
|
||||
...
|
||||
|
||||
.. versionadded:: 0.6.1
|
||||
'''
|
||||
__slots__ = ('_from', '_to', '_bind_uid', )
|
||||
|
||||
def __init__(self, from_: T.Tuple[EventDispatcher, str], *to_):
|
||||
self._from = from_
|
||||
self._to = to_
|
||||
|
||||
def _sync(setattr, to_, event_dispatcher, new_value):
|
||||
for obj, attr_name in to_:
|
||||
setattr(obj, attr_name, new_value)
|
||||
|
||||
def __enter__(self, partial=partial, sync=partial(_sync, setattr)):
|
||||
self._bind_uid = self._from[0].fbind(self._from[1], partial(sync, self._to))
|
||||
|
||||
def __exit__(self, *args):
|
||||
self._from[0].unbind_uid(self._from[1], self._bind_uid)
|
||||
|
||||
del _sync
|
20
kivy_venv/lib/python3.11/site-packages/asynckivy/vanim.py
Normal file
20
kivy_venv/lib/python3.11/site-packages/asynckivy/vanim.py
Normal file
@ -0,0 +1,20 @@
|
||||
__all__ = (
|
||||
'dt', 'delta_time',
|
||||
'et', 'elapsed_time',
|
||||
'dt_et', 'delta_time_elapsed_time',
|
||||
'progress',
|
||||
'dt_et_progress', 'delta_time_elapsed_time_progress',
|
||||
)
|
||||
|
||||
import warnings
|
||||
from . import _anim_with_xxx
|
||||
|
||||
|
||||
warnings.warn("The 'vanim' module is deprecated. Use 'asynckivy.anim_with_xxx' instead.")
|
||||
|
||||
|
||||
delta_time = dt = _anim_with_xxx.anim_with_dt
|
||||
elapsed_time = et = _anim_with_xxx.anim_with_et
|
||||
progress = _anim_with_xxx.anim_with_ratio
|
||||
delta_time_elapsed_time = dt_et = _anim_with_xxx.anim_with_dt_et
|
||||
delta_time_elapsed_time_progress = dt_et_progress = _anim_with_xxx.anim_with_dt_et_ratio
|
@ -1,394 +0,0 @@
|
||||
../../../bin/kivymd.add_view,sha256=u2N52U9NKr85se5a66gdG5Old498YxKwDezJ-cwIZAY,266
|
||||
../../../bin/kivymd.create_project,sha256=6LnjVohJ7V3MZYfVCtWqtyHHaku6Io-y0pN1BFPmDAM,272
|
||||
../../../bin/kivymd.make_release,sha256=hKmHIsjNRMSeSS3A2PNqeer_kEliqi6NhzI9bmLc0Zo,269
|
||||
kivymd-1.2.0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
kivymd-1.2.0.dist-info/LICENSE,sha256=bWmhpIowwWDSSAQwBDm2S0_cUBhZc2yzQ0DwcT9-TrY,1691
|
||||
kivymd-1.2.0.dist-info/METADATA,sha256=GNIP7_ZragUNLOP6JBXj04nv3clgw33m1MlflQ8a9g4,15020
|
||||
kivymd-1.2.0.dist-info/RECORD,,
|
||||
kivymd-1.2.0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd-1.2.0.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
|
||||
kivymd-1.2.0.dist-info/entry_points.txt,sha256=1-yhsSzIhBNRiKNTmevRDT02q8qzg3upZcWAyrr880w,342
|
||||
kivymd-1.2.0.dist-info/top_level.txt,sha256=ABq82F4nFM8sy3xAhxiO5XXT_lAen0YqiDD29qRiPhc,7
|
||||
kivymd/__init__.py,sha256=Lk1_FB7hhUcfOVc2hAVZdmpJa9RStEhpKf3Gx-Nm1C8,2158
|
||||
kivymd/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/__pycache__/_version.cpython-311.pyc,,
|
||||
kivymd/__pycache__/app.cpython-311.pyc,,
|
||||
kivymd/__pycache__/color_definitions.cpython-311.pyc,,
|
||||
kivymd/__pycache__/factory_registers.cpython-311.pyc,,
|
||||
kivymd/__pycache__/font_definitions.cpython-311.pyc,,
|
||||
kivymd/__pycache__/icon_definitions.cpython-311.pyc,,
|
||||
kivymd/__pycache__/material_resources.cpython-311.pyc,,
|
||||
kivymd/__pycache__/theming.cpython-311.pyc,,
|
||||
kivymd/__pycache__/theming_dynamic_text.cpython-311.pyc,,
|
||||
kivymd/_version.py,sha256=KnOtqZaS5l4zlFEKhhqjLzpQaqc4Kmdc5stnQiKUDYs,140
|
||||
kivymd/app.py,sha256=M1rwjNfNURnCdhVB_Rk7Hz5cljpwJxN8T6UhKkR4qaI,4222
|
||||
kivymd/color_definitions.py,sha256=vkOEWwRem3-Vh4dOIyJdSPrg88kyLaD6QZtpx7ecuV0,21550
|
||||
kivymd/effects/__init__.py,sha256=ySU96kLlmPF4QB-hDa0WM_Y0Odq1MPSR568yI_hiaqI,24
|
||||
kivymd/effects/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/effects/fadingedge/__init__.py,sha256=ED7rP0TF96RxwjtLhj3KdAfqo7-YQuA4B10jnWuuMEg,41
|
||||
kivymd/effects/fadingedge/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/effects/fadingedge/__pycache__/fadingedge.cpython-311.pyc,,
|
||||
kivymd/effects/fadingedge/fadingedge.py,sha256=ZM3JRhQ7kvNuj8Z52VUq6MLF2sh7BEoa4_5oc7-mvcg,6054
|
||||
kivymd/effects/roulettescroll/__init__.py,sha256=Ep2YTxf03Y_A2GbosQIsm8AFsuOeE-w5VPL_NxckTbY,49
|
||||
kivymd/effects/roulettescroll/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/effects/roulettescroll/__pycache__/roulettescroll.cpython-311.pyc,,
|
||||
kivymd/effects/roulettescroll/roulettescroll.py,sha256=b4pJtyKDUqRzSGW4iIZpgUWV91QlRxgUXaPreBUVVEI,8092
|
||||
kivymd/effects/stiffscroll/__init__.py,sha256=tkGDtFz6s7W3iFtHRDo6NYWadL85cn7GXKAQQfpiJRk,43
|
||||
kivymd/effects/stiffscroll/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/effects/stiffscroll/__pycache__/stiffscroll.cpython-311.pyc,,
|
||||
kivymd/effects/stiffscroll/stiffscroll.py,sha256=3bSj43xOzhBcBSn58iLUiaNWevlHuO8seklAyfvZsJE,7117
|
||||
kivymd/factory_registers.py,sha256=0wC2kYMlYCNdShEzETUWEyLsESwwDgnGrgsvVL3t7-M,6431
|
||||
kivymd/font_definitions.py,sha256=2-4eWkHy4GUT_HhIr5GSEK7CUd71th6Mvi3QAPibkTA,1628
|
||||
kivymd/fonts/Roboto-Black.ttf,sha256=OHLps5dgobWaweGSYz27O1jllbTUI5MKx97VJemuJeA,171480
|
||||
kivymd/fonts/Roboto-BlackItalic.ttf,sha256=AT0ipPsmOK26KFVe4ZNm9FhfbcUzt8My9JMaIxSXyyI,177552
|
||||
kivymd/fonts/Roboto-Bold.ttf,sha256=fQuZHuPgvnrwGtfqjNK-6mwAol5nmgImtnN_B5qv_4Y,170760
|
||||
kivymd/fonts/Roboto-BoldItalic.ttf,sha256=pLysFPQZqX3gkXGYpLxRw-1PxKPbn2ilEC8jZk7gE1Q,174952
|
||||
kivymd/fonts/Roboto-Italic.ttf,sha256=X86Lb4up9NGfDVNeJB1WorjnK7B-ffcR2WjQku9_n8o,173932
|
||||
kivymd/fonts/Roboto-Light.ttf,sha256=ptND1CW8ONuQFS-gYFixxzkeypJk8zTvZcHOF1CFxvY,170420
|
||||
kivymd/fonts/Roboto-LightItalic.ttf,sha256=Nkoj4Txkk3w_zqPbd4YouJN5yJOEm7reblv4PF9gXGo,176616
|
||||
kivymd/fonts/Roboto-Medium.ttf,sha256=8gXMURgh6lYHihBVV_zqYlMSlATUEcmX4YZvvQBqu2g,172064
|
||||
kivymd/fonts/Roboto-MediumItalic.ttf,sha256=8Xfu0Q0kcNE-xo0EkHpYKCnQ7oKB-KAqkG9pVMeBblg,176864
|
||||
kivymd/fonts/Roboto-Regular.ttf,sha256=eehRQEZX2sIQaz0irSVtR4JKmldlRY7bcskQKkWBbZU,171676
|
||||
kivymd/fonts/Roboto-Thin.ttf,sha256=PZH3qmnLf3BkA1iVxWasXLmyCEWC01Gvcme7Tg-6YPU,171904
|
||||
kivymd/fonts/Roboto-ThinItalic.ttf,sha256=9eiaNEiUpg8PmPHAGCulH1BG4p3eMRiCDTkCVEWuqug,176300
|
||||
kivymd/fonts/materialdesignicons-webfont.ttf,sha256=pY7LVPRe7Br628ITFNHwkyzwCeXLx_MiXX5KThtx72s,1279992
|
||||
kivymd/icon_definitions.py,sha256=NPLejj2aOoR3N97zW8H8K2Sw7ECqYXQ_xLALkD0Yo-c,276638
|
||||
kivymd/images/alpha_layer.png,sha256=FRlE7o8oQebgftB_P9I-o-a6mslCr7aIrY3Zo6QGuAs,553
|
||||
kivymd/images/black.png,sha256=2oJF5FzBeTXDdA7lE2kQ_ftDv8TRtCOiTQtfvCf_qlM,147
|
||||
kivymd/images/blue.png,sha256=vOIOgEL_pAc4anbPSOhe6dxcEYi58dh3jlprNc36ASQ,147
|
||||
kivymd/images/folder.png,sha256=xY9uUYegh7hDzFI4iPEA-zyFBzq9IE007zaJGGY5JY0,2311
|
||||
kivymd/images/green.png,sha256=GK69rWfb7kTIlxD8nPjSq1X6k06SO1AxstcJLskJtp4,147
|
||||
kivymd/images/logo/kivymd-icon-128.png,sha256=VjWHaIJ-MSyP7ZnM25xgBfp_wG4vbQhr8B8QOTcXeaM,19826
|
||||
kivymd/images/logo/kivymd-icon-256.png,sha256=5iJVryvz0D-IvqLGTsaeJlYhZYk2R7OxskKiNgw25Ks,31943
|
||||
kivymd/images/logo/kivymd-icon-512.png,sha256=JAtfTEA7AWBPcMhFGqlwSQmQSq-lWAEJ8Y98qmDe0I0,54349
|
||||
kivymd/images/red.png,sha256=_4J3FtVS8IKWHCmr2e9GOy2cOGKmwV_0lzAbQf1IKLM,147
|
||||
kivymd/images/transparent.png,sha256=yM2bydAM4U0tnbs4zAuK2GnCC6I6NgAIfpw7rQhG1BQ,156
|
||||
kivymd/images/yellow.png,sha256=TH_ecR8dfP9R-8zYD4Ez24qZjaEbDTgJ0RcIcbHBIeE,147
|
||||
kivymd/material_resources.py,sha256=Ph4x6f5Lp7XOI4jqIkOBo_tZ_yMUPZDToO34A7akOlo,1763
|
||||
kivymd/theming.py,sha256=hQ5RfjoQlE8hWQKdQ2ZVOF_83ok-o8o0BzR-Kv5XDmA,58553
|
||||
kivymd/theming_dynamic_text.py,sha256=5TaO0Tc98EqK4-qTDMUO4FQHIU_wVxk6Y2GHhD6UcRk,2920
|
||||
kivymd/toast/__init__.py,sha256=1gkx40QSHU_0YprtsIJfog8Nnj6t_ZuXMLGhI7QZ0ww,238
|
||||
kivymd/toast/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/toast/androidtoast/__init__.py,sha256=CCs95Gih3ri4OcO1J-xPFVmhGKPdY9idW3-V0mIjQ_s,226
|
||||
kivymd/toast/androidtoast/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/toast/androidtoast/__pycache__/androidtoast.cpython-311.pyc,,
|
||||
kivymd/toast/androidtoast/androidtoast.py,sha256=cpbgUhZUjOU1go4Sn-qOo9h61Qhk4EAx1SFI9b4tC8o,2363
|
||||
kivymd/toast/kivytoast/__init__.py,sha256=mFY2Qi4xK_ttQxx7DnEg7XZxX68he0Hr09rZ60Pm95A,51
|
||||
kivymd/toast/kivytoast/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/toast/kivytoast/__pycache__/kivytoast.cpython-311.pyc,,
|
||||
kivymd/toast/kivytoast/kivytoast.py,sha256=jRLOmiUV2Hf_09tTxnEfJUM5lEBZWfo_wEmgC9zLq5M,4135
|
||||
kivymd/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/__pycache__/argument_parser.cpython-311.pyc,,
|
||||
kivymd/tools/argument_parser.py,sha256=oxgJoS5WZH_ATDlaEU0HDtm7ve4DOJ23CnOILIBygy8,3193
|
||||
kivymd/tools/hotreload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/hotreload/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/hotreload/__pycache__/app.cpython-311.pyc,,
|
||||
kivymd/tools/hotreload/app.py,sha256=cJxyUxz1GbQ58pgPY3GZNSl-CoawoPUPoCUF3lECltI,16803
|
||||
kivymd/tools/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/packaging/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/packaging/pyinstaller/__init__.py,sha256=ibpoURJJkyGuSgWhz8t-RuLnCmQf15TiFNr-HKTCPHA,1480
|
||||
kivymd/tools/packaging/pyinstaller/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/packaging/pyinstaller/__pycache__/hook-kivymd.cpython-311.pyc,,
|
||||
kivymd/tools/packaging/pyinstaller/hook-kivymd.py,sha256=cN0arGlcA_vLA8FTaAdzKgn7s2YQRCclv7G0e4c4o-Y,1053
|
||||
kivymd/tools/patterns/MVC/Model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/patterns/MVC/Model/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/Model/__pycache__/database_firebase.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/Model/__pycache__/database_restdb.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/Model/database_firebase.py,sha256=5SlPAn-ROkh_ytnv2nteaVRAMC0MUSDM9u115Crfh-o,1376
|
||||
kivymd/tools/patterns/MVC/Model/database_restdb.py,sha256=Wc-zPffP-Wriyn-JGKCQrw3SGZMiAk-8LrVjParRtGM,3866
|
||||
kivymd/tools/patterns/MVC/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/patterns/MVC/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/data/locales/po/en.po,sha256=1b2jIsEnyQi_T_gnpe5QeO90IdaQLwWClk5pn46ZjME,425
|
||||
kivymd/tools/patterns/MVC/data/locales/po/ru.po,sha256=mQd6ol2abec-PUJsrnRWNoah0din3IAg_F4gPf5VBVw,425
|
||||
kivymd/tools/patterns/MVC/libs/__init__.py,sha256=B6Kln9GZ6UrMOxr4lOnpTxGBMaoKlcar5wpyTGyUlIk,54
|
||||
kivymd/tools/patterns/MVC/libs/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/libs/__pycache__/translation.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/libs/translation.py,sha256=LiiMZUxVbAmUy71mVA-PyEkxwYrCAOcjeiDnlbCSPvQ,1411
|
||||
kivymd/tools/patterns/MVC/messages.pot,sha256=2cutqkylhtiY07tkXzE8yNqpux9eeoW3tdeoEbXdB1Y,582
|
||||
kivymd/tools/patterns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/patterns/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/__pycache__/add_view.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/__pycache__/create_project.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/add_view.py,sha256=4J41yOosi9KkNrMBI6h6yJ_0LoncdJzmJDy-iShaArk,6576
|
||||
kivymd/tools/patterns/create_project.py,sha256=x3g37U3Dbk-ivUJ_aGgwvjpwBkyM4zIcPF3Bcyw1ASQ,39373
|
||||
kivymd/uix/__init__.py,sha256=iYE45157qMg3owm8X0BMVuStS8kU6bFyWr04VTjIPcw,2892
|
||||
kivymd/uix/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/anchorlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/boxlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/carousel.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/circularlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/floatlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/gridlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/hero.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/recyclegridlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/recycleview.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/relativelayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/responsivelayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/screen.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/screenmanager.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/scrollview.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/stacklayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/taptargetview.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/widget.cpython-311.pyc,,
|
||||
kivymd/uix/anchorlayout.py,sha256=lrw9QiThjutmOTQix71atzJKP_cauoGUykiLdLfW99Q,1025
|
||||
kivymd/uix/backdrop/__init__.py,sha256=_9OLuWRMGEDqI1-ix6u0VJbuOpHJ6FLnJuODPYw2Eko,46
|
||||
kivymd/uix/backdrop/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/backdrop/__pycache__/backdrop.cpython-311.pyc,,
|
||||
kivymd/uix/backdrop/backdrop.kv,sha256=L0w8al59AMQlkUrqjJsX1o7pMC9S70zt5KwulOON18g,1407
|
||||
kivymd/uix/backdrop/backdrop.py,sha256=eiJyqjY3hT-CFUVUX97f-2-npPxsr4TfsECjTGIrhTE,16311
|
||||
kivymd/uix/banner/__init__.py,sha256=JimxFPqzTx8l1pwI4rknb8r3QiDhLcI9xb4pIfpselo,42
|
||||
kivymd/uix/banner/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/banner/__pycache__/banner.cpython-311.pyc,,
|
||||
kivymd/uix/banner/banner.kv,sha256=Mb5jq9VSLr0A4DqvTpSF9tKKh-JvpiN3oM9jKh8V5vs,1679
|
||||
kivymd/uix/banner/banner.py,sha256=E99gUMVE51jKNpTG3gyQKVAiaxQ4yeIznLzcGeOO4-A,12053
|
||||
kivymd/uix/behaviors/__init__.py,sha256=htl-U1oP2Tkmgul6gvkWV54LOzrTKe_jhwpT7dd372M,979
|
||||
kivymd/uix/behaviors/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/backgroundcolor_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/declarative_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/elevation.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/focus_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/hover_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/magic_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/motion_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/ripple_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/rotate_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/scale_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/stencil_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/toggle_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/touch_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/backgroundcolor_behavior.py,sha256=a8Oa41plDW4G4tiIL-QNLc963VsW-5u7BuwvCTFfl3s,8962
|
||||
kivymd/uix/behaviors/declarative_behavior.py,sha256=MI2KelKtrkhXMIXoqu53ivHf_Zn7CQNQUtRHiwHpe9A,10236
|
||||
kivymd/uix/behaviors/elevation.py,sha256=cdQgXKUxM1-2YS1H3IM2yssc5FUQOJtptccMn7xQZvo,22211
|
||||
kivymd/uix/behaviors/focus_behavior.py,sha256=fhqtqiTMEopNMP7-_xWTVTtwiuKS9pkjnIIirjm3PcA,4240
|
||||
kivymd/uix/behaviors/hover_behavior.py,sha256=mhogwYWLTxJzqrO_Yk38v5BhYY7rFhVZ1xQfcEeXGq8,7616
|
||||
kivymd/uix/behaviors/magic_behavior.py,sha256=wwN40b_0NTG3Dopdhqt89PXYqY5mXSM4lY2xuIk1v9Q,4570
|
||||
kivymd/uix/behaviors/motion_behavior.py,sha256=15cwgX1UWlS2TJVBVOCia5FhYEOyr6PG9OPJRn_6aqU,7342
|
||||
kivymd/uix/behaviors/ripple_behavior.py,sha256=LoS_lIpYlzIGQWAX1FNh_56EmZ5NE_FsxNdQWaVvYZg,16658
|
||||
kivymd/uix/behaviors/rotate_behavior.py,sha256=Z8Ux_UwKZHoeu-cCl8hNc2EDVgC_hWni-ld8BpbL1uE,3268
|
||||
kivymd/uix/behaviors/scale_behavior.py,sha256=2ONpA7LKW5UhNI-ibBLlyQtOP_xyHDkasNxmqLO-z_c,4062
|
||||
kivymd/uix/behaviors/stencil_behavior.py,sha256=k6S2fwKMrxsFQKgI36q5-zCaQZ6LMFmv97jDPXD8e2Y,3017
|
||||
kivymd/uix/behaviors/toggle_behavior.py,sha256=wGi3INtIa_6chPcJMekye5jTaGkLMbwPtmW0aFdL_fE,8451
|
||||
kivymd/uix/behaviors/touch_behavior.py,sha256=uSP_AE8QuU_t_Q_Q-lUxuxh_Ms8TOZCewxUvSDsj04U,2475
|
||||
kivymd/uix/bottomnavigation/__init__.py,sha256=oAt66rNw5qp5ueAqLxfXs2iPpp68IWp5jVEnY3xMkwQ,85
|
||||
kivymd/uix/bottomnavigation/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/bottomnavigation/__pycache__/bottomnavigation.cpython-311.pyc,,
|
||||
kivymd/uix/bottomnavigation/bottomnavigation.kv,sha256=7swDhIg8quCg7Vtm01jy1BnEtMx9qvMueFT88QBnkvU,4082
|
||||
kivymd/uix/bottomnavigation/bottomnavigation.py,sha256=BpVHD3XKnkZe2tLvNDn6Z23Kuq7l0lneY3TrRMK1pec,27138
|
||||
kivymd/uix/bottomsheet/__init__.py,sha256=VhYEno0toWnl6OmaxgYT7as1MIXYXLxhZHnTTrZ4TAY,255
|
||||
kivymd/uix/bottomsheet/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/bottomsheet/__pycache__/bottomsheet.cpython-311.pyc,,
|
||||
kivymd/uix/bottomsheet/bottomsheet.kv,sha256=83LTxxGThfDnPN1ATAw4zU0_LB-jmERiFQyC8b3iedA,1047
|
||||
kivymd/uix/bottomsheet/bottomsheet.py,sha256=zv5Y3x7e3YdqnL_RJgMunpRrSd5BP4Oro7iO-QDLC7w,36674
|
||||
kivymd/uix/boxlayout.py,sha256=cWQuo2HJNnCoeY-HwXxsxZrv0YXR-IE4GGf8ymPVswI,1694
|
||||
kivymd/uix/button/__init__.py,sha256=hflz-R7RufS_l2SBqnwYtmAV5WAnsnmD2jwr3OQeusc,385
|
||||
kivymd/uix/button/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/button/__pycache__/button.cpython-311.pyc,,
|
||||
kivymd/uix/button/button.kv,sha256=Z4AKWPAoRfPUflwHeUH81NpXSGZKrsiuSbAuy5GDTTA,6614
|
||||
kivymd/uix/button/button.py,sha256=O4u_5Ph7bVeicDk_fxc1HTiCzIZUr8rTGoyTIiPDnMU,75206
|
||||
kivymd/uix/card/__init__.py,sha256=DRguLhBrd_iil2DlVN7R8Euq711j6M81Hbkyfv9f4fs,130
|
||||
kivymd/uix/card/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/card/__pycache__/card.cpython-311.pyc,,
|
||||
kivymd/uix/card/card.kv,sha256=dMijf_VPWw1Vc6cM7LdCf3KCFEcHtC9QnAU2icmAeXk,192
|
||||
kivymd/uix/card/card.py,sha256=cVm6dSVT6bUsWjyh2MbXUTPbCbgpGR7ekLWQb2afIJc,33665
|
||||
kivymd/uix/carousel.py,sha256=371UKLVsrndHekRbtAgnEtUU_ZQVDdzgXFJfhpJIr1c,7044
|
||||
kivymd/uix/chip/__init__.py,sha256=gpNRYAODC-ip0mjg36rcw8SMTQh_-223GPQsPPY65OE,50
|
||||
kivymd/uix/chip/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/chip/__pycache__/chip.cpython-311.pyc,,
|
||||
kivymd/uix/chip/chip.kv,sha256=2ZUAugzJb3yw-Mf0rw7yKA07foheqB1gS9LhK0WQrZ4,1035
|
||||
kivymd/uix/chip/chip.py,sha256=a7xTg3jyQFhsJrmjBI2eVqBwhIJSY2UdjAufll0A75U,34934
|
||||
kivymd/uix/circularlayout.py,sha256=rG9QqC_1PoEqNhHCS8OK4oLcSvqBC2RSRZh9BHc8I0w,5506
|
||||
kivymd/uix/controllers/__init__.py,sha256=WNbi76mp899CTLeSZUnVJ0b5gSeUMJ9ganvmhEcNR40,231
|
||||
kivymd/uix/controllers/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/controllers/__pycache__/windowcontroller.cpython-311.pyc,,
|
||||
kivymd/uix/controllers/windowcontroller.py,sha256=msVZQJwaekkIw4XUECXWAMOAsXw5NkFe38xIel1wG84,2335
|
||||
kivymd/uix/datatables/__init__.py,sha256=UQ_0tOrl5F-VSHQUpByyFw5LQzKTFAnWBNrUAnmPN2k,49
|
||||
kivymd/uix/datatables/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/datatables/__pycache__/datatables.cpython-311.pyc,,
|
||||
kivymd/uix/datatables/datatables.kv,sha256=4u8JMT66faxazxGdVDAbHF3aT_ioNQRN04O_asr5Si0,6558
|
||||
kivymd/uix/datatables/datatables.py,sha256=OfoHMXPE1LYaNF03th3M8dMp_ZcgNV4wuQF0FTL5yc0,71271
|
||||
kivymd/uix/dialog/__init__.py,sha256=GcaS3dDIcvTSuJ9hYwNAsSKe89OKj1F7DEyu2j2HxCw,54
|
||||
kivymd/uix/dialog/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/dialog/__pycache__/dialog.cpython-311.pyc,,
|
||||
kivymd/uix/dialog/dialog.kv,sha256=0afWO3x6OXEsOUHUSdxO7q3m6mOU7HlizEal4FCBCYQ,2155
|
||||
kivymd/uix/dialog/dialog.py,sha256=YjK1ozUeZ1HQpzSQvZQav0D3SWfavFJwB6g6vZlAaTs,21874
|
||||
kivymd/uix/dropdownitem/__init__.py,sha256=KyXd1v0gdOilE48z8Sp-Pqig_KJOdl0fyzWY8gPjA0U,54
|
||||
kivymd/uix/dropdownitem/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/dropdownitem/__pycache__/dropdownitem.cpython-311.pyc,,
|
||||
kivymd/uix/dropdownitem/dropdownitem.kv,sha256=w46i9i807rDqqk1iZyBTqf2wzrt4jtRv2TKxyZaWxGI,906
|
||||
kivymd/uix/dropdownitem/dropdownitem.py,sha256=uVveaPSF27cjPCe8WiVp1zjfIIqU36e79NIUPhn193U,2633
|
||||
kivymd/uix/expansionpanel/__init__.py,sha256=fOxf-XTewfdiUEsKs4O8-ZFCLxG_zC12oWWIIGtO1Xc,182
|
||||
kivymd/uix/expansionpanel/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/expansionpanel/__pycache__/expansionpanel.cpython-311.pyc,,
|
||||
kivymd/uix/expansionpanel/expansionpanel.kv,sha256=ImVy4Axm1-EqLYn52AR5gE6ypSE_jiDjQLz-FnrNZQM,355
|
||||
kivymd/uix/expansionpanel/expansionpanel.py,sha256=wPMCjQaN8HE1KwUd7-t97gI-xu-SxwZQAwrh4cRC55M,14229
|
||||
kivymd/uix/filemanager/__init__.py,sha256=TR0eAXbR-lzZUQLiVcGcVp5D1myeiLoXGpSWZitrWKI,52
|
||||
kivymd/uix/filemanager/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/filemanager/__pycache__/filemanager.cpython-311.pyc,,
|
||||
kivymd/uix/filemanager/filemanager.kv,sha256=PCTjXk8I4yeZSwio4YwyXf2DkXDT0Uz92d0Bk16zKq8,2863
|
||||
kivymd/uix/filemanager/filemanager.py,sha256=k_NztZeWL75BPtCCf2e-cNuKgjiRlp6FRjWg9Z6ekKc,25313
|
||||
kivymd/uix/fitimage/__init__.py,sha256=BVf16byn839UfzikgsfJj_s5xH0PjGgU9gUuetb1dsU,44
|
||||
kivymd/uix/fitimage/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/fitimage/__pycache__/fitimage.cpython-311.pyc,,
|
||||
kivymd/uix/fitimage/fitimage.py,sha256=o2RLSBlr9ahCeZZkmp1zyuhzPN24NKkSknWajBN1dhg,6516
|
||||
kivymd/uix/floatlayout.py,sha256=CUeL6e-k20Jg2zqWBL9sMvGzWgO7nNAsTd5So0UMgd4,1202
|
||||
kivymd/uix/gridlayout.py,sha256=HULtL-Zg0V_qN_7PZxe9Rr7jEuvGrnRA398tVZQSPkc,1671
|
||||
kivymd/uix/hero.py,sha256=P-rsRLF7OL5zHWpw6dgMRsWWWboXghyhFUw9GWpVu-I,17379
|
||||
kivymd/uix/imagelist/__init__.py,sha256=O4MQYEuq07GdwTytyXcE48Frp5Cy86zd8sqaYTPMFnk,47
|
||||
kivymd/uix/imagelist/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/imagelist/__pycache__/imagelist.cpython-311.pyc,,
|
||||
kivymd/uix/imagelist/imagelist.kv,sha256=lRzJikpng24-TNQl2olHbgg4CUUKnwu8XEhaOY2ts1M,921
|
||||
kivymd/uix/imagelist/imagelist.py,sha256=DkSpHgpVgN1hHlFYQddWW-BxcxcuXCg90KEq0C-q3mU,8000
|
||||
kivymd/uix/label/__init__.py,sha256=DHLIPzLH5Uq0ChimIQIUVHQ42iAilC-F2xYzWqeqiXY,48
|
||||
kivymd/uix/label/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/label/__pycache__/label.cpython-311.pyc,,
|
||||
kivymd/uix/label/label.kv,sha256=pQa0LHD7haztYEiOKnKLYiK4NbbKe_gwUQWrbPPDKb0,2055
|
||||
kivymd/uix/label/label.py,sha256=h_kFBoEXrzPlf9poja-lyLOTJVcgIq9kyPGnKu3lPXI,27892
|
||||
kivymd/uix/list/__init__.py,sha256=vaqucd89ij0ssXVPdvdl9bmsiXWbsUX7uZi-qT6QzIc,788
|
||||
kivymd/uix/list/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/list/__pycache__/list.cpython-311.pyc,,
|
||||
kivymd/uix/list/list.kv,sha256=7tm7YcnXRURc_CHXRTYSw9zNObeviasG7arladTBZ5U,4715
|
||||
kivymd/uix/list/list.py,sha256=ymc8r18Eex4lNKAyp1UjbyWBFFKw-yaBe9WBy3dQDcs,45486
|
||||
kivymd/uix/menu/__init__.py,sha256=2a7cHJKvQmKiqu4_YWWQMF96owFFkRiMnEPX2R_kMbA,46
|
||||
kivymd/uix/menu/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/menu/__pycache__/menu.cpython-311.pyc,,
|
||||
kivymd/uix/menu/menu.kv,sha256=ZJ3j-XggUkcEOsEdYRlMnsGit9jZQ1VvKICBgovy2DA,14002
|
||||
kivymd/uix/menu/menu.py,sha256=7dnA5hi2CXLWhlrRsBKj59J1FWthaBs2JneIdDzioTw,40950
|
||||
kivymd/uix/navigationdrawer/__init__.py,sha256=YFHzu07n8mPUmONaMYhwkx5OzK-J5mrzi109Mfj8S8o,240
|
||||
kivymd/uix/navigationdrawer/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/navigationdrawer/__pycache__/navigationdrawer.cpython-311.pyc,,
|
||||
kivymd/uix/navigationdrawer/navigationdrawer.kv,sha256=Sh9d6kvvLONwvFSGJyXFGJ_hzsMhBekMNVnc4Kv5J9U,3586
|
||||
kivymd/uix/navigationdrawer/navigationdrawer.py,sha256=zg1m9K_Y2oYRgd5b2lvHAq5QxG5qc2Mzqpco0jTOcJA,46331
|
||||
kivymd/uix/navigationrail/__init__.py,sha256=4chGrBkw62foF0LYSBv7fkL9E5MvwUExi7-VG_cSbtM,155
|
||||
kivymd/uix/navigationrail/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/navigationrail/__pycache__/navigationrail.cpython-311.pyc,,
|
||||
kivymd/uix/navigationrail/navigationrail.kv,sha256=xDomPL_lSc_ssaPUQsOfQizMZc5Gc3ZBFbAQO2dyN0o,5588
|
||||
kivymd/uix/navigationrail/navigationrail.py,sha256=Vr8PjkkbPkCjuvYAW_3Wd-Az9IxwOUWPSOACsQ3dz5k,42888
|
||||
kivymd/uix/pickers/__init__.py,sha256=7FvCnbWhjGmwOTqCMFrzTyPOa77Yytkrger5Vz7nOqI,152
|
||||
kivymd/uix/pickers/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/colorpicker/__init__.py,sha256=7HqXXTyARgnSu9I26V08PEj53OZw34MrOGmymOFOPJs,52
|
||||
kivymd/uix/pickers/colorpicker/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/colorpicker/__pycache__/colorpicker.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/colorpicker/colorpicker.kv,sha256=mbHuEnvYGd97CUJLfrnjZ0qCuJZ8SR14sj9ztUOI-yQ,8272
|
||||
kivymd/uix/pickers/colorpicker/colorpicker.py,sha256=ucG1wqZWrG2WBTcUp3kE3uzfVKNMGEMCI4BqOgvEg38,22794
|
||||
kivymd/uix/pickers/datepicker/__init__.py,sha256=-_u_4EUwtwFtCh5E58y7aMi4XCK4CJi0R5cZmDptDaE,107
|
||||
kivymd/uix/pickers/datepicker/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/datepicker/__pycache__/datepicker.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/datepicker/datepicker.kv,sha256=yk5zBwAZZJ_LOADiGBNLVNnx73Y-D58NoqCqooP0vss,14321
|
||||
kivymd/uix/pickers/datepicker/datepicker.py,sha256=MBsMiUwYOIumJnI_Dtmhu3UOESv1CjMDWhI84w0SCvw,50563
|
||||
kivymd/uix/pickers/timepicker/__init__.py,sha256=ZWB8oTmsgA1Uy5zv2I5QmwZ2N3spznS0anLvK-aytVQ,50
|
||||
kivymd/uix/pickers/timepicker/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/timepicker/__pycache__/timepicker.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/timepicker/timepicker.kv,sha256=1REiI_DBcT9868oWTAK1BmPhFn0LltmR9Lwq0EHVs-g,10618
|
||||
kivymd/uix/pickers/timepicker/timepicker.py,sha256=H3qUswLdaBQ63zbF19bt0y-WiHmCGUBNQt2Qh-_sUlY,25249
|
||||
kivymd/uix/progressbar/__init__.py,sha256=YLT-xcOX3Z_O8py_ENTH9wFIletQiMJ5vUVK6nr3Qco,52
|
||||
kivymd/uix/progressbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/progressbar/__pycache__/progressbar.cpython-311.pyc,,
|
||||
kivymd/uix/progressbar/progressbar.kv,sha256=p0LzgpX6k_hd-r_CUTbQA2K2yO7M7SIyW8nx-0B8r4Q,1423
|
||||
kivymd/uix/progressbar/progressbar.py,sha256=5EYTXRxrV3JkCSidbmXRXt9FNt9tBF3gTTvGzOvh7cI,8523
|
||||
kivymd/uix/recyclegridlayout.py,sha256=gvtUVMG04EjsCw2wOPBWgGwu_anZS7buKjFAnZqVhyQ,1804
|
||||
kivymd/uix/recycleview.py,sha256=uBxnIU6FgjS44cE6K-Wqp4xel4tuV726_Vaa6W5f5tw,1008
|
||||
kivymd/uix/refreshlayout/__init__.py,sha256=r6yH7AYvn831mRtdu6KN_p4L42JBJh2qKpNIuHyckao,66
|
||||
kivymd/uix/refreshlayout/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/refreshlayout/__pycache__/refreshlayout.cpython-311.pyc,,
|
||||
kivymd/uix/refreshlayout/refreshlayout.kv,sha256=5jMCt1kBIA91ll4rWNYZ33fheUvMxph3uUBAj0BhdH0,602
|
||||
kivymd/uix/refreshlayout/refreshlayout.py,sha256=lHL1nGOpHWiPqjD7r0dkSabhR6d_Qzis7xtuhpr8RjA,9638
|
||||
kivymd/uix/relativelayout.py,sha256=hYfETginxPuQvYU37w22E184wZD_A-eTfRgFw5SqwAE,1062
|
||||
kivymd/uix/responsivelayout.py,sha256=N1GMNejHlNssk8ZpC9kMuZELuWywUs9Dms_AzHcpU1Q,5409
|
||||
kivymd/uix/screen.py,sha256=WhRKHyC8o7t8c_lgBfX4_hpIz7L2kArKYSAVM7MA0cI,2280
|
||||
kivymd/uix/screenmanager.py,sha256=YD3pJ79LdINVEH2QS1zC-FpPQcg3m4mSZakYKh3a9Wc,5091
|
||||
kivymd/uix/scrollview.py,sha256=fKCNMqezyYpNlNrYXSueRQ7ISy1Qd6PD74INrPURvdE,948
|
||||
kivymd/uix/segmentedbutton/__init__.py,sha256=WpaigD2XLpcvKEEAqWoJTZiZRy3S4J47_KU36FhNPNc,96
|
||||
kivymd/uix/segmentedbutton/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/segmentedbutton/__pycache__/segmentedbutton.cpython-311.pyc,,
|
||||
kivymd/uix/segmentedbutton/segmentedbutton.kv,sha256=1cE5UXZOI46aItAYYpM0cJdgWgPXc6dcqKMFG_0ZD2Y,840
|
||||
kivymd/uix/segmentedbutton/segmentedbutton.py,sha256=JjKLG0GO2AVyk-EJQwD8EBeKaaV3Rrk0tr_pkJRRs7Q,19122
|
||||
kivymd/uix/segmentedcontrol/__init__.py,sha256=z8ZZj8D5wDxyr__hqHZjscxexIw8CRDkYX6Dl9tZxxs,99
|
||||
kivymd/uix/segmentedcontrol/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/segmentedcontrol/__pycache__/segmentedcontrol.cpython-311.pyc,,
|
||||
kivymd/uix/segmentedcontrol/segmentedcontrol.kv,sha256=jhZiaohChE-DqhZC-hA3_HHxJqQ08eEGmGSF7euyA4A,959
|
||||
kivymd/uix/segmentedcontrol/segmentedcontrol.py,sha256=AJQyaQN0et40snqGp9A1ag8HWRMEJqj5PeZ5hrit_sA,11084
|
||||
kivymd/uix/selection/__init__.py,sha256=12J_d15BRpSKymQbsMwSZ51Bo_5FauKwaY-d0z_2uAk,52
|
||||
kivymd/uix/selection/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/selection/__pycache__/selection.cpython-311.pyc,,
|
||||
kivymd/uix/selection/selection.kv,sha256=lpA5YyksPcf2tJmmE754eOGsTRkNhLa0IGHAjmlXD70,379
|
||||
kivymd/uix/selection/selection.py,sha256=0j-12oo2dVzs-KZDJqHTLIIHDbLcQNerZzds-NFgq8Y,21378
|
||||
kivymd/uix/selectioncontrol/__init__.py,sha256=n1yw1X7ccriTWj1GPN-V9LvFXgxuFNfEy6uRHPyhQGA,71
|
||||
kivymd/uix/selectioncontrol/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/selectioncontrol/__pycache__/selectioncontrol.cpython-311.pyc,,
|
||||
kivymd/uix/selectioncontrol/selectioncontrol.kv,sha256=4_Xlvgjpfi_3OmC2BPE7eZ_P4XRRGJw5AcmlXWsf1C0,4873
|
||||
kivymd/uix/selectioncontrol/selectioncontrol.py,sha256=Nu-eGtbmgjcaI8A4Ke7nleFOXqPnWuB4q0GTe7aZ4Yc,27724
|
||||
kivymd/uix/slider/__init__.py,sha256=TQwpwsmQElirZufuKGck-QZuYLe1V1Vd2HVUwSnPx8k,42
|
||||
kivymd/uix/slider/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/slider/__pycache__/slider.cpython-311.pyc,,
|
||||
kivymd/uix/slider/slider.kv,sha256=ddb5p6jonpz3R9Lqg4tfKqKVTTy2s0_pkURnwUovmtA,6144
|
||||
kivymd/uix/slider/slider.py,sha256=nmYRtmX0OOnokQFr-xbWgomK6DnkoBjQXSfe6SjNcaU,8502
|
||||
kivymd/uix/sliverappbar/__init__.py,sha256=axuqy95RR0oDLXpBtH3EauoTZN56p6EAp3JFBC-MoYI,103
|
||||
kivymd/uix/sliverappbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/sliverappbar/__pycache__/sliverappbar.cpython-311.pyc,,
|
||||
kivymd/uix/sliverappbar/sliverappbar.kv,sha256=_Ck4u11h0HJUQa4gNwEkCBR28xHspd6KNhZ-1oHPzac,1208
|
||||
kivymd/uix/sliverappbar/sliverappbar.py,sha256=ABfFDECbD9dbefONxHxKd6qFDhS-WNGOtlZE81r5VPs,14833
|
||||
kivymd/uix/snackbar/__init__.py,sha256=wG6Czix7Tb-3f69MAZqdxy2oY_-lQF8mYHQ_rueZ2lI,124
|
||||
kivymd/uix/snackbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/snackbar/__pycache__/snackbar.cpython-311.pyc,,
|
||||
kivymd/uix/snackbar/snackbar.kv,sha256=M0HYjCKUR6-aSrleQaqVjXzrO2tbhCTgyuYTgn0s3S8,761
|
||||
kivymd/uix/snackbar/snackbar.py,sha256=9alYRqr9yxqFlMPHbuUrXCCcron2VOZiZSA_7hZz9gA,14432
|
||||
kivymd/uix/spinner/__init__.py,sha256=QI6bPGhsNGXXrXR-fPvEkbEfTUF3V3tY1wHTx_zZAJI,44
|
||||
kivymd/uix/spinner/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/spinner/__pycache__/spinner.cpython-311.pyc,,
|
||||
kivymd/uix/spinner/spinner.kv,sha256=UerB-S-STJiBnjZw6HsRqAGCNxLw0bvfu5EegQQpzDQ,521
|
||||
kivymd/uix/spinner/spinner.py,sha256=PCRVUq07-ZP0ADAWSz5vATEZE9Blx62onzKc_AdOoNs,9121
|
||||
kivymd/uix/stacklayout.py,sha256=VE-OemocOjID3yVA6cwOt1KUn64NwdVCgVA1ssD1nAM,1724
|
||||
kivymd/uix/swiper/__init__.py,sha256=yjVyswA0HfoLRx9UW7k_GR497shvH5EthBbQk8CoU_4,43
|
||||
kivymd/uix/swiper/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/swiper/__pycache__/swiper.cpython-311.pyc,,
|
||||
kivymd/uix/swiper/swiper.kv,sha256=iTaioAm-1WWmrGV4mqTizz3f4Qobv8WJZT-cwhEqyD0,291
|
||||
kivymd/uix/swiper/swiper.py,sha256=4Wwnj_jFvNhRlyPFvyXyPt01ZHeJt_25KcyjeZAB-II,14656
|
||||
kivymd/uix/tab/__init__.py,sha256=ui2pD_Y163wYI19O3JdSlVHhXUs83FHQUrZFi9FcGHs,62
|
||||
kivymd/uix/tab/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/tab/__pycache__/tab.cpython-311.pyc,,
|
||||
kivymd/uix/tab/tab.kv,sha256=UuHLg4fS1CwROB4wwjWLxOmFk7xU5W78qWLZxSMMvSM,3809
|
||||
kivymd/uix/tab/tab.py,sha256=WnsmGmgjPWTYbtuNkOLRZSFRciGZwHOaaAWS_zHJaNM,67730
|
||||
kivymd/uix/taptargetview.py,sha256=8oIPH-HC-kxSOsKua0NJqeacb1oxjNIExPDFz46p3-k,26995
|
||||
kivymd/uix/templates/__init__.py,sha256=N58Ktx4cjBdiBsabyRkeJKOczHNQCGhWpQV_bGEy6CY,216
|
||||
kivymd/uix/templates/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/templates/rotatewidget/__init__.py,sha256=44Zf8a5sc5FSSfYX2RTWLAikbOzgi9g3Sm_LhroTsv4,39
|
||||
kivymd/uix/templates/rotatewidget/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/templates/rotatewidget/__pycache__/rotatewidget.cpython-311.pyc,,
|
||||
kivymd/uix/templates/rotatewidget/rotatewidget.py,sha256=Ea9ImstSgTxTeNKikN7GQlu_tWcgjaAkE-iMJpuYAr4,764
|
||||
kivymd/uix/templates/scalewidget/__init__.py,sha256=QeR6z6AC4N1ylUnh0aI2cBAVDuOhsqUNF0Ux9Dza2zQ,37
|
||||
kivymd/uix/templates/scalewidget/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/templates/scalewidget/__pycache__/scalewidget.cpython-311.pyc,,
|
||||
kivymd/uix/templates/scalewidget/scalewidget.py,sha256=xnV2r-bw3gwvhyiwWtueNkCODC7uTg2sSJCNwlTSWuA,804
|
||||
kivymd/uix/templates/stencilwidget/__init__.py,sha256=1hoHSMc_CudX4ixsz4dlvAPQi_ppki1ht1zi7oSza_g,41
|
||||
kivymd/uix/templates/stencilwidget/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/templates/stencilwidget/__pycache__/stencilwidget.cpython-311.pyc,,
|
||||
kivymd/uix/templates/stencilwidget/stencilwidget.py,sha256=VbMTYBRJXH1BGh-1jxFIXLZVGOfVj47K-1DHCzCQG4U,843
|
||||
kivymd/uix/textfield/__init__.py,sha256=TsquVODAqOW9KRaVdZEwDSuj84xNu3btukztMO1u-R8,64
|
||||
kivymd/uix/textfield/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/textfield/__pycache__/textfield.cpython-311.pyc,,
|
||||
kivymd/uix/textfield/textfield.kv,sha256=1YRvhffqhGvrTT6ak7-9Q8igtweGh3heUkudK5vAsog,11995
|
||||
kivymd/uix/textfield/textfield.py,sha256=ZgKSMcO0rPjbgbhZ9sKDtCEZ4UsQS9AlUhaJkwgS9fc,66314
|
||||
kivymd/uix/toolbar/__init__.py,sha256=ERxUgGcxjesHxwJoadRRiboL22K2gdMaIu1h57GJCcM,163
|
||||
kivymd/uix/toolbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/toolbar/__pycache__/toolbar.cpython-311.pyc,,
|
||||
kivymd/uix/toolbar/toolbar.kv,sha256=XTLAQDaSN1lMW350XzY1Wy9gpIm-GVWQzuBhngsr2-g,3569
|
||||
kivymd/uix/toolbar/toolbar.py,sha256=qOySilG3qNjHwyFEKfcqWEzbTjeLLIEc0h1JwM9QwIU,67947
|
||||
kivymd/uix/tooltip/__init__.py,sha256=TrHnzd6U1iKu-TzPaBG4jPRL7Cdaa91FqQQiS37ce9o,64
|
||||
kivymd/uix/tooltip/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/tooltip/__pycache__/tooltip.cpython-311.pyc,,
|
||||
kivymd/uix/tooltip/tooltip.kv,sha256=eiA1FwuWCUm8BTdTilYPS01V2lDoVh0mW-BkeEldGPY,1171
|
||||
kivymd/uix/tooltip/tooltip.py,sha256=_-crrT-DxKx12VGfCBqe3sV_nIPTmdklEDRGhngAl4k,10861
|
||||
kivymd/uix/transition/__init__.py,sha256=QA3XDj483c_iPrbiVHdkvVZhCKPu495dr5_6hBZRLgw,113
|
||||
kivymd/uix/transition/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/transition/__pycache__/transition.cpython-311.pyc,,
|
||||
kivymd/uix/transition/transition.py,sha256=xwN5NcfogHwl4xeuzA1R49Vu88LBpuwmmv2N394UWV0,11349
|
||||
kivymd/uix/widget.py,sha256=6oQLzQuKgp4Rnulq63Zlw4fPjJ0RmkttrFx7NJbCMug,1074
|
||||
kivymd/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/utils/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/utils/__pycache__/asynckivy.cpython-311.pyc,,
|
||||
kivymd/utils/__pycache__/fpsmonitor.cpython-311.pyc,,
|
||||
kivymd/utils/__pycache__/set_bars_colors.cpython-311.pyc,,
|
||||
kivymd/utils/asynckivy.py,sha256=veVrps6-mxT5JFgRpwzZ18_HFzx9CeG4IZomp8cTtyQ,1544
|
||||
kivymd/utils/fpsmonitor.py,sha256=QzWJs1lr9SIk2NDVeDUC2HRSyMXNXTWB39HvLDtL0vI,1024
|
||||
kivymd/utils/set_bars_colors.py,sha256=uhCQdrRhRW-P--5D5MJR6rcauOA8wmiFoapJJczkf14,4050
|
@ -0,0 +1 @@
|
||||
pip
|
@ -1,18 +1,7 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2022 Andrés Rodríguez and other contributors - KivyMD library up to version 0.1.2
|
||||
Copyright (c) 2022 KivyMD Team and other contributors - KivyMD library version 0.1.3 and higher
|
||||
|
||||
Other libraries used in the project:
|
||||
|
||||
Copyright (c) 2010-2022 Kivy Team and other contributors
|
||||
Copyright (c) 2022 Brian Knapp - Androidoast library
|
||||
Copyright (c) 2022 LogicalDash - stiffscroll library
|
||||
Copyright (c) 2022 Kivy Garden - tabs module
|
||||
Copyright (c) 2022 Nattōsai Mitō - asynckivy module
|
||||
Copyright (c) 2022 tshirtman - magic_behavior module
|
||||
Copyright (c) 2022 shashi278 - taptargetview module
|
||||
Copyright (c) 2022 Benedikt Zwölfer - fitimage module
|
||||
Copyright (c) 2024 Andrés Rodríguez and other contributors - KivyMD library up to version 0.1.2
|
||||
Copyright (c) 2024 KivyMD Team and other contributors - KivyMD library version 0.1.3 and higher
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
@ -1,6 +1,6 @@
|
||||
Metadata-Version: 2.1
|
||||
Name: kivymd
|
||||
Version: 1.2.0
|
||||
Version: 2.0.1.dev0
|
||||
Summary: Set of widgets for Kivy inspired by Google's Material Design
|
||||
Home-page: https://github.com/kivymd/KivyMD
|
||||
Author: Andres Rodriguez, fork author - Ivanov Yuri
|
||||
@ -40,8 +40,10 @@ Classifier: Topic :: Scientific/Engineering :: Visualization
|
||||
Requires-Python: >=3.7
|
||||
Description-Content-Type: text/markdown; charset=UTF-8
|
||||
License-File: LICENSE
|
||||
Requires-Dist: kivy>=2.2.0
|
||||
Requires-Dist: kivy>=2.3.0
|
||||
Requires-Dist: pillow
|
||||
Requires-Dist: materialyoucolor>=2.0.7
|
||||
Requires-Dist: asynckivy<0.7,>=0.6
|
||||
Provides-Extra: dev
|
||||
Requires-Dist: pre-commit; extra == "dev"
|
||||
Requires-Dist: black; extra == "dev"
|
||||
@ -54,14 +56,14 @@ Requires-Dist: pytest-timeout; extra == "dev"
|
||||
Requires-Dist: coveralls; extra == "dev"
|
||||
Requires-Dist: pyinstaller[hook_testing]; extra == "dev"
|
||||
Provides-Extra: docs
|
||||
Requires-Dist: sphinx; extra == "docs"
|
||||
Requires-Dist: sphinx-autoapi==1.4.0; extra == "docs"
|
||||
Requires-Dist: furo; extra == "docs"
|
||||
Requires-Dist: sphinx==7.3.7; extra == "docs"
|
||||
Requires-Dist: sphinx-autoapi==3.0.0; extra == "docs"
|
||||
Requires-Dist: sphinx-book-theme; extra == "docs"
|
||||
Requires-Dist: sphinx-notfound-page; extra == "docs"
|
||||
Requires-Dist: sphinx-copybutton; extra == "docs"
|
||||
Requires-Dist: sphinx-tabs; extra == "docs"
|
||||
|
||||
# KivyMD [1.2.0](https://kivymd.readthedocs.io/en/latest/changelog/index.html)
|
||||
# KivyMD [2.0.0](https://kivymd.readthedocs.io/en/latest/changelog/index.html)
|
||||
|
||||
<img align="right" height="256" src="https://github.com/kivymd/internal/raw/main/logo/kivymd_logo_blue.png"/>
|
||||
|
||||
@ -106,15 +108,16 @@ may be offered to you without asking too.
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
pip install kivymd==1.2.0
|
||||
pip install kivymd==2.0.0
|
||||
```
|
||||
|
||||
### Dependencies:
|
||||
|
||||
- [Kivy](https://github.com/kivy/kivy) >= 2.2.0 ([Installation](https://kivy.org/doc/stable/gettingstarted/installation.html))
|
||||
- [Kivy](https://github.com/kivy/kivy) >= 2.3.0 ([Installation](https://kivy.org/doc/stable/gettingstarted/installation.html))
|
||||
- [Python 3.7+](https://www.python.org/)
|
||||
- [Pillow](https://github.com/python-pillow/Pillow/)
|
||||
- [MaterialColor](https://github.com/T-Dynamos/materialyoucolor-pyhton)
|
||||
- [MaterialColor](https://github.com/T-Dynamos/materialyoucolor-python)
|
||||
- [asynckivy](https://github.com/asyncgui/asynckivy)
|
||||
|
||||
### How to install
|
||||
|
||||
@ -144,25 +147,16 @@ pip install .
|
||||
use a shallow clone (`git clone https://github.com/kivymd/KivyMD.git --depth 1`)
|
||||
to save time. If you need full commit history, then remove `--depth 1`.
|
||||
|
||||
### How to fix a shader bug on an android device
|
||||
|
||||
Use `Kivy` from master branch or `Kivy` >= `2.2.0` and `KivyMD` (from master branch):
|
||||
|
||||
```bash
|
||||
pip install https://github.com/kivy/kivy/archive/master.zip
|
||||
pip install https://github.com/kivymd/KivyMD/archive/master.zip
|
||||
```
|
||||
|
||||
And use with `Buildozer`:
|
||||
|
||||
```ini
|
||||
requirements = kivy==master, https://github.com/kivymd/KivyMD/archive/master.zip
|
||||
```
|
||||
|
||||
### How to use with [Buildozer](https://github.com/kivy/buildozer)
|
||||
|
||||
```ini
|
||||
requirements = kivy==2.2.0, kivymd==1.2.0
|
||||
requirements = python3,
|
||||
kivy,
|
||||
https://github.com/kivymd/KivyMD/archive/master.zip,
|
||||
materialyoucolor,
|
||||
exceptiongroup,
|
||||
asyncgui,
|
||||
asynckivy
|
||||
```
|
||||
|
||||
This will download latest release version of KivyMD from [PyPI](https://pypi.org/project/kivymd).
|
||||
@ -171,7 +165,7 @@ If you want to use development version from [master](https://github.com/kivymd/K
|
||||
branch, you should specify link to zip archive:
|
||||
|
||||
```ini
|
||||
requirements = kivy==2.1.0, https://github.com/kivymd/KivyMD/archive/master.zip
|
||||
requirements = kivy, https://github.com/kivymd/KivyMD/archive/master.zip
|
||||
```
|
||||
|
||||
Do not forget to run `buildozer android clean` or remove `.buildozer` directory
|
||||
@ -356,6 +350,13 @@ and get your logo on our Readme with a link to your website.
|
||||
|
||||
<a href="https://opencollective.com/peter-surda?requireActive=false" target="_blank"><img src="https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/gold-sponsor-1.png?requireActive=false"></a>
|
||||
|
||||
<a href="https://route4me.com" target="_blank" style="display: inline-block; text-align: center;">
|
||||
<div style="text-align: center;">
|
||||
<img width="280" src="https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/route4me.png" alt="Best Route Planner"><br>
|
||||
Best Route Planner - Route Optimization Software
|
||||
</div>
|
||||
</a>
|
||||
|
||||
#### Backers
|
||||
|
||||
[Become a Backer](https://opencollective.com/kivymd/contribute/backer-16159) if you want to help develop this project.
|
@ -0,0 +1,332 @@
|
||||
../../../bin/kivymd.add_view,sha256=u2N52U9NKr85se5a66gdG5Old498YxKwDezJ-cwIZAY,266
|
||||
../../../bin/kivymd.create_project,sha256=6LnjVohJ7V3MZYfVCtWqtyHHaku6Io-y0pN1BFPmDAM,272
|
||||
../../../bin/kivymd.make_release,sha256=hKmHIsjNRMSeSS3A2PNqeer_kEliqi6NhzI9bmLc0Zo,269
|
||||
kivymd-2.0.1.dev0.dist-info/INSTALLER,sha256=zuuue4knoyJ-UwPPXg8fezS7VCrXJQrAP7zeNuwvFQg,4
|
||||
kivymd-2.0.1.dev0.dist-info/LICENSE,sha256=mAllwI3MAD8PljsyLcDu8ByZZYChrptzwCCA7pXK-70,1230
|
||||
kivymd-2.0.1.dev0.dist-info/METADATA,sha256=gFwEntEUBVZqXg9ZkEARN2wJJ3LRdRr49tfGGCKZt3c,15236
|
||||
kivymd-2.0.1.dev0.dist-info/RECORD,,
|
||||
kivymd-2.0.1.dev0.dist-info/REQUESTED,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd-2.0.1.dev0.dist-info/WHEEL,sha256=pL8R0wFFS65tNSRnaOVrsw9EOkOqxLrlUPenUYnJKNo,91
|
||||
kivymd-2.0.1.dev0.dist-info/direct_url.json,sha256=4K7_rCzsQAA6VPgFZkDLzO5m3GluAszqZihOmO2M4Lo,82
|
||||
kivymd-2.0.1.dev0.dist-info/entry_points.txt,sha256=1-yhsSzIhBNRiKNTmevRDT02q8qzg3upZcWAyrr880w,342
|
||||
kivymd-2.0.1.dev0.dist-info/top_level.txt,sha256=ABq82F4nFM8sy3xAhxiO5XXT_lAen0YqiDD29qRiPhc,7
|
||||
kivymd/__init__.py,sha256=d_a46HKOE97-WwIhBsv9yjAciPPx7yOLTeVzDynBVMI,1957
|
||||
kivymd/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/__pycache__/_version.cpython-311.pyc,,
|
||||
kivymd/__pycache__/animation.cpython-311.pyc,,
|
||||
kivymd/__pycache__/app.cpython-311.pyc,,
|
||||
kivymd/__pycache__/dynamic_color.cpython-311.pyc,,
|
||||
kivymd/__pycache__/factory_registers.cpython-311.pyc,,
|
||||
kivymd/__pycache__/font_definitions.cpython-311.pyc,,
|
||||
kivymd/__pycache__/icon_definitions.cpython-311.pyc,,
|
||||
kivymd/__pycache__/material_resources.cpython-311.pyc,,
|
||||
kivymd/__pycache__/theming.cpython-311.pyc,,
|
||||
kivymd/_version.py,sha256=6I20Wxx3c8MaIw5uF7UNh0yNERX7X5SkzUyMzzVsxno,115
|
||||
kivymd/animation.py,sha256=UMkBmLxjTlgz_tPVYrAGYxPIgVWAshAZivwlX_t983Q,6361
|
||||
kivymd/app.py,sha256=7As7g0jn_HnzRNDwPvulXGQtLd208x4Bm8dIeaRtEpE,4921
|
||||
kivymd/dynamic_color.py,sha256=jjlCogPmF5nmNHZzg9eG2YKZkoGtPUgaMb67RD5KGNo,16408
|
||||
kivymd/effects/__init__.py,sha256=ySU96kLlmPF4QB-hDa0WM_Y0Odq1MPSR568yI_hiaqI,24
|
||||
kivymd/effects/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/effects/stiffscroll/__init__.py,sha256=tkGDtFz6s7W3iFtHRDo6NYWadL85cn7GXKAQQfpiJRk,43
|
||||
kivymd/effects/stiffscroll/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/effects/stiffscroll/__pycache__/stiffscroll.cpython-311.pyc,,
|
||||
kivymd/effects/stiffscroll/stiffscroll.py,sha256=3bSj43xOzhBcBSn58iLUiaNWevlHuO8seklAyfvZsJE,7117
|
||||
kivymd/factory_registers.py,sha256=MEdyWS0DPv8XnVbLEbygs_8pB0DHoNLPxLO56Qn9GX0,7775
|
||||
kivymd/font_definitions.py,sha256=4WLZWIPY_hdCbY3a-8mPhL-0pmxMmWvBbzN9MDqRo4E,3774
|
||||
kivymd/fonts/Roboto-Black.ttf,sha256=Ws4NCDOrg_8Y6pTkp3RfkZxFiuTqvCmCGCJt9CdczU0,168060
|
||||
kivymd/fonts/Roboto-BlackItalic.ttf,sha256=iy-H-wj_S11i51PHUP4ykYE1hlAfoU3SWLGtC_ulM64,174108
|
||||
kivymd/fonts/Roboto-Bold.ttf,sha256=7GhaRhBSlv5GyHRNpKEc-BGLpsEScZQXZvelRt9qp8c,167336
|
||||
kivymd/fonts/Roboto-BoldItalic.ttf,sha256=Yd9Zf3PJHyOMvoj-PFNnAtEg0Ei3myX6D094GP0SOm8,171508
|
||||
kivymd/fonts/Roboto-Italic.ttf,sha256=meSoUGETbpngUpKe0NheNjhPulw0t3MTmo9kM5xgmUM,170504
|
||||
kivymd/fonts/Roboto-Light.ttf,sha256=xXbFBkInG82__-0E-S3I1qmB2vMAkU0KIMilpaVwFcc,167000
|
||||
kivymd/fonts/Roboto-LightItalic.ttf,sha256=pIQGImhU00_plkKlJKQ7L9Jqfb7KgC1RAKipjSDhtz0,173172
|
||||
kivymd/fonts/Roboto-Medium.ttf,sha256=nQ1VowO_0Tt5qHch9lGF6T8jXi13_jmLLcpnrFGZFfU,168644
|
||||
kivymd/fonts/Roboto-MediumItalic.ttf,sha256=0_MXyX9AA4ksuWm8_OjePcnWf7-W_a-miy41lTF7DZQ,173416
|
||||
kivymd/fonts/Roboto-Regular.ttf,sha256=ThR6tkuf322J0B9rjDygs83cWdYIqOIhj5olBLXJjhQ,168260
|
||||
kivymd/fonts/Roboto-Thin.ttf,sha256=ZySPfoxu2zzn73Ow8ApTSn9CwRFs72POIbIDW16XmgY,168488
|
||||
kivymd/fonts/Roboto-ThinItalic.ttf,sha256=KM4lGpnNV9AKmCJaj8tmtgtp2vELCUfH7E7VA8Iq_-8,172860
|
||||
kivymd/fonts/materialdesignicons-webfont.ttf,sha256=YeirpaTpgf4iz3yOi82-oAR251xiw38Bv37jM2HWhCg,1307660
|
||||
kivymd/icon_definitions.py,sha256=DAc0bD1hlaFBeIiHo5p2_HFzZHr7IUhBXC3t3SBRffQ,282946
|
||||
kivymd/images/folder.png,sha256=xY9uUYegh7hDzFI4iPEA-zyFBzq9IE007zaJGGY5JY0,2311
|
||||
kivymd/images/logo/kivymd-icon-128.png,sha256=VjWHaIJ-MSyP7ZnM25xgBfp_wG4vbQhr8B8QOTcXeaM,19826
|
||||
kivymd/images/logo/kivymd-icon-256.png,sha256=5iJVryvz0D-IvqLGTsaeJlYhZYk2R7OxskKiNgw25Ks,31943
|
||||
kivymd/images/logo/kivymd-icon-512.png,sha256=JAtfTEA7AWBPcMhFGqlwSQmQSq-lWAEJ8Y98qmDe0I0,54349
|
||||
kivymd/images/transparent.png,sha256=yM2bydAM4U0tnbs4zAuK2GnCC6I6NgAIfpw7rQhG1BQ,156
|
||||
kivymd/material_resources.py,sha256=XnkSLVe-kTAEmEl9QzJRV-qs5sgmXjKT-V5GY30KXjY,576
|
||||
kivymd/theming.py,sha256=4dUslqibyGwEd9noplpmhGbH9daoGfdaqr-XlP55a-E,33018
|
||||
kivymd/toast/__init__.py,sha256=AWk597R4COWhbrfiUSjceBpmeaVer3-f3-L4dHOCQEY,54
|
||||
kivymd/toast/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/toast/__pycache__/androidtoast.cpython-311.pyc,,
|
||||
kivymd/toast/androidtoast.py,sha256=nPo0oay5MbILuwE36H4B_WtbMtAMSNtH89bCbZF0ULU,2361
|
||||
kivymd/tools/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/__pycache__/argument_parser.cpython-311.pyc,,
|
||||
kivymd/tools/argument_parser.py,sha256=oxgJoS5WZH_ATDlaEU0HDtm7ve4DOJ23CnOILIBygy8,3193
|
||||
kivymd/tools/hotreload/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/hotreload/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/hotreload/__pycache__/app.cpython-311.pyc,,
|
||||
kivymd/tools/hotreload/app.py,sha256=cJxyUxz1GbQ58pgPY3GZNSl-CoawoPUPoCUF3lECltI,16803
|
||||
kivymd/tools/packaging/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/packaging/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/packaging/pyinstaller/__init__.py,sha256=ibpoURJJkyGuSgWhz8t-RuLnCmQf15TiFNr-HKTCPHA,1480
|
||||
kivymd/tools/packaging/pyinstaller/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/packaging/pyinstaller/__pycache__/hook-kivymd.cpython-311.pyc,,
|
||||
kivymd/tools/packaging/pyinstaller/hook-kivymd.py,sha256=cN0arGlcA_vLA8FTaAdzKgn7s2YQRCclv7G0e4c4o-Y,1053
|
||||
kivymd/tools/patterns/MVC/Model/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/patterns/MVC/Model/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/Model/__pycache__/database_firebase.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/Model/__pycache__/database_restdb.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/Model/database_firebase.py,sha256=5SlPAn-ROkh_ytnv2nteaVRAMC0MUSDM9u115Crfh-o,1376
|
||||
kivymd/tools/patterns/MVC/Model/database_restdb.py,sha256=Wc-zPffP-Wriyn-JGKCQrw3SGZMiAk-8LrVjParRtGM,3866
|
||||
kivymd/tools/patterns/MVC/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/patterns/MVC/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/data/locales/po/en.po,sha256=1b2jIsEnyQi_T_gnpe5QeO90IdaQLwWClk5pn46ZjME,425
|
||||
kivymd/tools/patterns/MVC/data/locales/po/ru.po,sha256=mQd6ol2abec-PUJsrnRWNoah0din3IAg_F4gPf5VBVw,425
|
||||
kivymd/tools/patterns/MVC/libs/__init__.py,sha256=B6Kln9GZ6UrMOxr4lOnpTxGBMaoKlcar5wpyTGyUlIk,54
|
||||
kivymd/tools/patterns/MVC/libs/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/libs/__pycache__/translation.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/MVC/libs/translation.py,sha256=LiiMZUxVbAmUy71mVA-PyEkxwYrCAOcjeiDnlbCSPvQ,1411
|
||||
kivymd/tools/patterns/MVC/messages.pot,sha256=2cutqkylhtiY07tkXzE8yNqpux9eeoW3tdeoEbXdB1Y,582
|
||||
kivymd/tools/patterns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/tools/patterns/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/__pycache__/add_view.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/__pycache__/create_project.cpython-311.pyc,,
|
||||
kivymd/tools/patterns/add_view.py,sha256=4J41yOosi9KkNrMBI6h6yJ_0LoncdJzmJDy-iShaArk,6576
|
||||
kivymd/tools/patterns/create_project.py,sha256=x3g37U3Dbk-ivUJ_aGgwvjpwBkyM4zIcPF3Bcyw1ASQ,39373
|
||||
kivymd/uix/__init__.py,sha256=OP4CD9D1ezU3v3LGF0Yo91GIMIIJAUPMFSZNSLWdLOo,2793
|
||||
kivymd/uix/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/anchorlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/boxlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/circularlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/floatlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/gridlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/hero.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/recyclegridlayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/recycleview.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/relativelayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/responsivelayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/screen.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/screenmanager.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/scrollview.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/stacklayout.cpython-311.pyc,,
|
||||
kivymd/uix/__pycache__/widget.cpython-311.pyc,,
|
||||
kivymd/uix/anchorlayout.py,sha256=K40IAwhpYiCemdh9jvOtTYF4IHnF3wdce3CjD6gXQy4,1365
|
||||
kivymd/uix/appbar/__init__.py,sha256=rL3GwJPgu7s0GcKDYri7sDtIznAYaniO2B_UxVEWU7A,264
|
||||
kivymd/uix/appbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/appbar/__pycache__/appbar.cpython-311.pyc,,
|
||||
kivymd/uix/appbar/appbar.kv,sha256=EsSrZb-6aoYWc_kCZODw0EH6kzrTsbBESmRGv5ADzvU,2565
|
||||
kivymd/uix/appbar/appbar.py,sha256=6dquqLBAOLaBkxiwG7RQKAFF7t1OjHkBm8U83EGnSqg,38722
|
||||
kivymd/uix/badge/__init__.py,sha256=7CIBe8jXrxme7ankbSEmiPjT0EbJhPqawZHEcUa17mk,40
|
||||
kivymd/uix/badge/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/badge/__pycache__/badge.cpython-311.pyc,,
|
||||
kivymd/uix/badge/badge.kv,sha256=LW70SjdLKfULFydUYceLZCLE3ulJdjUI9DLOe5zo-Ck,545
|
||||
kivymd/uix/badge/badge.py,sha256=3coq8IQq9St8t2lQOVA4gzu9ZEk3owPBCh4VdI-lnMk,1429
|
||||
kivymd/uix/behaviors/__init__.py,sha256=VWDGd99o9hPc4Ej4nuQmuVk8P3jRU4D2iQGj9h3zUyo,745
|
||||
kivymd/uix/behaviors/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/backgroundcolor_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/declarative_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/elevation.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/focus_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/hover_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/magic_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/motion_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/ripple_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/rotate_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/scale_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/state_layer_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/stencil_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/toggle_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/__pycache__/touch_behavior.cpython-311.pyc,,
|
||||
kivymd/uix/behaviors/backgroundcolor_behavior.py,sha256=wtIo7A8wBr562wc9MliDk3vLkQGl8MzOEnWT6E-Jiqg,5275
|
||||
kivymd/uix/behaviors/declarative_behavior.py,sha256=E6vfUjq5QoVhm7pO5BKbWZrZjiLLq0wJ-lpKDi6mwgY,9776
|
||||
kivymd/uix/behaviors/elevation.py,sha256=ybmb_IQnpLv2gZZWrEhvp5hwNxDkapdZ9IfQFD7ciFI,20274
|
||||
kivymd/uix/behaviors/focus_behavior.py,sha256=lE84JzIeMGQyoRLYPt2z2OyaoNaJ6irKMUBhjzxKwa8,2865
|
||||
kivymd/uix/behaviors/hover_behavior.py,sha256=4Dslyh8758uViHlpbJOWzOqF0I-XEdrfO-NbWbFxZ-k,7745
|
||||
kivymd/uix/behaviors/magic_behavior.py,sha256=wwN40b_0NTG3Dopdhqt89PXYqY5mXSM4lY2xuIk1v9Q,4570
|
||||
kivymd/uix/behaviors/motion_behavior.py,sha256=Jl7v9KM19gRjXQ5K-stwtj89udxn20pKRSbYjnFd1ek,13820
|
||||
kivymd/uix/behaviors/ripple_behavior.py,sha256=o2Nl94jjd7HhH0b5kwEQcby1IAZT-gcjVaYTX6Vs4yg,16973
|
||||
kivymd/uix/behaviors/rotate_behavior.py,sha256=Z8Ux_UwKZHoeu-cCl8hNc2EDVgC_hWni-ld8BpbL1uE,3268
|
||||
kivymd/uix/behaviors/scale_behavior.py,sha256=2ONpA7LKW5UhNI-ibBLlyQtOP_xyHDkasNxmqLO-z_c,4062
|
||||
kivymd/uix/behaviors/state_layer_behavior.py,sha256=vr_ZNA8ggVcqDIjNDHgsa66HqlzoO4BgNOQeF4CCrLI,22138
|
||||
kivymd/uix/behaviors/stencil_behavior.py,sha256=yJtQY5Te-sa635lhz0pRwGGfyJeG5NtuzKpw3x1i8tw,3015
|
||||
kivymd/uix/behaviors/toggle_behavior.py,sha256=9dcZhoFTDMYNEMY8vNn0_Ei9VMLzy1aHyu26RcAOxEs,8644
|
||||
kivymd/uix/behaviors/touch_behavior.py,sha256=tOxMS2XyX-8o9romBRSqJJ-G0_Kp1P7mDXyylOC1t1U,2776
|
||||
kivymd/uix/bottomsheet/__init__.py,sha256=_pvnNLykM_K6xdruglPD6BbAmq7jo2uXfLarsoehxeo,158
|
||||
kivymd/uix/bottomsheet/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/bottomsheet/__pycache__/bottomsheet.cpython-311.pyc,,
|
||||
kivymd/uix/bottomsheet/bottomsheet.kv,sha256=bemuxX5ABIiWP1v_dddvTEGaVwCJO6tOB6xSlgSj_jU,1163
|
||||
kivymd/uix/bottomsheet/bottomsheet.py,sha256=NBm4KJe4zPbdYHZ78jgxUj2YCjrJExd0Mdmq9sYys2E,12793
|
||||
kivymd/uix/boxlayout.py,sha256=KKONYwmEON79f2c6TLCxN4KNDj7E9yvuXs2oT5vEiMc,2031
|
||||
kivymd/uix/button/__init__.py,sha256=YhX34jdEnmi9kDofnQXg5v3H1NJWC_uX10f5fOmMFuo,239
|
||||
kivymd/uix/button/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/button/__pycache__/button.cpython-311.pyc,,
|
||||
kivymd/uix/button/button.kv,sha256=0dJtZ_6IzOXbmHsBCDG64-OawofWV1okG1-eWP5nwQk,13278
|
||||
kivymd/uix/button/button.py,sha256=D7Rg3a4nT6zEJIZ6QONTigHfukAyQX8Ly1CuZ6tVINU,32731
|
||||
kivymd/uix/card/__init__.py,sha256=hjAO06DlaWnFP_wYQC5ZFMR4lobKDY0aztACZCvWgd8,113
|
||||
kivymd/uix/card/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/card/__pycache__/card.cpython-311.pyc,,
|
||||
kivymd/uix/card/card.kv,sha256=DZMWfl8xWTrWaZ35miD23vBNtl5g_86QY3tv3mMyGdo,2926
|
||||
kivymd/uix/card/card.py,sha256=vdewoU57GGQDC5JjPsd3Z8Xy5aCKRtX_sEpYbpU7kig,27567
|
||||
kivymd/uix/chip/__init__.py,sha256=1uvEh6w800aZE4KV-LA6xch01o8Netw-h8N3Wy4Jb6E,135
|
||||
kivymd/uix/chip/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/chip/__pycache__/chip.cpython-311.pyc,,
|
||||
kivymd/uix/chip/chip.kv,sha256=WUigEnF_XgGmwpv-5OUxaMY8LRZeXWxD4Ew36tk0JHI,3445
|
||||
kivymd/uix/chip/chip.py,sha256=n5-qQWzqXr6-eTGavpU7apsgX7WdsSnAP2MhKQ_6DyA,35420
|
||||
kivymd/uix/circularlayout.py,sha256=S5Z4R2Z7ENwSoDB-UqWjOl0lCoemTessK_C4KT3jru8,5407
|
||||
kivymd/uix/controllers/__init__.py,sha256=WNbi76mp899CTLeSZUnVJ0b5gSeUMJ9ganvmhEcNR40,231
|
||||
kivymd/uix/controllers/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/controllers/__pycache__/windowcontroller.cpython-311.pyc,,
|
||||
kivymd/uix/controllers/windowcontroller.py,sha256=msVZQJwaekkIw4XUECXWAMOAsXw5NkFe38xIel1wG84,2335
|
||||
kivymd/uix/dialog/__init__.py,sha256=6dLZqaNu832pAEUyZBrEU6BdQ46SSOx9LI8jOMsnHD4,182
|
||||
kivymd/uix/dialog/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/dialog/__pycache__/dialog.cpython-311.pyc,,
|
||||
kivymd/uix/dialog/dialog.kv,sha256=cLK7ZK50QwBmT73D3WgjnGbGGQ0BLrkQ8VHYmwFLFVA,2958
|
||||
kivymd/uix/dialog/dialog.py,sha256=iAr3ur0C0afToFtVXYSVpJrswIn6LX5_0IHZXaiobQI,18598
|
||||
kivymd/uix/divider/__init__.py,sha256=p52N9PonSJQ90tycWEJRDRpk8-D5R-ClBX0NN3xycl0,44
|
||||
kivymd/uix/divider/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/divider/__pycache__/divider.cpython-311.pyc,,
|
||||
kivymd/uix/divider/divider.kv,sha256=hn-zA8BMGFadxbyojHmC07pvge-TLSxF0VCv2sMPizE,250
|
||||
kivymd/uix/divider/divider.py,sha256=GRPGVGjSQEaIefqehWO5untZom69GD-OgIAaGd7srhY,3702
|
||||
kivymd/uix/dropdownitem/__init__.py,sha256=e4eaF7uU5hU119DKcnTkj2hC-DtQoJ5gpx4n-EilUvI,74
|
||||
kivymd/uix/dropdownitem/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/dropdownitem/__pycache__/dropdownitem.cpython-311.pyc,,
|
||||
kivymd/uix/dropdownitem/dropdownitem.kv,sha256=7ZljjTLoW__Fixl4jPTJG96upstMIfRxijwFLmbsWvc,1180
|
||||
kivymd/uix/dropdownitem/dropdownitem.py,sha256=6uneYSSjErpJSYaFnjGMNsOodt8c0VIs8OlZyKzRZkg,4773
|
||||
kivymd/uix/expansionpanel/__init__.py,sha256=OFJC5zK9iAI9doEVtptYDVPRuCQ2WTqd8LjScXQetEA,123
|
||||
kivymd/uix/expansionpanel/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/expansionpanel/__pycache__/expansionpanel.cpython-311.pyc,,
|
||||
kivymd/uix/expansionpanel/expansionpanel.kv,sha256=vK3HR_n4ihGzD-lRSV5Y_RKRdk5a151YjUr7QlClK78,279
|
||||
kivymd/uix/expansionpanel/expansionpanel.py,sha256=9KwYGUFkpZGdLrnHZ2YsVovDzDE9vwqRlHnffRT8dzo,14722
|
||||
kivymd/uix/filemanager/__init__.py,sha256=TR0eAXbR-lzZUQLiVcGcVp5D1myeiLoXGpSWZitrWKI,52
|
||||
kivymd/uix/filemanager/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/filemanager/__pycache__/filemanager.cpython-311.pyc,,
|
||||
kivymd/uix/filemanager/filemanager.kv,sha256=chfHadHr34MRk_UAuqPv9MOWLFhV_Ne84XfqL-NQF0I,2550
|
||||
kivymd/uix/filemanager/filemanager.py,sha256=Bsd_iFa2Yk_1JsW6rgobOOV2jOZDORrV5d5Y8IO9FWY,25902
|
||||
kivymd/uix/fitimage/__init__.py,sha256=BVf16byn839UfzikgsfJj_s5xH0PjGgU9gUuetb1dsU,44
|
||||
kivymd/uix/fitimage/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/fitimage/__pycache__/fitimage.cpython-311.pyc,,
|
||||
kivymd/uix/fitimage/fitimage.py,sha256=r364DXB21psGT2Mw8MIDZtXYgTbujb0ya6b5t5PD1jA,3250
|
||||
kivymd/uix/floatlayout.py,sha256=QfF_RcIiG7ITlKfxvsmcW0gy97fXdk5BmVVyvAqibpg,1541
|
||||
kivymd/uix/gridlayout.py,sha256=HJCj1dEvIXwJj0tOK9lWNgovFYMMUAmtf5-SZO9__f8,2013
|
||||
kivymd/uix/hero.py,sha256=Pkdo1qCbwQnErS8zExJBOO23pM2TM56UaKgaftGwCq8,18420
|
||||
kivymd/uix/imagelist/__init__.py,sha256=VgCXsVvUFA9yfBpB3cEwLWqQR0_s6um2SMohe0wTcv4,111
|
||||
kivymd/uix/imagelist/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/imagelist/__pycache__/imagelist.cpython-311.pyc,,
|
||||
kivymd/uix/imagelist/imagelist.kv,sha256=ukH2JEHvszq165W2Joylu7HoVl3pKYqMd7xhk_YWR54,1052
|
||||
kivymd/uix/imagelist/imagelist.py,sha256=hfJphayTAaVMQ-2BQsq5I3u8Tvyzm4ka_yNfNmAlRBg,7010
|
||||
kivymd/uix/label/__init__.py,sha256=DHLIPzLH5Uq0ChimIQIUVHQ42iAilC-F2xYzWqeqiXY,48
|
||||
kivymd/uix/label/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/label/__pycache__/label.cpython-311.pyc,,
|
||||
kivymd/uix/label/label.kv,sha256=wCK0divTBiNdEqsDlxLAWStH69MYIDiLqiVZw9wg9fA,1323
|
||||
kivymd/uix/label/label.py,sha256=cQVTn_ArbRQsoPXMq-tgDP99ebU05oF4fILP-TQZPoc,26088
|
||||
kivymd/uix/list/__init__.py,sha256=JQbupFYB2E24FxZaz4y94ImASKQfS1eGrZPdfEpJ4-E,364
|
||||
kivymd/uix/list/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/list/__pycache__/list.cpython-311.pyc,,
|
||||
kivymd/uix/list/list.kv,sha256=T7A3DeE6Vcsba2UacXMPPck2OBo2Kxzp7OOWPt1GjoI,4563
|
||||
kivymd/uix/list/list.py,sha256=koECDdLVSW1gluCNYT-VEST8N3fV6Y-jkAenKQ8fWXs,16560
|
||||
kivymd/uix/menu/__init__.py,sha256=2a7cHJKvQmKiqu4_YWWQMF96owFFkRiMnEPX2R_kMbA,46
|
||||
kivymd/uix/menu/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/menu/__pycache__/menu.cpython-311.pyc,,
|
||||
kivymd/uix/menu/menu.kv,sha256=f35OBRCv2GiFoIoQsmJiD5OO6HJBMtWvtGFG8l7Njks,13637
|
||||
kivymd/uix/menu/menu.py,sha256=s5ykbqIKmZokiYRCbNsPImOrPxulVxuQnmOxEjl-sr8,40145
|
||||
kivymd/uix/navigationbar/__init__.py,sha256=a30ldn9-lWqS5o8UjCD2T2bUF95jRiC-yKF_r3KqXOs,139
|
||||
kivymd/uix/navigationbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/navigationbar/__pycache__/navigationbar.cpython-311.pyc,,
|
||||
kivymd/uix/navigationbar/navigationbar.kv,sha256=-yaGGm2VOpgyAhvTtRNQD5rVKRuga9ZaADtbPgj-9SA,4035
|
||||
kivymd/uix/navigationbar/navigationbar.py,sha256=NCULciX76Vbe6DkQnWXhcDmRb8zvoaMGpdt9h07CgSQ,17122
|
||||
kivymd/uix/navigationdrawer/__init__.py,sha256=JNRnAbxuu0x2Xb8oO7lwBjKwKnYn2grJo_RZBcvBEIA,351
|
||||
kivymd/uix/navigationdrawer/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/navigationdrawer/__pycache__/navigationdrawer.cpython-311.pyc,,
|
||||
kivymd/uix/navigationdrawer/navigationdrawer.kv,sha256=R6xE6aRpthfbeEfUm62pvnWRBA7uE-Za_mNa--H9JpA,2031
|
||||
kivymd/uix/navigationdrawer/navigationdrawer.py,sha256=gxkX3v9U5LCQXZLRPjcXJLoz_bUd-fTbP-M2H2qQCGM,38521
|
||||
kivymd/uix/navigationrail/__init__.py,sha256=1fQMqMVg-A3g6ZOFOrX-adJd8k9R7Xe5kijzq_U3Ksw,216
|
||||
kivymd/uix/navigationrail/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/navigationrail/__pycache__/navigationrail.cpython-311.pyc,,
|
||||
kivymd/uix/navigationrail/navigationrail.kv,sha256=fMPYmHmNdS3WnSl2zpaxSuQMbLwg01YRU_3MbTh5eMs,2935
|
||||
kivymd/uix/navigationrail/navigationrail.py,sha256=MDMM8pdO5oGvH1gVGG4T2sLsz9lIWnrfR1C4qQe6Zsw,22302
|
||||
kivymd/uix/pickers/__init__.py,sha256=mhnmC4YAXu71eD90YcUe_l9kuMXUjHKALTFG6GdvtZM,242
|
||||
kivymd/uix/pickers/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/datepicker/__init__.py,sha256=gXQyrdPWJP9UxOwZ8VWuXZn8FB6S2AYnhl0FmAhI8Pc,116
|
||||
kivymd/uix/pickers/datepicker/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/datepicker/__pycache__/datepicker.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/datepicker/datepicker.kv,sha256=ZyWURj3ZzJ1Vb0-Fr4nI33sJQSLS2gAsjanoVHYBD5I,11736
|
||||
kivymd/uix/pickers/datepicker/datepicker.py,sha256=bYMdgC533VJdkR9vFVHM8mkyUyOrnUwbi7YvywR4hIs,60382
|
||||
kivymd/uix/pickers/timepicker/__init__.py,sha256=SBtSeGRb0VrrQgzFUGZxl0tQRwmUjKw5jpLhg371tNc,126
|
||||
kivymd/uix/pickers/timepicker/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/timepicker/__pycache__/timepicker.cpython-311.pyc,,
|
||||
kivymd/uix/pickers/timepicker/timepicker.kv,sha256=xXlxSukPBj9L05B2hP-IdxEAvI3_O0hmuMQttlyCWGc,11334
|
||||
kivymd/uix/pickers/timepicker/timepicker.py,sha256=k6kbkVFug5fY_IN98j9YGWtewSsztqIVYa8zbQo51wY,38753
|
||||
kivymd/uix/progressindicator/__init__.py,sha256=dA8bwUMDtdx1CglUx3R73Xz6j9uUiiZT6qVphrx9me8,112
|
||||
kivymd/uix/progressindicator/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/progressindicator/__pycache__/progressindicator.cpython-311.pyc,,
|
||||
kivymd/uix/progressindicator/progressindicator.kv,sha256=3XXvaGnEXAYpAFgQGE8gR3VGnYNYHapx827RBFtViDE,2221
|
||||
kivymd/uix/progressindicator/progressindicator.py,sha256=nuzNdqp1yGaQ6R80OQlYgXiYl42IPIRC2lRT9s1bwjw,18195
|
||||
kivymd/uix/recyclegridlayout.py,sha256=I399c4gsmyHAedTU1Biwd7QRYG60QJ-gx33WVct7CCc,2140
|
||||
kivymd/uix/recycleview.py,sha256=FVhr4SI0wjbQy08q68nDjh-Mqsdg6nfjwONZfHTBctY,1348
|
||||
kivymd/uix/refreshlayout/__init__.py,sha256=r6yH7AYvn831mRtdu6KN_p4L42JBJh2qKpNIuHyckao,66
|
||||
kivymd/uix/refreshlayout/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/refreshlayout/__pycache__/refreshlayout.cpython-311.pyc,,
|
||||
kivymd/uix/refreshlayout/refreshlayout.kv,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/uix/refreshlayout/refreshlayout.py,sha256=lHL1nGOpHWiPqjD7r0dkSabhR6d_Qzis7xtuhpr8RjA,9638
|
||||
kivymd/uix/relativelayout.py,sha256=9ewM64QYa1PI_-yBWo5d6mY5PfWudJ5gYu94q9OYEm8,1434
|
||||
kivymd/uix/responsivelayout.py,sha256=N1GMNejHlNssk8ZpC9kMuZELuWywUs9Dms_AzHcpU1Q,5409
|
||||
kivymd/uix/screen.py,sha256=MgpjK_06QR66Zr4qdxfyiW3ACcaRHclBu-vGsep9Xuo,2625
|
||||
kivymd/uix/screenmanager.py,sha256=gSccPZXnmadWd6ueyl9jXXZK4vpUNgEaw0iHVBd262s,5549
|
||||
kivymd/uix/scrollview.py,sha256=jeE7XEi8AIigV_BAL-uUOzACu1hEwrTg0FrpabexNok,10744
|
||||
kivymd/uix/segmentedbutton/__init__.py,sha256=4xtmjrtfPcihaUtek7R5GXm6ltBYdyY6vz7UokAM1hY,147
|
||||
kivymd/uix/segmentedbutton/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/segmentedbutton/__pycache__/segmentedbutton.cpython-311.pyc,,
|
||||
kivymd/uix/segmentedbutton/segmentedbutton.kv,sha256=JjfYB1naUJjHn8_quYhjnA8rgHH552eeoCLJb6JegRs,3468
|
||||
kivymd/uix/segmentedbutton/segmentedbutton.py,sha256=WaZ5DBY-7bmKdoclIl6W7q_ZN7ZgmKnPcJ75TbKiwng,22680
|
||||
kivymd/uix/selectioncontrol/__init__.py,sha256=n1yw1X7ccriTWj1GPN-V9LvFXgxuFNfEy6uRHPyhQGA,71
|
||||
kivymd/uix/selectioncontrol/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/selectioncontrol/__pycache__/selectioncontrol.cpython-311.pyc,,
|
||||
kivymd/uix/selectioncontrol/selectioncontrol.kv,sha256=RylxUp5CUsYur5Md_kzX76tcy93rwbfcrOr_eMy9HuQ,5311
|
||||
kivymd/uix/selectioncontrol/selectioncontrol.py,sha256=mIgPK-LLcm4We5LfJ8vv2Ue6uuLQ-biiy0EkN5ZXJQQ,24706
|
||||
kivymd/uix/slider/__init__.py,sha256=f2N0xMmmO7e9aNdxn0vDqKRgpMIV8EScrsRl71OG1yU,78
|
||||
kivymd/uix/slider/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/slider/__pycache__/slider.cpython-311.pyc,,
|
||||
kivymd/uix/slider/slider.kv,sha256=ydvIp5T2Htrh7Q2YMb2joStz8FVKENTnREmh6FcdVuk,7066
|
||||
kivymd/uix/slider/slider.py,sha256=DuuUi_jEpU8c5cyNmjZ5ZeKV4wU-sqNuyicWDOW8f28,17486
|
||||
kivymd/uix/sliverappbar/__init__.py,sha256=axuqy95RR0oDLXpBtH3EauoTZN56p6EAp3JFBC-MoYI,103
|
||||
kivymd/uix/sliverappbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/sliverappbar/__pycache__/sliverappbar.cpython-311.pyc,,
|
||||
kivymd/uix/sliverappbar/sliverappbar.kv,sha256=jcGxg6SQqadnGHJVJ6S1U6MmwDwALuJ1dGV6Ra651YU,1370
|
||||
kivymd/uix/sliverappbar/sliverappbar.py,sha256=Usg3jZdwnaUwO-f2YycHVl9qJIkB29QLtURi0W2_OuA,11439
|
||||
kivymd/uix/snackbar/__init__.py,sha256=wP0ppgJbwiGlR3HEMdTo5Umbkq5xeCMkmmJI8ohv8lU,223
|
||||
kivymd/uix/snackbar/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/snackbar/__pycache__/snackbar.cpython-311.pyc,,
|
||||
kivymd/uix/snackbar/snackbar.kv,sha256=JSszxvKOLOGvX3KR5DRekgPVRx8yqEq9BXwgRhbeqno,1836
|
||||
kivymd/uix/snackbar/snackbar.py,sha256=Li_UxO9IkrAf29Rkq1vFyoIr9CzVRm-HsFb46Z1ciTg,11746
|
||||
kivymd/uix/stacklayout.py,sha256=UDmj4W66Js16Y_RaHRA3WzXz1lBVwvhhtZkIIhQYfco,2067
|
||||
kivymd/uix/swiper/__init__.py,sha256=yjVyswA0HfoLRx9UW7k_GR497shvH5EthBbQk8CoU_4,43
|
||||
kivymd/uix/swiper/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/swiper/__pycache__/swiper.cpython-311.pyc,,
|
||||
kivymd/uix/swiper/swiper.kv,sha256=iTaioAm-1WWmrGV4mqTizz3f4Qobv8WJZT-cwhEqyD0,291
|
||||
kivymd/uix/swiper/swiper.py,sha256=lG0_lK1TIfIIz5jkrSnQS67ecA9_Ty6DbwcTXN9olck,12618
|
||||
kivymd/uix/tab/__init__.py,sha256=Cr-a9CGP8XGLa7QkvU08OpIS1mXu2-o_8V2CONFH1fE,192
|
||||
kivymd/uix/tab/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/tab/__pycache__/tab.cpython-311.pyc,,
|
||||
kivymd/uix/tab/tab.kv,sha256=ZBRG7PYPNPuI8pwfw7RNHI5wYgDP_oNPnZLzR4B_pMc,2255
|
||||
kivymd/uix/tab/tab.py,sha256=GTbl_ONS94t4-Lyb3tg5UXG6plx_t3QjDDZCxZtYyRQ,41727
|
||||
kivymd/uix/textfield/__init__.py,sha256=q0cpSrgMsws4Csqjz1xv-OCiiFkSstO9P1Vxi6H3sTo,195
|
||||
kivymd/uix/textfield/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/textfield/__pycache__/textfield.cpython-311.pyc,,
|
||||
kivymd/uix/textfield/textfield.kv,sha256=Yu3KxUoBhim0ZI-7if-dY4HI0ZqhPA7mUHyLW7M4obo,13507
|
||||
kivymd/uix/textfield/textfield.py,sha256=G0freQCtBynqyvvfYrkqFg3tqfFyAOHla119eFworC0,60112
|
||||
kivymd/uix/tooltip/__init__.py,sha256=QPH-5XUDaiDQm6TO5gKyE7lUveO7F4Y4ZiWOfZkxD08,182
|
||||
kivymd/uix/tooltip/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/tooltip/__pycache__/tooltip.cpython-311.pyc,,
|
||||
kivymd/uix/tooltip/tooltip.kv,sha256=gdM-7qQFuTcS-OXzsd6MgFZEalzgx_4wq5azAy1MxoM,2012
|
||||
kivymd/uix/tooltip/tooltip.py,sha256=I7UbwBjgaXQQJAsbYsSRZA3kskhZaOilUxav4akYfAM,14636
|
||||
kivymd/uix/transition/__init__.py,sha256=Akw-XkRM_JWV17J_SkneutkxlsKZZKqAEkCA4Rd8XYQ,141
|
||||
kivymd/uix/transition/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/uix/transition/__pycache__/transition.cpython-311.pyc,,
|
||||
kivymd/uix/transition/transition.py,sha256=6uWH24w6ZUK4abdQrc1ZuQqbOem9j_coS0zH16KvR-Q,17974
|
||||
kivymd/uix/widget.py,sha256=tR6SyGcoofexLHh_P9YUI7qcYrbHEzOkPwWQhpMoRJ4,1457
|
||||
kivymd/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
||||
kivymd/utils/__pycache__/__init__.cpython-311.pyc,,
|
||||
kivymd/utils/__pycache__/fpsmonitor.cpython-311.pyc,,
|
||||
kivymd/utils/__pycache__/set_bars_colors.cpython-311.pyc,,
|
||||
kivymd/utils/fpsmonitor.py,sha256=F1g2HqSr1QH2_SIoQReesMSMmyRj5YJxolBGlK1Tgs8,1514
|
||||
kivymd/utils/set_bars_colors.py,sha256=uhCQdrRhRW-P--5D5MJR6rcauOA8wmiFoapJJczkf14,4050
|
@ -1,5 +1,5 @@
|
||||
Wheel-Version: 1.0
|
||||
Generator: setuptools (74.1.2)
|
||||
Generator: setuptools (74.1.3)
|
||||
Root-Is-Purelib: true
|
||||
Tag: py3-none-any
|
||||
|
@ -0,0 +1 @@
|
||||
{"archive_info": {}, "url": "https://github.com/kivymd/KivyMD/archive/master.zip"}
|
@ -26,12 +26,10 @@ import os
|
||||
import kivy
|
||||
from kivy.logger import Logger
|
||||
|
||||
__version__ = "1.2.0"
|
||||
"""KivyMD version."""
|
||||
from kivymd._version import __version__, release
|
||||
|
||||
release = False
|
||||
if "READTHEDOCS" not in os.environ:
|
||||
kivy.require("2.2.0")
|
||||
kivy.require("2.3.0")
|
||||
|
||||
try:
|
||||
from kivymd._version import __date__, __hash__, __short_hash__
|
||||
@ -59,13 +57,8 @@ _log_message = (
|
||||
+ f' (installed at "{__file__}")'
|
||||
)
|
||||
Logger.info(_log_message)
|
||||
Logger.warning(
|
||||
"KivyMD: "
|
||||
"Version 1.2.0 is deprecated and is no longer supported. "
|
||||
"Use KivyMD version 2.0.0 from the master branch "
|
||||
"(pip install https://github.com/kivymd/KivyMD/archive/master.zip)"
|
||||
)
|
||||
|
||||
import kivymd.factory_registers # NOQA
|
||||
import kivymd.font_definitions # NOQA
|
||||
import kivymd.animation # NOQA
|
||||
from kivymd.tools.packaging.pyinstaller import hooks_path # NOQA
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1,5 +1,5 @@
|
||||
# THIS FILE IS GENERATED FROM KIVYMD SETUP.PY
|
||||
__version__ = '1.2.0'
|
||||
__hash__ = 'Unknown'
|
||||
__short_hash__ = 'Unknown'
|
||||
__date__ = '2024-09-15'
|
||||
release = False
|
||||
__version__ = "2.0.1.dev0"
|
||||
__hash__ = "Unknown"
|
||||
__short_hash__ = "Unknown"
|
||||
__date__ = "2024-09-15"
|
||||
|
224
kivy_venv/lib/python3.11/site-packages/kivymd/animation.py
Normal file
224
kivy_venv/lib/python3.11/site-packages/kivymd/animation.py
Normal file
@ -0,0 +1,224 @@
|
||||
"""
|
||||
Animation
|
||||
=========
|
||||
|
||||
.. versionadded:: 2.0.0
|
||||
|
||||
Adds new transitions to the :class:`~kivy.animation.AnimationTransition` class:
|
||||
- "easing_standard"
|
||||
- "easing_decelerated"
|
||||
- "easing_accelerated"
|
||||
- "easing_linear"
|
||||
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.animation import Animation
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.clock import Clock
|
||||
from kivy.metrics import dp
|
||||
from kivy.properties import ListProperty
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
class AnimBox(BoxLayout):
|
||||
obj_pos = ListProperty([0, 0])
|
||||
|
||||
|
||||
UI = '''
|
||||
<AnimBox>:
|
||||
transition:"in_out_bounce"
|
||||
size_hint_y:None
|
||||
height:dp(100)
|
||||
obj_pos:[dp(40), self.pos[-1] + dp(40)]
|
||||
canvas:
|
||||
Color:
|
||||
rgba:app.theme_cls.primaryContainerColor
|
||||
Rectangle:
|
||||
size:[self.size[0], dp(5)]
|
||||
pos:self.pos[0], self.pos[-1] + dp(50)
|
||||
Color:
|
||||
rgba:app.theme_cls.primaryColor
|
||||
Rectangle:
|
||||
size:[dp(30)] * 2
|
||||
pos:root.obj_pos
|
||||
MDLabel:
|
||||
adaptive_height:True
|
||||
text:root.transition
|
||||
padding:[dp(10), 0]
|
||||
halign:"center"
|
||||
|
||||
MDGridLayout:
|
||||
orientation:"lr-tb"
|
||||
cols:1
|
||||
md_bg_color:app.theme_cls.backgroundColor
|
||||
spacing:dp(10)
|
||||
'''
|
||||
|
||||
|
||||
class MotionApp(MDApp):
|
||||
|
||||
def build(self):
|
||||
return Builder.load_string(UI)
|
||||
|
||||
def on_start(self):
|
||||
for transition in [
|
||||
"easing_linear",
|
||||
"easing_accelerated",
|
||||
"easing_decelerated",
|
||||
"easing_standard",
|
||||
"in_out_cubic"
|
||||
]: # Add more here for comparison
|
||||
print(transition)
|
||||
widget = AnimBox()
|
||||
widget.transition = transition
|
||||
self.root.add_widget(widget)
|
||||
Clock.schedule_once(self.run_animation, 1)
|
||||
|
||||
_inverse = True
|
||||
def run_animation(self, dt):
|
||||
x = (self.root.children[0].width - dp(30)) if self._inverse else 0
|
||||
for widget in self.root.children:
|
||||
Animation(
|
||||
obj_pos=[x, widget.obj_pos[-1]], t=widget.transition, d=3
|
||||
).start(widget)
|
||||
self._inverse = not self._inverse
|
||||
Clock.schedule_once(self.run_animation, 3.1)
|
||||
|
||||
MotionApp().run()
|
||||
|
||||
.. image:: https://github.com/kivymd/KivyMD/assets/68729523/21c847b0-284a-4796-b704-e4a2531fbb1b
|
||||
:align: center
|
||||
"""
|
||||
|
||||
import math
|
||||
import sys
|
||||
import kivy.animation
|
||||
|
||||
float_epsilon = 8.3446500e-7
|
||||
|
||||
if sys.version_info < (3, 11):
|
||||
cbrt = lambda number: (abs(number) ** (1/3)) * (-1 if number < 0 else 1)
|
||||
else:
|
||||
cbrt = math.cbrt
|
||||
|
||||
class CubicBezier:
|
||||
"""Ported from Android source code"""
|
||||
|
||||
p0 = 0
|
||||
p1 = 0
|
||||
p2 = 0
|
||||
p3 = 0
|
||||
|
||||
def __init__(self, *args):
|
||||
self.p0, self.p1, self.p2, self.p3 = args
|
||||
|
||||
def evaluate_cubic(self, p1, p2, t):
|
||||
a = 1.0 / 3.0 + (p1 - p2)
|
||||
b = p2 - 2.0 * p1
|
||||
c = p1
|
||||
return 3.0 * ((a * t + b) * t + c) * t
|
||||
|
||||
def clamp_range(self, r):
|
||||
if r < 0.0:
|
||||
if -float_epsilon <= r < 0.0:
|
||||
return 0.0
|
||||
else:
|
||||
return math.nan
|
||||
elif r > 1.0:
|
||||
if 1.0 <= r <= 1.0 + float_epsilon:
|
||||
return 1.0
|
||||
else:
|
||||
return math.nan
|
||||
else:
|
||||
return r
|
||||
|
||||
def close_to(self, x, y):
|
||||
return abs(x - y) < float_epsilon
|
||||
|
||||
def find_first_cubic_root(self, p0, p1, p2, p3):
|
||||
a = 3.0 * (p0 - 2.0 * p1 + p2)
|
||||
b = 3.0 * (p1 - p0)
|
||||
c = p0
|
||||
d = -p0 + 3.0 * (p1 - p2) + p3
|
||||
if self.close_to(d, 0.0):
|
||||
if self.close_to(a, 0.0):
|
||||
if self.close_to(b, 0.0):
|
||||
return math.nan
|
||||
return self.clamp_range(-c / b)
|
||||
else:
|
||||
q = math.sqrt(b * b - 4.0 * a * c)
|
||||
a2 = 2.0 * a
|
||||
root = self.clamp_range((q - b) / a2)
|
||||
if not math.isnan(root):
|
||||
return root
|
||||
return self.clamp_range((-b - q) / a2)
|
||||
a /= d
|
||||
b /= d
|
||||
c /= d
|
||||
o3 = (3.0 * b - a * a) / 9.0
|
||||
q2 = (2.0 * a * a * a - 9.0 * a * b + 27.0 * c) / 54.0
|
||||
discriminant = q2 * q2 + o3 * o3 * o3
|
||||
a3 = a / 3.0
|
||||
|
||||
if discriminant < 0.0:
|
||||
mp33 = -(o3 * o3 * o3)
|
||||
r = math.sqrt(mp33)
|
||||
t = -q2 / r
|
||||
cos_phi = max(-1.0, min(t, 1.0))
|
||||
phi = math.acos(cos_phi)
|
||||
t1 = 2.0 * cbrt(r)
|
||||
root = self.clamp_range(t1 * math.cos(phi / 3.0) - a3)
|
||||
if not math.isnan(root):
|
||||
return root
|
||||
root = self.clamp_range(
|
||||
t1 * math.cos((phi + 2.0 * math.pi) / 3.0) - a3
|
||||
)
|
||||
if not math.isnan(root):
|
||||
return root
|
||||
return self.clamp_range(
|
||||
t1 * math.cos((phi + 4.0 * math.pi) / 3.0) - a3
|
||||
)
|
||||
|
||||
elif self.close_to(discriminant, 0.0):
|
||||
u1 = -cbrt(q2)
|
||||
root = self.clamp_range(2.0 * u1 - a3)
|
||||
if not math.isnan(root):
|
||||
return root
|
||||
return self.clamp_range(-u1 - a3)
|
||||
|
||||
sd = math.sqrt(discriminant)
|
||||
u1 = cbrt(-q2 + sd)
|
||||
v1 = cbrt(q2 + sd)
|
||||
return self.clamp_range(u1 - v1 - a3)
|
||||
|
||||
def t(self, value: float):
|
||||
return self.evaluate_cubic(
|
||||
self.p1,
|
||||
self.p3,
|
||||
self.find_first_cubic_root(
|
||||
-value,
|
||||
self.p0 - value,
|
||||
self.p2 - value,
|
||||
1.0 - value,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
class MDAnimationTransition(kivy.animation.AnimationTransition):
|
||||
"""KivyMD's equivalent of kivy's `AnimationTransition`"""
|
||||
|
||||
easing_standard = CubicBezier(0.4, 0.0, 0.2, 1.0).t
|
||||
easing_decelerated = CubicBezier(0.0, 0.0, 0.2, 1.0).t
|
||||
easing_accelerated = CubicBezier(0.4, 0.0, 1.0, 1.0).t
|
||||
easing_linear = CubicBezier(0.0, 0.0, 1.0, 1.0).t
|
||||
|
||||
# TODO: add `easing_emphasized` here
|
||||
# it's defination is
|
||||
# path(M 0,0 C 0.05, 0, 0.133333, 0.06, 0.166666, 0.4 C 0.208333, 0.82, 0.25, 1, 1, 1)
|
||||
|
||||
# Monkey patch kivy's animation module
|
||||
kivy.animation.AnimationTransition = MDAnimationTransition
|
@ -3,14 +3,15 @@ Themes/Material App
|
||||
===================
|
||||
|
||||
This module contains :class:`MDApp` class that is inherited from
|
||||
:class:`~kivy.app.App`. :class:`MDApp` has some properties needed for ``KivyMD``
|
||||
library (like :attr:`~MDApp.theme_cls`). You can turn on the monitor displaying
|
||||
the current ``FPS`` value in your application:
|
||||
:class:`~kivy.app.App`. :class:`MDApp` has some properties needed for `KivyMD`
|
||||
library (like :attr:`~MDApp.theme_cls`). You can turn on the monitor
|
||||
displaying the current `FP` value in your application:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
md_bg_color: self.theme_cls.backgroundColor
|
||||
|
||||
MDLabel:
|
||||
text: "Hello, World!"
|
||||
@ -32,10 +33,23 @@ the current ``FPS`` value in your application:
|
||||
|
||||
MainApp().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/fps-monitor.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/fps-monitor-dark.png
|
||||
:width: 350 px
|
||||
:align: center
|
||||
|
||||
.. note::
|
||||
|
||||
Note that if you override the built-in on_start method, you will
|
||||
definitely need to call the super method:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
class MainApp(MDApp):
|
||||
def build(self):
|
||||
[...]
|
||||
|
||||
def on_start(self):
|
||||
[...]
|
||||
"""
|
||||
|
||||
__all__ = ("MDApp",)
|
||||
@ -55,7 +69,12 @@ class FpsMonitoring:
|
||||
"""Implements a monitor to display the current FPS in the toolbar."""
|
||||
|
||||
def fps_monitor_start(self, anchor: str = "top") -> None:
|
||||
"""Adds a monitor to the main application window."""
|
||||
"""
|
||||
Adds a monitor to the main application window.
|
||||
|
||||
:type anchor: str;
|
||||
:param anchor: anchor FPS panel ('top' or 'bottom');
|
||||
"""
|
||||
|
||||
def add_monitor(*args):
|
||||
from kivy.core.window import Window
|
||||
@ -114,6 +133,14 @@ class MDApp(App, FpsMonitoring):
|
||||
super().__init__(**kwargs)
|
||||
self.theme_cls = ThemeManager()
|
||||
|
||||
def _run_prepare(self):
|
||||
self.theme_cls.bind(
|
||||
theme_style=self.theme_cls.update_theme_colors,
|
||||
primary_palette=self.theme_cls.set_colors
|
||||
)
|
||||
self.theme_cls.set_colors()
|
||||
super()._run_prepare()
|
||||
|
||||
def load_all_kv_files(self, path_to_directory: str) -> None:
|
||||
"""
|
||||
Recursively loads KV files from the selected directory.
|
||||
@ -128,8 +155,8 @@ class MDApp(App, FpsMonitoring):
|
||||
if "kivymd" in path_to_directory:
|
||||
Logger.critical(
|
||||
"KivyMD: "
|
||||
"Do not use the word 'kivymd' in the name of the directory "
|
||||
"from where you download KV files"
|
||||
"Do not use the word 'kivymd' in the name of the "
|
||||
"directory from where you download KV files"
|
||||
)
|
||||
if (
|
||||
"venv" in path_to_dir
|
||||
|
@ -1,954 +0,0 @@
|
||||
"""
|
||||
Themes/Color Definitions
|
||||
========================
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Material Design spec, The color system <https://material.io/design/color/the-color-system.html>`_
|
||||
|
||||
`Material Design spec, The color tool <https://material.io/resources/color/#!/?view.left=0&view.right=0>`_
|
||||
|
||||
Material colors palette to use in :class:`kivymd.theming.ThemeManager`.
|
||||
:data:`~colors` is a dict-in-dict where the first key is a value from
|
||||
:data:`~palette` and the second key is a value from :data:`~hue`. Color is a hex
|
||||
value, a string of 6 characters (0-9, A-F) written in uppercase.
|
||||
|
||||
For example, ``colors["Red"]["900"]`` is ``"B71C1C"``.
|
||||
"""
|
||||
|
||||
colors = {
|
||||
"Red": {
|
||||
"50": "FFEBEE",
|
||||
"100": "FFCDD2",
|
||||
"200": "EF9A9A",
|
||||
"300": "E57373",
|
||||
"400": "EF5350",
|
||||
"500": "F44336",
|
||||
"600": "E53935",
|
||||
"700": "D32F2F",
|
||||
"800": "C62828",
|
||||
"900": "B71C1C",
|
||||
"A100": "FF8A80",
|
||||
"A200": "FF5252",
|
||||
"A400": "FF1744",
|
||||
"A700": "D50000",
|
||||
},
|
||||
"Pink": {
|
||||
"50": "FCE4EC",
|
||||
"100": "F8BBD0",
|
||||
"200": "F48FB1",
|
||||
"300": "F06292",
|
||||
"400": "EC407A",
|
||||
"500": "E91E63",
|
||||
"600": "D81B60",
|
||||
"700": "C2185B",
|
||||
"800": "AD1457",
|
||||
"900": "880E4F",
|
||||
"A100": "FF80AB",
|
||||
"A200": "FF4081",
|
||||
"A400": "F50057",
|
||||
"A700": "C51162",
|
||||
},
|
||||
"Purple": {
|
||||
"50": "F3E5F5",
|
||||
"100": "E1BEE7",
|
||||
"200": "CE93D8",
|
||||
"300": "BA68C8",
|
||||
"400": "AB47BC",
|
||||
"500": "9C27B0",
|
||||
"600": "8E24AA",
|
||||
"700": "7B1FA2",
|
||||
"800": "6A1B9A",
|
||||
"900": "4A148C",
|
||||
"A100": "EA80FC",
|
||||
"A200": "E040FB",
|
||||
"A400": "D500F9",
|
||||
"A700": "AA00FF",
|
||||
},
|
||||
"DeepPurple": {
|
||||
"50": "EDE7F6",
|
||||
"100": "D1C4E9",
|
||||
"200": "B39DDB",
|
||||
"300": "9575CD",
|
||||
"400": "7E57C2",
|
||||
"500": "673AB7",
|
||||
"600": "5E35B1",
|
||||
"700": "512DA8",
|
||||
"800": "4527A0",
|
||||
"900": "311B92",
|
||||
"A100": "B388FF",
|
||||
"A200": "7C4DFF",
|
||||
"A400": "651FFF",
|
||||
"A700": "6200EA",
|
||||
},
|
||||
"Indigo": {
|
||||
"50": "E8EAF6",
|
||||
"100": "C5CAE9",
|
||||
"200": "9FA8DA",
|
||||
"300": "7986CB",
|
||||
"400": "5C6BC0",
|
||||
"500": "3F51B5",
|
||||
"600": "3949AB",
|
||||
"700": "303F9F",
|
||||
"800": "283593",
|
||||
"900": "1A237E",
|
||||
"A100": "8C9EFF",
|
||||
"A200": "536DFE",
|
||||
"A400": "3D5AFE",
|
||||
"A700": "304FFE",
|
||||
},
|
||||
"Blue": {
|
||||
"50": "E3F2FD",
|
||||
"100": "BBDEFB",
|
||||
"200": "90CAF9",
|
||||
"300": "64B5F6",
|
||||
"400": "42A5F5",
|
||||
"500": "2196F3",
|
||||
"600": "1E88E5",
|
||||
"700": "1976D2",
|
||||
"800": "1565C0",
|
||||
"900": "0D47A1",
|
||||
"A100": "82B1FF",
|
||||
"A200": "448AFF",
|
||||
"A400": "2979FF",
|
||||
"A700": "2962FF",
|
||||
},
|
||||
"LightBlue": {
|
||||
"50": "E1F5FE",
|
||||
"100": "B3E5FC",
|
||||
"200": "81D4FA",
|
||||
"300": "4FC3F7",
|
||||
"400": "29B6F6",
|
||||
"500": "03A9F4",
|
||||
"600": "039BE5",
|
||||
"700": "0288D1",
|
||||
"800": "0277BD",
|
||||
"900": "01579B",
|
||||
"A100": "80D8FF",
|
||||
"A200": "40C4FF",
|
||||
"A400": "00B0FF",
|
||||
"A700": "0091EA",
|
||||
},
|
||||
"Cyan": {
|
||||
"50": "E0F7FA",
|
||||
"100": "B2EBF2",
|
||||
"200": "80DEEA",
|
||||
"300": "4DD0E1",
|
||||
"400": "26C6DA",
|
||||
"500": "00BCD4",
|
||||
"600": "00ACC1",
|
||||
"700": "0097A7",
|
||||
"800": "00838F",
|
||||
"900": "006064",
|
||||
"A100": "84FFFF",
|
||||
"A200": "18FFFF",
|
||||
"A400": "00E5FF",
|
||||
"A700": "00B8D4",
|
||||
},
|
||||
"Teal": {
|
||||
"50": "E0F2F1",
|
||||
"100": "B2DFDB",
|
||||
"200": "80CBC4",
|
||||
"300": "4DB6AC",
|
||||
"400": "26A69A",
|
||||
"500": "009688",
|
||||
"600": "00897B",
|
||||
"700": "00796B",
|
||||
"800": "00695C",
|
||||
"900": "004D40",
|
||||
"A100": "A7FFEB",
|
||||
"A200": "64FFDA",
|
||||
"A400": "1DE9B6",
|
||||
"A700": "00BFA5",
|
||||
},
|
||||
"Green": {
|
||||
"50": "E8F5E9",
|
||||
"100": "C8E6C9",
|
||||
"200": "A5D6A7",
|
||||
"300": "81C784",
|
||||
"400": "66BB6A",
|
||||
"500": "4CAF50",
|
||||
"600": "43A047",
|
||||
"700": "388E3C",
|
||||
"800": "2E7D32",
|
||||
"900": "1B5E20",
|
||||
"A100": "B9F6CA",
|
||||
"A200": "69F0AE",
|
||||
"A400": "00E676",
|
||||
"A700": "00C853",
|
||||
},
|
||||
"LightGreen": {
|
||||
"50": "F1F8E9",
|
||||
"100": "DCEDC8",
|
||||
"200": "C5E1A5",
|
||||
"300": "AED581",
|
||||
"400": "9CCC65",
|
||||
"500": "8BC34A",
|
||||
"600": "7CB342",
|
||||
"700": "689F38",
|
||||
"800": "558B2F",
|
||||
"900": "33691E",
|
||||
"A100": "CCFF90",
|
||||
"A200": "B2FF59",
|
||||
"A400": "76FF03",
|
||||
"A700": "64DD17",
|
||||
},
|
||||
"Lime": {
|
||||
"50": "F9FBE7",
|
||||
"100": "F0F4C3",
|
||||
"200": "E6EE9C",
|
||||
"300": "DCE775",
|
||||
"400": "D4E157",
|
||||
"500": "CDDC39",
|
||||
"600": "C0CA33",
|
||||
"700": "AFB42B",
|
||||
"800": "9E9D24",
|
||||
"900": "827717",
|
||||
"A100": "F4FF81",
|
||||
"A200": "EEFF41",
|
||||
"A400": "C6FF00",
|
||||
"A700": "AEEA00",
|
||||
},
|
||||
"Yellow": {
|
||||
"50": "FFFDE7",
|
||||
"100": "FFF9C4",
|
||||
"200": "FFF59D",
|
||||
"300": "FFF176",
|
||||
"400": "FFEE58",
|
||||
"500": "FFEB3B",
|
||||
"600": "FDD835",
|
||||
"700": "FBC02D",
|
||||
"800": "F9A825",
|
||||
"900": "F57F17",
|
||||
"A100": "FFFF8D",
|
||||
"A200": "FFFF00",
|
||||
"A400": "FFEA00",
|
||||
"A700": "FFD600",
|
||||
},
|
||||
"Amber": {
|
||||
"50": "FFF8E1",
|
||||
"100": "FFECB3",
|
||||
"200": "FFE082",
|
||||
"300": "FFD54F",
|
||||
"400": "FFCA28",
|
||||
"500": "FFC107",
|
||||
"600": "FFB300",
|
||||
"700": "FFA000",
|
||||
"800": "FF8F00",
|
||||
"900": "FF6F00",
|
||||
"A100": "FFE57F",
|
||||
"A200": "FFD740",
|
||||
"A400": "FFC400",
|
||||
"A700": "FFAB00",
|
||||
},
|
||||
"Orange": {
|
||||
"50": "FFF3E0",
|
||||
"100": "FFE0B2",
|
||||
"200": "FFCC80",
|
||||
"300": "FFB74D",
|
||||
"400": "FFA726",
|
||||
"500": "FF9800",
|
||||
"600": "FB8C00",
|
||||
"700": "F57C00",
|
||||
"800": "EF6C00",
|
||||
"900": "E65100",
|
||||
"A100": "FFD180",
|
||||
"A200": "FFAB40",
|
||||
"A400": "FF9100",
|
||||
"A700": "FF6D00",
|
||||
},
|
||||
"DeepOrange": {
|
||||
"50": "FBE9E7",
|
||||
"100": "FFCCBC",
|
||||
"200": "FFAB91",
|
||||
"300": "FF8A65",
|
||||
"400": "FF7043",
|
||||
"500": "FF5722",
|
||||
"600": "F4511E",
|
||||
"700": "E64A19",
|
||||
"800": "D84315",
|
||||
"900": "BF360C",
|
||||
"A100": "FF9E80",
|
||||
"A200": "FF6E40",
|
||||
"A400": "FF3D00",
|
||||
"A700": "DD2C00",
|
||||
},
|
||||
"Brown": {
|
||||
"50": "EFEBE9",
|
||||
"100": "D7CCC8",
|
||||
"200": "BCAAA4",
|
||||
"300": "A1887F",
|
||||
"400": "8D6E63",
|
||||
"500": "795548",
|
||||
"600": "6D4C41",
|
||||
"700": "5D4037",
|
||||
"800": "4E342E",
|
||||
"900": "3E2723",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Gray": {
|
||||
"50": "FAFAFA",
|
||||
"100": "F5F5F5",
|
||||
"200": "EEEEEE",
|
||||
"300": "E0E0E0",
|
||||
"400": "BDBDBD",
|
||||
"500": "9E9E9E",
|
||||
"600": "757575",
|
||||
"700": "616161",
|
||||
"800": "424242",
|
||||
"900": "212121",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"BlueGray": {
|
||||
"50": "ECEFF1",
|
||||
"100": "CFD8DC",
|
||||
"200": "B0BEC5",
|
||||
"300": "90A4AE",
|
||||
"400": "78909C",
|
||||
"500": "607D8B",
|
||||
"600": "546E7A",
|
||||
"700": "455A64",
|
||||
"800": "37474F",
|
||||
"900": "263238",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Light": {
|
||||
"StatusBar": "E0E0E0",
|
||||
"AppBar": "F5F5F5",
|
||||
"Background": "FAFAFA",
|
||||
"CardsDialogs": "FFFFFF",
|
||||
"FlatButtonDown": "cccccc",
|
||||
},
|
||||
"Dark": {
|
||||
"StatusBar": "000000",
|
||||
"AppBar": "1f1f1f",
|
||||
"Background": "121212",
|
||||
"CardsDialogs": "212121",
|
||||
"FlatButtonDown": "999999",
|
||||
},
|
||||
}
|
||||
"""
|
||||
Color palette. Taken from `2014 Material Design color palettes
|
||||
<https://material.io/design/color/the-color-system.html>`_.
|
||||
|
||||
To demonstrate the shades of the palette, you can run the following code:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import ListProperty, StringProperty
|
||||
|
||||
from kivymd.color_definitions import colors
|
||||
from kivymd.uix.tab import MDTabsBase
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
|
||||
demo = '''
|
||||
<Root@MDBoxLayout>
|
||||
orientation: 'vertical'
|
||||
|
||||
MDTopAppBar:
|
||||
title: app.title
|
||||
|
||||
MDTabs:
|
||||
id: android_tabs
|
||||
on_tab_switch: app.on_tab_switch(*args)
|
||||
size_hint_y: None
|
||||
height: "48dp"
|
||||
tab_indicator_anim: False
|
||||
|
||||
RecycleView:
|
||||
id: rv
|
||||
key_viewclass: "viewclass"
|
||||
key_size: "height"
|
||||
|
||||
RecycleBoxLayout:
|
||||
default_size: None, dp(48)
|
||||
default_size_hint: 1, None
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
orientation: "vertical"
|
||||
|
||||
|
||||
<ItemColor>
|
||||
size_hint_y: None
|
||||
height: "42dp"
|
||||
|
||||
MDLabel:
|
||||
text: root.text
|
||||
halign: "center"
|
||||
|
||||
|
||||
<Tab>
|
||||
'''
|
||||
|
||||
from kivy.factory import Factory
|
||||
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
class Tab(MDBoxLayout, MDTabsBase):
|
||||
pass
|
||||
|
||||
|
||||
class ItemColor(MDBoxLayout):
|
||||
text = StringProperty()
|
||||
color = ListProperty()
|
||||
|
||||
|
||||
class Palette(MDApp):
|
||||
title = "Colors definitions"
|
||||
|
||||
def build(self):
|
||||
Builder.load_string(demo)
|
||||
self.screen = Factory.Root()
|
||||
|
||||
for name_tab in colors.keys():
|
||||
tab = Tab(title=name_tab)
|
||||
self.screen.ids.android_tabs.add_widget(tab)
|
||||
return self.screen
|
||||
|
||||
def on_tab_switch(
|
||||
self, instance_tabs, instance_tab, instance_tabs_label, tab_text
|
||||
):
|
||||
self.screen.ids.rv.data = []
|
||||
if not tab_text:
|
||||
tab_text = 'Red'
|
||||
for value_color in colors[tab_text]:
|
||||
self.screen.ids.rv.data.append(
|
||||
{
|
||||
"viewclass": "ItemColor",
|
||||
"md_bg_color": colors[tab_text][value_color],
|
||||
"title": value_color,
|
||||
}
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
self.on_tab_switch(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
self.screen.ids.android_tabs.ids.layout.children[-1].text,
|
||||
)
|
||||
|
||||
|
||||
Palette().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/palette.gif
|
||||
:align: center
|
||||
"""
|
||||
|
||||
palette = [
|
||||
"Red",
|
||||
"Pink",
|
||||
"Purple",
|
||||
"DeepPurple",
|
||||
"Indigo",
|
||||
"Blue",
|
||||
"LightBlue",
|
||||
"Cyan",
|
||||
"Teal",
|
||||
"Green",
|
||||
"LightGreen",
|
||||
"Lime",
|
||||
"Yellow",
|
||||
"Amber",
|
||||
"Orange",
|
||||
"DeepOrange",
|
||||
"Brown",
|
||||
"Gray",
|
||||
"BlueGray",
|
||||
]
|
||||
"""Valid values for color palette selecting."""
|
||||
|
||||
hue = [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"700",
|
||||
"800",
|
||||
"900",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
]
|
||||
"""Valid values for color hue selecting."""
|
||||
|
||||
|
||||
light_colors = {
|
||||
"Red": ["50", "100", "200", "300", "A100"],
|
||||
"Pink": ["50", "100", "200", "A100"],
|
||||
"Purple": ["50", "100", "200", "A100"],
|
||||
"DeepPurple": ["50", "100", "200", "A100"],
|
||||
"Indigo": ["50", "100", "200", "A100"],
|
||||
"Blue": ["50", "100", "200", "300", "400", "A100"],
|
||||
"LightBlue": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
],
|
||||
"Cyan": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"Teal": ["50", "100", "200", "300", "400", "A100", "A200", "A400", "A700"],
|
||||
"Green": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"LightGreen": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"Lime": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"700",
|
||||
"800",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"Yellow": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"700",
|
||||
"800",
|
||||
"900",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"Amber": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"700",
|
||||
"800",
|
||||
"900",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"Orange": [
|
||||
"50",
|
||||
"100",
|
||||
"200",
|
||||
"300",
|
||||
"400",
|
||||
"500",
|
||||
"600",
|
||||
"700",
|
||||
"A100",
|
||||
"A200",
|
||||
"A400",
|
||||
"A700",
|
||||
],
|
||||
"DeepOrange": ["50", "100", "200", "300", "400", "A100", "A200"],
|
||||
"Brown": ["50", "100", "200"],
|
||||
"Gray": ["50", "100", "200", "300", "400", "500"],
|
||||
"BlueGray": ["50", "100", "200", "300"],
|
||||
"Dark": [],
|
||||
"Light": ["White", "MainBackground", "DialogBackground"],
|
||||
}
|
||||
"""Which colors are light. Other are dark."""
|
||||
|
||||
text_colors = {
|
||||
"Red": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Pink": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "FFFFFF",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Purple": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "FFFFFF",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"DeepPurple": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "FFFFFF",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Indigo": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "FFFFFF",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Blue": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"LightBlue": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Cyan": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "000000",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Teal": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Green": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"LightGreen": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "000000",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Lime": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "000000",
|
||||
"700": "000000",
|
||||
"800": "000000",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Yellow": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "000000",
|
||||
"700": "000000",
|
||||
"800": "000000",
|
||||
"900": "000000",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Amber": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "000000",
|
||||
"700": "000000",
|
||||
"800": "000000",
|
||||
"900": "000000",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"Orange": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "000000",
|
||||
"700": "000000",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "000000",
|
||||
"A700": "000000",
|
||||
},
|
||||
"DeepOrange": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "000000",
|
||||
"A200": "000000",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Brown": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "FFFFFF",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "FFFFFF",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"Gray": {
|
||||
"50": "FFFFFF",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "000000",
|
||||
"500": "000000",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "FFFFFF",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
"BlueGray": {
|
||||
"50": "000000",
|
||||
"100": "000000",
|
||||
"200": "000000",
|
||||
"300": "000000",
|
||||
"400": "FFFFFF",
|
||||
"500": "FFFFFF",
|
||||
"600": "FFFFFF",
|
||||
"700": "FFFFFF",
|
||||
"800": "FFFFFF",
|
||||
"900": "FFFFFF",
|
||||
"A100": "FFFFFF",
|
||||
"A200": "FFFFFF",
|
||||
"A400": "FFFFFF",
|
||||
"A700": "FFFFFF",
|
||||
},
|
||||
}
|
||||
"""
|
||||
Text colors generated from :data:`~light_colors`. "000000" for light and
|
||||
"FFFFFF" for dark.
|
||||
|
||||
How to generate text_colors dict
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
text_colors = {}
|
||||
for p in palette:
|
||||
text_colors[p] = {}
|
||||
for h in hue:
|
||||
if h in light_colors[p]:
|
||||
text_colors[p][h] = "000000"
|
||||
else:
|
||||
text_colors[p][h] = "FFFFFF"
|
||||
"""
|
||||
|
||||
theme_colors = [
|
||||
"Primary",
|
||||
"Secondary",
|
||||
"Background",
|
||||
"Surface",
|
||||
"Error",
|
||||
"On_Primary",
|
||||
"On_Secondary",
|
||||
"On_Background",
|
||||
"On_Surface",
|
||||
"On_Error",
|
||||
]
|
||||
"""Valid theme colors."""
|
632
kivy_venv/lib/python3.11/site-packages/kivymd/dynamic_color.py
Normal file
632
kivy_venv/lib/python3.11/site-packages/kivymd/dynamic_color.py
Normal file
@ -0,0 +1,632 @@
|
||||
"""
|
||||
Components/Dynamic color
|
||||
========================
|
||||
|
||||
.. seealso::
|
||||
|
||||
`Material Design spec, Dynamic color
|
||||
<https://m3.material.io/styles/color/dynamic-color/overview>`_
|
||||
|
||||
.. rubric:: Dynamic color can create accessible UI color schemes based on
|
||||
content or user settings
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dynamic-color.png
|
||||
:align: center
|
||||
|
||||
Dynamic color experiences are built with M3 color schemes. Beginning with
|
||||
Android 12, users can generate individualized schemes through wallpaper
|
||||
selection and other customization settings. With M3 as a foundation,
|
||||
user-generated colors can coexist with app colors, putting a range of
|
||||
customizable visual experiences in the hands of users.
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dynamic-color-preview.png
|
||||
:align: center
|
||||
|
||||
1. Baseline scheme
|
||||
2. Colors extracted from a wallpaper
|
||||
3. Colors extracted from content
|
||||
|
||||
Example of dynamic color from the list of standard color schemes
|
||||
----------------------------------------------------------------
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.clock import Clock
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import StringProperty, ColorProperty
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
from kivy.utils import hex_colormap
|
||||
|
||||
from kivymd.uix.menu import MDDropdownMenu
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
KV = '''
|
||||
<ColorCard>
|
||||
orientation: "vertical"
|
||||
|
||||
MDLabel:
|
||||
text: root.text
|
||||
color: "grey"
|
||||
adaptive_height: True
|
||||
|
||||
MDCard:
|
||||
theme_bg_color: "Custom"
|
||||
md_bg_color: root.bg_color
|
||||
|
||||
|
||||
MDScreen:
|
||||
md_bg_color: app.theme_cls.backgroundColor
|
||||
|
||||
MDIconButton:
|
||||
on_release: app.open_menu(self)
|
||||
pos_hint: {"top": .98}
|
||||
x: "12dp"
|
||||
icon: "menu"
|
||||
|
||||
MDRecycleView:
|
||||
id: card_list
|
||||
viewclass: "ColorCard"
|
||||
bar_width: 0
|
||||
size_hint_y: None
|
||||
height: root.height - dp(68)
|
||||
|
||||
RecycleGridLayout:
|
||||
cols: 3
|
||||
spacing: "16dp"
|
||||
padding: "16dp"
|
||||
default_size: None, dp(56)
|
||||
default_size_hint: 1, None
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
'''
|
||||
|
||||
|
||||
class ColorCard(BoxLayout):
|
||||
text = StringProperty()
|
||||
bg_color = ColorProperty()
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
menu: MDDropdownMenu = None
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.dynamic_color = True
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def get_instance_from_menu(self, name_item):
|
||||
index = 0
|
||||
rv = self.menu.ids.md_menu
|
||||
opts = rv.layout_manager.view_opts
|
||||
datas = rv.data[0]
|
||||
|
||||
for data in rv.data:
|
||||
if data["text"] == name_item:
|
||||
index = rv.data.index(data)
|
||||
break
|
||||
|
||||
instance = rv.view_adapter.get_view(
|
||||
index, datas, opts[index]["viewclass"]
|
||||
)
|
||||
|
||||
return instance
|
||||
|
||||
def open_menu(self, menu_button):
|
||||
menu_items = []
|
||||
for item, method in {
|
||||
"Set palette": lambda: self.set_palette(),
|
||||
"Switch theme style": lambda: self.theme_switch(),
|
||||
}.items():
|
||||
menu_items.append({"text": item, "on_release": method})
|
||||
self.menu = MDDropdownMenu(
|
||||
caller=menu_button,
|
||||
items=menu_items,
|
||||
)
|
||||
self.menu.open()
|
||||
|
||||
def set_palette(self):
|
||||
instance_from_menu = self.get_instance_from_menu("Set palette")
|
||||
available_palettes = [
|
||||
name_color.capitalize() for name_color in hex_colormap.keys()
|
||||
]
|
||||
|
||||
menu_items = []
|
||||
for name_palette in available_palettes:
|
||||
menu_items.append(
|
||||
{
|
||||
"text": name_palette,
|
||||
"on_release": lambda x=name_palette: self.switch_palette(x),
|
||||
}
|
||||
)
|
||||
MDDropdownMenu(
|
||||
caller=instance_from_menu,
|
||||
items=menu_items,
|
||||
).open()
|
||||
|
||||
def switch_palette(self, selected_palette):
|
||||
self.theme_cls.primary_palette = selected_palette
|
||||
Clock.schedule_once(self.generate_cards, 0.5)
|
||||
|
||||
def theme_switch(self) -> None:
|
||||
self.theme_cls.switch_theme()
|
||||
Clock.schedule_once(self.generate_cards, 0.5)
|
||||
|
||||
def generate_cards(self, *args):
|
||||
self.root.ids.card_list.data = []
|
||||
for color in self.theme_cls.schemes_name_colors:
|
||||
value = f"{color}Color"
|
||||
self.root.ids.card_list.data.append(
|
||||
{
|
||||
"bg_color": getattr(self.theme_cls, value),
|
||||
"text": value,
|
||||
}
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
Clock.schedule_once(self.generate_cards)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dynamic-color.gif
|
||||
:align: center
|
||||
|
||||
Example of a dynamic color from an image
|
||||
----------------------------------------
|
||||
|
||||
.. seealso::
|
||||
|
||||
:attr:`kivymd.theming.ThemeManager.path_to_wallpaper`
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
import os
|
||||
|
||||
from kivy.clock import Clock
|
||||
from kivy.core.window import Window
|
||||
from kivy.core.window.window_sdl2 import WindowSDL
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import StringProperty, ColorProperty
|
||||
|
||||
from kivymd.uix.boxlayout import MDBoxLayout
|
||||
from kivymd.app import MDApp
|
||||
|
||||
|
||||
KV = '''
|
||||
<ColorCard>
|
||||
orientation: "vertical"
|
||||
|
||||
MDLabel:
|
||||
text: root.text
|
||||
color: "grey"
|
||||
adaptive_height: True
|
||||
|
||||
MDCard:
|
||||
theme_bg_color: "Custom"
|
||||
md_bg_color: root.bg_color
|
||||
|
||||
|
||||
MDScreen:
|
||||
md_bg_color: app.theme_cls.backgroundColor
|
||||
|
||||
MDRecycleView:
|
||||
id: card_list
|
||||
viewclass: "ColorCard"
|
||||
bar_width: 0
|
||||
|
||||
RecycleGridLayout:
|
||||
cols: 3
|
||||
spacing: "16dp"
|
||||
padding: "16dp"
|
||||
default_size: None, dp(56)
|
||||
default_size_hint: 1, None
|
||||
size_hint_y: None
|
||||
height: self.minimum_height
|
||||
'''
|
||||
|
||||
|
||||
class ColorCard(MDBoxLayout):
|
||||
text = StringProperty()
|
||||
bg_color = ColorProperty()
|
||||
|
||||
|
||||
class Example(MDApp):
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Window.bind(on_dropfile=self.on_drop_file)
|
||||
|
||||
def on_drop_file(self, sdl: WindowSDL, path_to_file: str) -> None:
|
||||
ext = os.path.splitext(path_to_file)[1]
|
||||
if isinstance(path_to_file, bytes):
|
||||
path_to_file = path_to_file.decode()
|
||||
if isinstance(ext, bytes):
|
||||
ext = ext.decode()
|
||||
if ext in [".png", ".jpg"]:
|
||||
self.theme_cls.path_to_wallpaper = path_to_file
|
||||
Clock.schedule_once(self.generate_cards, 0.5)
|
||||
|
||||
def build(self):
|
||||
self.theme_cls.dynamic_color = True
|
||||
self.theme_cls.theme_style = "Dark"
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def theme_switch(self) -> None:
|
||||
self.theme_cls.switch_theme()
|
||||
Clock.schedule_once(self.generate_cards, 0.5)
|
||||
|
||||
def generate_cards(self, *args):
|
||||
self.root.ids.card_list.data = []
|
||||
for color in self.theme_cls.schemes_name_colors:
|
||||
value = f"{color}Color"
|
||||
self.root.ids.card_list.data.append(
|
||||
{
|
||||
"bg_color": getattr(self.theme_cls, value),
|
||||
"text": value,
|
||||
}
|
||||
)
|
||||
|
||||
def on_start(self):
|
||||
Clock.schedule_once(self.generate_cards)
|
||||
|
||||
|
||||
Example().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/dynamic-color-path-to_wallpapper.gif
|
||||
:align: center
|
||||
"""
|
||||
|
||||
from kivy.properties import ColorProperty
|
||||
|
||||
|
||||
class DynamicColor:
|
||||
"""
|
||||
Dynamic color class.
|
||||
|
||||
.. versionadded:: 2.0.0
|
||||
"""
|
||||
|
||||
# Primary.
|
||||
primaryColor = ColorProperty()
|
||||
"""
|
||||
Primary color.
|
||||
|
||||
:attr:`primaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
primaryContainerColor = ColorProperty()
|
||||
"""
|
||||
Primary container color.
|
||||
|
||||
:attr:`primaryContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# On Primary.
|
||||
onPrimaryColor = ColorProperty()
|
||||
"""
|
||||
On primary color.
|
||||
|
||||
:attr:`onPrimaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
onPrimaryContainerColor = ColorProperty()
|
||||
"""
|
||||
On primary container color.
|
||||
|
||||
:attr:`onPrimaryContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Secondary.
|
||||
secondaryColor = ColorProperty()
|
||||
"""
|
||||
Secondary color.
|
||||
|
||||
:attr:`secondaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
secondaryContainerColor = ColorProperty()
|
||||
"""
|
||||
Secondary container color.
|
||||
|
||||
:attr:`secondaryContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# On Secondary.
|
||||
onSecondaryColor = ColorProperty()
|
||||
"""
|
||||
On secondary color.
|
||||
|
||||
:attr:`onSecondaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
onSecondaryContainerColor = ColorProperty()
|
||||
"""
|
||||
On secondary container color.
|
||||
|
||||
:attr:`onSecondaryContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Tertiary.
|
||||
tertiaryColor = ColorProperty()
|
||||
"""
|
||||
Tertiary color.
|
||||
|
||||
:attr:`tertiaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
tertiaryContainerColor = ColorProperty()
|
||||
"""
|
||||
Tertiary container color.
|
||||
|
||||
:attr:`tertiaryContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# On Tertiary.
|
||||
onTertiaryColor = ColorProperty()
|
||||
"""
|
||||
On tertiary color.
|
||||
|
||||
:attr:`onTertiaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
onTertiaryContainerColor = ColorProperty()
|
||||
"""
|
||||
On tertiary container color.
|
||||
|
||||
:attr:`onTertiaryContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Surface.
|
||||
surfaceColor = ColorProperty()
|
||||
"""
|
||||
Surface color.
|
||||
|
||||
:attr:`surfaceColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceDimColor = ColorProperty()
|
||||
"""
|
||||
Surface dim color.
|
||||
|
||||
:attr:`surfaceDimColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceBrightColor = ColorProperty()
|
||||
"""
|
||||
Surface bright color.
|
||||
|
||||
:attr:`surfaceBrightColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceContainerLowestColor = ColorProperty()
|
||||
"""
|
||||
Surface container lowest color.
|
||||
|
||||
:attr:`surfaceContainerLowestColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceContainerLowColor = ColorProperty()
|
||||
"""
|
||||
Surface container low color.
|
||||
|
||||
:attr:`surfaceContainerLowColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceContainerColor = ColorProperty()
|
||||
"""
|
||||
Surface container color.
|
||||
|
||||
:attr:`surfaceContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceContainerHighColor = ColorProperty()
|
||||
"""
|
||||
Surface container high color.
|
||||
|
||||
:attr:`surfaceContainerHighColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceContainerHighestColor = ColorProperty()
|
||||
"""
|
||||
Surface container highest color.
|
||||
|
||||
:attr:`surfaceContainerHighestColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceVariantColor = ColorProperty()
|
||||
"""
|
||||
Surface variant color.
|
||||
|
||||
:attr:`surfaceVariantColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
surfaceTintColor = ColorProperty()
|
||||
"""
|
||||
Surface tint color.
|
||||
|
||||
:attr:`surfaceTintColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# On Surface.
|
||||
onSurfaceColor = ColorProperty()
|
||||
"""
|
||||
On surface color.
|
||||
|
||||
:attr:`onSurfaceColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
onSurfaceLightColor = ColorProperty()
|
||||
"""
|
||||
On surface light color.
|
||||
|
||||
:attr:`onSurfaceLightColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
onSurfaceVariantColor = ColorProperty()
|
||||
"""
|
||||
On surface variant color.
|
||||
|
||||
:attr:`onSurfaceVariantColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Inverse.
|
||||
inverseSurfaceColor = ColorProperty()
|
||||
"""
|
||||
Inverse surface color.
|
||||
|
||||
:attr:`inverseSurfaceColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
inverseOnSurfaceColor = ColorProperty()
|
||||
"""
|
||||
Inverse on surface color.
|
||||
|
||||
:attr:`inverseOnSurfaceColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
inversePrimaryColor = ColorProperty()
|
||||
"""
|
||||
Inverse primary color.
|
||||
|
||||
:attr:`inversePrimaryColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Background.
|
||||
backgroundColor = ColorProperty()
|
||||
"""
|
||||
Background color.
|
||||
|
||||
:attr:`backgroundColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# On Background.
|
||||
onBackgroundColor = ColorProperty()
|
||||
"""
|
||||
On background color.
|
||||
|
||||
:attr:`onBackgroundColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Error.
|
||||
errorColor = ColorProperty()
|
||||
"""
|
||||
Error color.
|
||||
|
||||
:attr:`errorColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
errorContainerColor = ColorProperty()
|
||||
"""
|
||||
Error container color.
|
||||
|
||||
:attr:`errorContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# On Error.
|
||||
onErrorColor = ColorProperty()
|
||||
"""
|
||||
On error color.
|
||||
|
||||
:attr:`onErrorColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
onErrorContainerColor = ColorProperty()
|
||||
"""
|
||||
On error container color.
|
||||
|
||||
:attr:`onErrorContainerColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Outline.
|
||||
outlineColor = ColorProperty()
|
||||
"""
|
||||
Outline color.
|
||||
|
||||
:attr:`outlineColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
outlineVariantColor = ColorProperty()
|
||||
"""
|
||||
Outline variant color.
|
||||
|
||||
:attr:`outlineVariantColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Shadow/scrim.
|
||||
shadowColor = ColorProperty()
|
||||
"""
|
||||
Shadow color.
|
||||
|
||||
:attr:`shadowColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
scrimColor = ColorProperty()
|
||||
"""
|
||||
Scrim color.
|
||||
|
||||
:attr:`scrimColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Disabled.
|
||||
disabledTextColor = ColorProperty()
|
||||
"""
|
||||
Disabled text color.
|
||||
|
||||
:attr:`disabledTextColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
# Transparent.
|
||||
transparentColor = ColorProperty([0, 0, 0, 0])
|
||||
"""
|
||||
Transparent color.
|
||||
|
||||
:attr:`transparentColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `[0, 0, 0, 0]`.
|
||||
"""
|
||||
|
||||
# Ripple.
|
||||
rippleColor = ColorProperty("#BDBDBD")
|
||||
"""
|
||||
Ripple color.
|
||||
|
||||
:attr:`rippleColor` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `'#BDBDBD'`.
|
||||
"""
|
Binary file not shown.
@ -1 +0,0 @@
|
||||
from .fadingedge import FadingEdgeEffect
|
Binary file not shown.
Binary file not shown.
@ -1,200 +0,0 @@
|
||||
"""
|
||||
Effects/FadingEdgeEffect
|
||||
========================
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
|
||||
The `FadingEdgeEffect` class implements a fade effect for `KivyMD` widgets:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.scrollview import ScrollView
|
||||
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.effects.fadingedge.fadingedge import FadingEdgeEffect
|
||||
from kivymd.uix.list import OneLineListItem
|
||||
|
||||
KV = '''
|
||||
MDScreen:
|
||||
|
||||
FadeScrollView:
|
||||
fade_height: self.height / 2
|
||||
fade_color: root.md_bg_color
|
||||
|
||||
MDList:
|
||||
id: container
|
||||
'''
|
||||
|
||||
|
||||
class FadeScrollView(FadingEdgeEffect, ScrollView):
|
||||
pass
|
||||
|
||||
|
||||
class Test(MDApp):
|
||||
def build(self):
|
||||
return Builder.load_string(KV)
|
||||
|
||||
def on_start(self):
|
||||
for i in range(20):
|
||||
self.root.ids.container.add_widget(
|
||||
OneLineListItem(text=f"Single-line item {i}")
|
||||
)
|
||||
|
||||
|
||||
Test().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/fading-edge-effect-white.gif
|
||||
:align: center
|
||||
|
||||
.. note:: Use the same color value for the fade_color parameter as for the
|
||||
parent widget.
|
||||
"""
|
||||
|
||||
from typing import Union
|
||||
|
||||
from kivy.clock import Clock
|
||||
from kivy.graphics.context_instructions import Color
|
||||
from kivy.graphics.vertex_instructions import Rectangle
|
||||
from kivy.metrics import dp
|
||||
from kivy.properties import BooleanProperty, ColorProperty, NumericProperty
|
||||
|
||||
from kivymd.theming import ThemableBehavior
|
||||
|
||||
__all_ = ("FadingEdgeEffect",)
|
||||
|
||||
|
||||
class FadingEdgeEffect(ThemableBehavior):
|
||||
"""
|
||||
The class implements the fade effect.
|
||||
|
||||
.. versionadded:: 1.0.0
|
||||
"""
|
||||
|
||||
fade_color = ColorProperty(None)
|
||||
"""
|
||||
Fade color.
|
||||
|
||||
:attr:`fade_color` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `None`.
|
||||
"""
|
||||
|
||||
fade_height = NumericProperty(0)
|
||||
"""
|
||||
Fade height.
|
||||
|
||||
:attr:`fade_height` is an :class:`~kivy.properties.ColorProperty`
|
||||
and defaults to `0`.
|
||||
"""
|
||||
|
||||
edge_top = BooleanProperty(True)
|
||||
"""
|
||||
Display fade edge top.
|
||||
|
||||
:attr:`edge_top` is an :class:`~kivy.properties.BooleanProperty`
|
||||
and defaults to `True`.
|
||||
"""
|
||||
|
||||
edge_bottom = BooleanProperty(True)
|
||||
"""
|
||||
Display fade edge bottom.
|
||||
|
||||
:attr:`edge_bottom` is an :class:`~kivy.properties.BooleanProperty`
|
||||
and defaults to `True`.
|
||||
"""
|
||||
|
||||
_height_segment = 10
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
Clock.schedule_once(self.set_fade)
|
||||
|
||||
# TODO: Perhaps it would be better if we used a Shader for the fade effect.
|
||||
# But, I think the canvas instructions shouldn't affect performance
|
||||
def set_fade(self, interval: Union[int, float]) -> None:
|
||||
"""Draws a bottom and top fade border on the canvas."""
|
||||
|
||||
fade_color = (
|
||||
self.theme_cls.primary_color
|
||||
if not self.fade_color
|
||||
else self.fade_color
|
||||
)
|
||||
height_segment = (
|
||||
self.fade_height if self.fade_height else dp(100)
|
||||
) // self._height_segment
|
||||
alpha = 1.1
|
||||
|
||||
with self.canvas:
|
||||
for i in range(self._height_segment):
|
||||
alpha -= 0.1
|
||||
|
||||
Color(rgba=(fade_color[:-1] + [round(alpha, 1)]))
|
||||
rectangle_top = (
|
||||
Rectangle(
|
||||
pos=(self.x, self.height - (i * height_segment)),
|
||||
size=(self.width, height_segment),
|
||||
)
|
||||
if self.edge_top
|
||||
else None
|
||||
)
|
||||
rectangle_bottom = (
|
||||
Rectangle(
|
||||
pos=(self.x, i * height_segment),
|
||||
size=(self.width, height_segment),
|
||||
)
|
||||
if self.edge_bottom
|
||||
else None
|
||||
)
|
||||
# How I hate lambda functions because of their length :(
|
||||
# But I don’t want to call the arguments by short,
|
||||
# incomprehensible names 'a', 'b', 'c'.
|
||||
self.bind(
|
||||
pos=lambda instance_fadind_edge_effect, window_size, rectangle_top=rectangle_top, rectangle_bottom=rectangle_bottom, index=i: self.update_canvas(
|
||||
instance_fadind_edge_effect,
|
||||
window_size,
|
||||
rectangle_top,
|
||||
rectangle_bottom,
|
||||
index,
|
||||
),
|
||||
size=lambda instance_fadind_edge_effect, window_size, rectangle_top=rectangle_top, rectangle_bottom=rectangle_bottom, index=i: self.update_canvas(
|
||||
instance_fadind_edge_effect,
|
||||
window_size,
|
||||
rectangle_top,
|
||||
rectangle_bottom,
|
||||
index,
|
||||
),
|
||||
)
|
||||
self.update_canvas(
|
||||
self, self.size, rectangle_top, rectangle_bottom, i
|
||||
)
|
||||
|
||||
def update_canvas(
|
||||
self,
|
||||
instance_fadind_edge_effect,
|
||||
size: list[int, int],
|
||||
rectangle_top: Rectangle,
|
||||
rectangle_bottom: Rectangle,
|
||||
index: int,
|
||||
) -> None:
|
||||
"""
|
||||
Updates the position and size of the fade border on the canvas.
|
||||
Called when the application screen is resized.
|
||||
"""
|
||||
|
||||
height_segment = (
|
||||
self.fade_height if self.fade_height else dp(100)
|
||||
) // self._height_segment
|
||||
|
||||
if rectangle_top:
|
||||
rectangle_top.pos = (
|
||||
instance_fadind_edge_effect.x,
|
||||
size[1]
|
||||
- (index * height_segment - instance_fadind_edge_effect.y),
|
||||
)
|
||||
rectangle_top.size = (size[0], height_segment)
|
||||
if rectangle_bottom:
|
||||
rectangle_bottom.pos = (
|
||||
instance_fadind_edge_effect.x,
|
||||
index * height_segment + instance_fadind_edge_effect.y,
|
||||
)
|
||||
rectangle_bottom.size = (size[0], height_segment)
|
@ -1 +0,0 @@
|
||||
from .roulettescroll import RouletteScrollEffect
|
Binary file not shown.
Binary file not shown.
@ -1,251 +0,0 @@
|
||||
"""
|
||||
Effects/RouletteScrollEffect
|
||||
============================
|
||||
|
||||
This is a subclass of :class:`kivy.effects.ScrollEffect` that simulates the
|
||||
motion of a roulette, or a notched wheel (think Wheel of Fortune). It is
|
||||
primarily designed for emulating the effect of the iOS and android date pickers.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Here's an example of using :class:`RouletteScrollEffect` for a
|
||||
:class:`kivy.uix.scrollview.ScrollView`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
from kivy.uix.gridlayout import GridLayout
|
||||
from kivy.uix.button import Button
|
||||
from kivy.uix.scrollview import ScrollView
|
||||
|
||||
# Preparing a `GridLayout` inside a `ScrollView`.
|
||||
layout = GridLayout(cols=1, padding=10, size_hint=(None, None), width=500)
|
||||
layout.bind(minimum_height=layout.setter('height'))
|
||||
|
||||
for i in range(30):
|
||||
btn = Button(text=str(i), size=(480, 40), size_hint=(None, None))
|
||||
layout.add_widget(btn)
|
||||
|
||||
root = ScrollView(
|
||||
size_hint=(None, None),
|
||||
size=(500, 320),
|
||||
pos_hint={'center_x': .5, 'center_y': .5},
|
||||
do_scroll_x=False,
|
||||
)
|
||||
root.add_widget(layout)
|
||||
|
||||
# Preparation complete. Now add the new scroll effect.
|
||||
root.effect_y = RouletteScrollEffect(anchor=20, interval=40)
|
||||
runTouchApp(root)
|
||||
|
||||
Here the :class:`ScrollView` scrolls through a series of buttons with height
|
||||
40. We then attached a :class:`RouletteScrollEffect` with interval 40,
|
||||
corresponding to the button heights. This allows the scrolling to stop at
|
||||
the same offset no matter where it stops. The :attr:`RouletteScrollEffect.anchor`
|
||||
adjusts this offset.
|
||||
|
||||
Customizations
|
||||
--------------
|
||||
|
||||
Other settings that can be played with include:
|
||||
|
||||
:attr:`RouletteScrollEffect.pull_duration`,
|
||||
:attr:`RouletteScrollEffect.coasting_alpha`,
|
||||
:attr:`RouletteScrollEffect.pull_back_velocity`, and
|
||||
:attr:`RouletteScrollEffect.terminal_velocity`.
|
||||
|
||||
See their module documentations for details.
|
||||
|
||||
:class:`RouletteScrollEffect` has one event ``on_coasted_to_stop`` that
|
||||
is fired when the roulette stops, "making a selection". It can be listened to
|
||||
for handling or cleaning up choice making.
|
||||
"""
|
||||
|
||||
from math import ceil, exp, floor
|
||||
|
||||
from kivy.animation import Animation
|
||||
from kivy.effects.scroll import ScrollEffect
|
||||
from kivy.properties import AliasProperty, NumericProperty, ObjectProperty
|
||||
|
||||
__all_ = ("RouletteScrollEffect",)
|
||||
|
||||
|
||||
class RouletteScrollEffect(ScrollEffect):
|
||||
"""
|
||||
This is a subclass of :class:`kivy.effects.ScrollEffect` that simulates the
|
||||
motion of a roulette, or a notched wheel (think Wheel of Fortune). It is
|
||||
primarily designed for emulating the effect of the iOS and android date pickers.
|
||||
|
||||
.. versionadded:: 0.104.2
|
||||
"""
|
||||
|
||||
__events__ = ("on_coasted_to_stop",)
|
||||
|
||||
drag_threshold = NumericProperty(0)
|
||||
"""
|
||||
Overrides :attr:`ScrollEffect.drag_threshold` to abolish drag threshold.
|
||||
|
||||
.. note::
|
||||
If using this with a :class:`Roulette` or other :class:`Tickline`
|
||||
subclasses, what matters is :attr:`Tickline.drag_threshold`, which
|
||||
is passed to this attribute in the end.
|
||||
|
||||
:attr:`drag_threshold` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0`.
|
||||
"""
|
||||
|
||||
min = NumericProperty(-float("inf"))
|
||||
max = NumericProperty(float("inf"))
|
||||
|
||||
interval = NumericProperty(50)
|
||||
"""
|
||||
The interval of the values of the "roulette".
|
||||
|
||||
:attr:`interval` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `50`.
|
||||
"""
|
||||
|
||||
anchor = NumericProperty(0)
|
||||
"""
|
||||
One of the valid stopping values.
|
||||
|
||||
:attr:`anchor` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0`.
|
||||
"""
|
||||
|
||||
pull_duration = NumericProperty(0.2)
|
||||
"""
|
||||
When movement slows around a stopping value, an animation is used
|
||||
to pull it toward the nearest value. :attr:`pull_duration` is the duration
|
||||
used for such an animation.
|
||||
|
||||
:attr:`pull_duration` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0.2`.
|
||||
"""
|
||||
|
||||
coasting_alpha = NumericProperty(0.5)
|
||||
"""
|
||||
When within :attr:`coasting_alpha` * :attr:`interval` of the
|
||||
next notch and velocity is below :attr:`terminal_velocity`,
|
||||
coasting begins and will end on the next notch.
|
||||
|
||||
:attr:`coasting_alpha` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `0.5`.
|
||||
"""
|
||||
|
||||
pull_back_velocity = NumericProperty("50sp")
|
||||
"""
|
||||
The velocity below which the scroll value will be drawn to the
|
||||
*nearest* notch instead of the *next* notch in the direction travelled.
|
||||
|
||||
:attr:`pull_back_velocity` is an :class:`~kivy.properties.NumericProperty`
|
||||
and defaults to `50sp`.
|
||||
"""
|
||||
|
||||
_anim = ObjectProperty(None)
|
||||
|
||||
def get_term_vel(self):
|
||||
return (
|
||||
exp(self.friction)
|
||||
* self.interval
|
||||
* self.coasting_alpha
|
||||
/ self.pull_duration
|
||||
)
|
||||
|
||||
def set_term_vel(self, val):
|
||||
self.pull_duration = (
|
||||
exp(self.friction) * self.interval * self.coasting_alpha / val
|
||||
)
|
||||
|
||||
terminal_velocity = AliasProperty(
|
||||
get_term_vel,
|
||||
set_term_vel,
|
||||
bind=["interval", "coasting_alpha", "pull_duration", "friction"],
|
||||
cache=True,
|
||||
)
|
||||
"""
|
||||
If velocity falls between :attr:`pull_back_velocity` and
|
||||
:attr:`terminal velocity` then the movement will start to coast
|
||||
to the next coming stopping value.
|
||||
|
||||
:attr:`terminal_velocity` is computed from a set formula given
|
||||
:attr:`interval`, :attr:`coasting_alpha`, :attr:`pull_duration`,
|
||||
and :attr:`friction`. Setting :attr:`terminal_velocity` has the
|
||||
effect of setting :attr:`pull_duration`.
|
||||
"""
|
||||
|
||||
def start(self, val, t=None):
|
||||
if self._anim:
|
||||
self._anim.stop(self)
|
||||
return ScrollEffect.start(self, val, t=t)
|
||||
|
||||
def on_notch(self, *args):
|
||||
return (self.scroll - self.anchor) % self.interval == 0
|
||||
|
||||
def nearest_notch(self, *args):
|
||||
interval = float(self.interval)
|
||||
anchor = self.anchor
|
||||
n = round((self.scroll - anchor) / interval)
|
||||
return anchor + n * interval
|
||||
|
||||
def next_notch(self, *args):
|
||||
interval = float(self.interval)
|
||||
anchor = self.anchor
|
||||
round_ = ceil if self.velocity > 0 else floor
|
||||
n = round_((self.scroll - anchor) / interval)
|
||||
return anchor + n * interval
|
||||
|
||||
def near_notch(self, d=0.01):
|
||||
nearest = self.nearest_notch()
|
||||
if abs((nearest - self.scroll) / self.interval) % 1 < d:
|
||||
return nearest
|
||||
else:
|
||||
return None
|
||||
|
||||
def near_next_notch(self, d=None):
|
||||
d = d or self.coasting_alpha
|
||||
next_ = self.next_notch()
|
||||
if abs((next_ - self.scroll) / self.interval) % 1 < d:
|
||||
return next_
|
||||
else:
|
||||
return None
|
||||
|
||||
def update_velocity(self, dt):
|
||||
if self.is_manual:
|
||||
return
|
||||
velocity = self.velocity
|
||||
t_velocity = self.terminal_velocity
|
||||
next_ = self.near_next_notch()
|
||||
pull_back_velocity = self.pull_back_velocity
|
||||
if pull_back_velocity < abs(velocity) < t_velocity and next_:
|
||||
duration = abs((next_ - self.scroll) / self.velocity)
|
||||
anim = Animation(
|
||||
scroll=next_,
|
||||
duration=duration,
|
||||
)
|
||||
self._anim = anim
|
||||
anim.on_complete = self._coasted_to_stop
|
||||
anim.start(self)
|
||||
return
|
||||
if abs(velocity) < pull_back_velocity and not self.on_notch():
|
||||
anim = Animation(
|
||||
scroll=self.nearest_notch(),
|
||||
duration=self.pull_duration,
|
||||
t="in_out_circ",
|
||||
)
|
||||
self._anim = anim
|
||||
anim.on_complete = self._coasted_to_stop
|
||||
anim.start(self)
|
||||
else:
|
||||
self.velocity -= self.velocity * self.friction
|
||||
self.apply_distance(self.velocity * dt)
|
||||
self.trigger_velocity_update()
|
||||
|
||||
def on_coasted_to_stop(self, *args):
|
||||
"""
|
||||
This event fires when the roulette has stopped, `making a selection`.
|
||||
"""
|
||||
|
||||
def _coasted_to_stop(self, *args):
|
||||
self.velocity = 0
|
||||
self.dispatch("on_coasted_to_stop")
|
Binary file not shown.
Binary file not shown.
@ -7,11 +7,11 @@ from kivy.factory import Factory
|
||||
register = Factory.register
|
||||
register("MDSegmentedButton", module="kivymd.uix.segmentedbutton")
|
||||
register("MDSegmentedButtonItem", module="kivymd.uix.segmentedbutton")
|
||||
register("MDSegmentButtonIcon", module="kivymd.uix.segmentedbutton")
|
||||
register("MDSegmentButtonLabel", module="kivymd.uix.segmentedbutton")
|
||||
register("MDScrollView", module="kivymd.uix.scrollview")
|
||||
register("MDRecycleView", module="kivymd.uix.recycleview")
|
||||
register("MDResponsiveLayout", module="kivymd.uix.responsivelayout")
|
||||
register("MDSegmentedControl", module="kivymd.uix.segmentedcontrol")
|
||||
register("MDSegmentedControlItem", module="kivymd.uix.segmentedcontrol")
|
||||
register("MDSliverAppbar", module="kivymd.uix.sliverappbar")
|
||||
register("MDSliverAppbarContent", module="kivymd.uix.sliverappbar")
|
||||
register("MDSliverAppbarHeader", module="kivymd.uix.sliverappbar")
|
||||
@ -19,8 +19,9 @@ register("MDNavigationRailItem", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRail", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRailFabButton", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRailMenuButton", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRailItemIcon", module="kivymd.uix.navigationrail")
|
||||
register("MDNavigationRailItemLabel", module="kivymd.uix.navigationrail")
|
||||
register("MDSwiper", module="kivymd.uix.swiper")
|
||||
register("MDCarousel", module="kivymd.uix.carousel")
|
||||
register("MDWidget", module="kivymd.uix.widget")
|
||||
register("MDFloatLayout", module="kivymd.uix.floatlayout")
|
||||
register("MDAnchorLayout", module="kivymd.uix.anchorlayout")
|
||||
@ -32,80 +33,102 @@ register("MDRelativeLayout", module="kivymd.uix.relativelayout")
|
||||
register("MDGridLayout", module="kivymd.uix.gridlayout")
|
||||
register("MDStackLayout", module="kivymd.uix.stacklayout")
|
||||
register("MDExpansionPanel", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelOneLine", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelTwoLine", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelThreeLine", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelHeader", module="kivymd.uix.expansionpanel")
|
||||
register("MDExpansionPanelContent", module="kivymd.uix.expansionpanel")
|
||||
register("FitImage", module="kivymd.uix.fitimage")
|
||||
register("MDBackdrop", module="kivymd.uix.backdrop")
|
||||
register("MDBanner", module="kivymd.uix.banner")
|
||||
register("MDTooltip", module="kivymd.uix.tooltip")
|
||||
register("MDTooltipPlain", module="kivymd.uix.tooltip")
|
||||
register("MDTooltipRich", module="kivymd.uix.tooltip")
|
||||
register("MDTooltipRichActionButton", module="kivymd.uix.tooltip")
|
||||
register("MDTooltipRichSubhead", module="kivymd.uix.tooltip")
|
||||
register("MDTooltipRichSupportingText", module="kivymd.uix.tooltip")
|
||||
register("MDBottomSheet", module="kivymd.uix.bottomsheet")
|
||||
register("MDBottomNavigation", module="kivymd.uix.bottomnavigation")
|
||||
register("MDBottomNavigationItem", module="kivymd.uix.bottomnavigation")
|
||||
register("MDBottomSheetDragHandle", module="kivymd.uix.bottomsheet")
|
||||
register("MDBottomSheetDragHandleButton", module="kivymd.uix.bottomsheet")
|
||||
register("MDBottomSheetDragHandleTitle", module="kivymd.uix.bottomsheet")
|
||||
register("MDNavigationBar", module="kivymd.uix.navigationbar")
|
||||
register("MDNavigationItem", module="kivymd.uix.navigationbar")
|
||||
register("MDNavigationItemLabel", module="kivymd.uix.navigationbar")
|
||||
register("MDNavigationItemIcon", module="kivymd.uix.navigationbar")
|
||||
register("MDToggleButton", module="kivymd.uix.behaviors.toggle_behavior")
|
||||
register("MDFloatingActionButtonSpeedDial", module="kivymd.uix.button")
|
||||
register("MDButton", module="kivymd.uix.button")
|
||||
register("MDButtonText", module="kivymd.uix.button")
|
||||
register("MDButtonIcon", module="kivymd.uix.button")
|
||||
register("MDFabButton", module="kivymd.uix.button")
|
||||
register("MDIconButton", module="kivymd.uix.button")
|
||||
register("MDRoundImageButton", module="kivymd.uix.button")
|
||||
register("MDFlatButton", module="kivymd.uix.button")
|
||||
register("MDRaisedButton", module="kivymd.uix.button")
|
||||
register("MDFloatingActionButton", module="kivymd.uix.button")
|
||||
register("MDRectangleFlatButton", module="kivymd.uix.button")
|
||||
register("MDTextButton", module="kivymd.uix.button")
|
||||
register("MDCustomRoundIconButton", module="kivymd.uix.button")
|
||||
register("MDRoundFlatButton", module="kivymd.uix.button")
|
||||
register("MDFillRoundFlatButton", module="kivymd.uix.button")
|
||||
register("MDRectangleFlatIconButton", module="kivymd.uix.button")
|
||||
register("MDRoundFlatIconButton", module="kivymd.uix.button")
|
||||
register("MDFillRoundFlatIconButton", module="kivymd.uix.button")
|
||||
register("MDExtendedFabButton", module="kivymd.uix.button")
|
||||
register("MDExtendedFabButtonIcon", module="kivymd.uix.button")
|
||||
register("MDExtendedFabButtonText", module="kivymd.uix.button")
|
||||
register("MDCard", module="kivymd.uix.card")
|
||||
register("MDSeparator", module="kivymd.uix.card")
|
||||
register("MDSelectionList", module="kivymd.uix.selection")
|
||||
register("MDDivider", module="kivymd.uix.divider")
|
||||
register("MDChip", module="kivymd.uix.chip")
|
||||
register("MDChipLeadingAvatar", module="kivymd.uix.chip")
|
||||
register("MDChipLeadingIcon", module="kivymd.uix.chip")
|
||||
register("MDChipTrailingIcon", module="kivymd.uix.chip")
|
||||
register("MDChipText", module="kivymd.uix.chip")
|
||||
register("MDSmartTile", module="kivymd.uix.imagelist")
|
||||
register("MDSmartTileOverlayContainer", module="kivymd.uix.imagelist")
|
||||
register("MDSmartTileImage", module="kivymd.uix.imagelist")
|
||||
register("MDLabel", module="kivymd.uix.label")
|
||||
register("MDIcon", module="kivymd.uix.label")
|
||||
register("MDBadge", module="kivymd.uix.badge")
|
||||
register("MDList", module="kivymd.uix.list")
|
||||
register("ILeftBody", module="kivymd.uix.list")
|
||||
register("ILeftBodyTouch", module="kivymd.uix.list")
|
||||
register("IRightBody", module="kivymd.uix.list")
|
||||
register("IRightBodyTouch", module="kivymd.uix.list")
|
||||
register("OneLineListItem", module="kivymd.uix.list")
|
||||
register("TwoLineListItem", module="kivymd.uix.list")
|
||||
register("ThreeLineListItem", module="kivymd.uix.list")
|
||||
register("OneLineAvatarListItem", module="kivymd.uix.list")
|
||||
register("TwoLineAvatarListItem", module="kivymd.uix.list")
|
||||
register("ThreeLineAvatarListItem", module="kivymd.uix.list")
|
||||
register("OneLineIconListItem", module="kivymd.uix.list")
|
||||
register("TwoLineIconListItem", module="kivymd.uix.list")
|
||||
register("ThreeLineIconListItem", module="kivymd.uix.list")
|
||||
register("OneLineRightIconListItem", module="kivymd.uix.list")
|
||||
register("TwoLineRightIconListItem", module="kivymd.uix.list")
|
||||
register("ThreeLineRightIconListItem", module="kivymd.uix.list")
|
||||
register("OneLineAvatarIconListItem", module="kivymd.uix.list")
|
||||
register("TwoLineAvatarIconListItem", module="kivymd.uix.list")
|
||||
register("ThreeLineAvatarIconListItem", module="kivymd.uix.list")
|
||||
register("MDListItem", module="kivymd.uix.list")
|
||||
register("MDListItemHeadlineText", module="kivymd.uix.list")
|
||||
register("MDListItemSupportingText", module="kivymd.uix.list")
|
||||
register("MDListItemTrailingSupportingText", module="kivymd.uix.list")
|
||||
register("MDListItemLeadingIcon", module="kivymd.uix.list")
|
||||
register("MDListItemTrailingIcon", module="kivymd.uix.list")
|
||||
register("MDListItemTrailingCheckbox", module="kivymd.uix.list")
|
||||
register("MDListItemTertiaryText", module="kivymd.uix.list")
|
||||
register("HoverBehavior", module="kivymd.uix.behaviors.hover_behavior")
|
||||
register("FocusBehavior", module="kivymd.uix.behaviors.focus_behavior")
|
||||
register("MagicBehavior", module="kivymd.uix.behaviors.magic_behavior")
|
||||
register("MDNavigationDrawer", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationLayout", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationDrawerMenu", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationDrawerHeader", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationDrawerItem", module="kivymd.uix.navigationdrawer")
|
||||
register(
|
||||
"MDNavigationDrawerItemLeadingIcon", module="kivymd.uix.navigationdrawer"
|
||||
)
|
||||
register(
|
||||
"MDNavigationDrawerItemTrailingText", module="kivymd.uix.navigationdrawer"
|
||||
)
|
||||
register("MDNavigationDrawerHeader", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationDrawerItemText", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationDrawerLabel", module="kivymd.uix.navigationdrawer")
|
||||
register("MDNavigationDrawerDivider", module="kivymd.uix.navigationdrawer")
|
||||
register("MDProgressBar", module="kivymd.uix.progressbar")
|
||||
register("MDScrollViewRefreshLayout", module="kivymd.uix.refreshlayout")
|
||||
register("MDCheckbox", module="kivymd.uix.selectioncontrol")
|
||||
register("MDSwitch", module="kivymd.uix.selectioncontrol")
|
||||
register("MDSlider", module="kivymd.uix.slider")
|
||||
register("MDSpinner", module="kivymd.uix.spinner")
|
||||
register("MDTabs", module="kivymd.uix.tab")
|
||||
register("MDCircularProgressIndicator", module="kivymd.uix.progressindicator")
|
||||
register("MDLinearProgressIndicator", module="kivymd.uix.progressindicator")
|
||||
register("MDTabsPrimary", module="kivymd.uix.tab")
|
||||
register("MDTabsSecondary", module="kivymd.uix.tab")
|
||||
register("MDTabsItem", module="kivymd.uix.tab")
|
||||
register("MDTabsItemSecondary", module="kivymd.uix.tab")
|
||||
register("MDTabsBadge", module="kivymd.uix.tab")
|
||||
register("MDTabsItemIcon", module="kivymd.uix.tab")
|
||||
register("MDTabsItemText", module="kivymd.uix.tab")
|
||||
register("MDTabsCarousel", module="kivymd.uix.tab")
|
||||
register("MDTextField", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldRect", module="kivymd.uix.textfield")
|
||||
register("MDTopAppBar", module="kivymd.uix.toolbar")
|
||||
register("MDBottomAppBar", module="kivymd.uix.toolbar")
|
||||
register("MDTextFieldHelperText", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldMaxLengthText", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldHintText", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldLeadingIcon", module="kivymd.uix.textfield")
|
||||
register("MDTextFieldTrailingIcon", module="kivymd.uix.textfield")
|
||||
register("MDTopAppBarTrailingButtonContainer", module="kivymd.uix.appbar")
|
||||
register("MDTopAppBarLeadingButtonContainer", module="kivymd.uix.appbar")
|
||||
register("MDFabBottomAppBarButton", module="kivymd.uix.appbar")
|
||||
register("MDActionBottomAppBarButton", module="kivymd.uix.appbar")
|
||||
register("MDTopAppBarTitle", module="kivymd.uix.appbar")
|
||||
register("MDTopAppBar", module="kivymd.uix.appbar")
|
||||
register("MDBottomAppBar", module="kivymd.uix.appbar")
|
||||
register("MDActionTopAppBarButton", module="kivymd.uix.appbar")
|
||||
register("MDDropDownItem", module="kivymd.uix.dropdownitem")
|
||||
register("MDDropDownItemText", module="kivymd.uix.dropdownitem")
|
||||
register("MDCircularLayout", module="kivymd.uix.circularlayout")
|
||||
register("MDHeroFrom", module="kivymd.uix.hero")
|
||||
register("MDHeroTo", module="kivymd.uix.hero")
|
||||
|
@ -1,5 +1,5 @@
|
||||
"""
|
||||
Themes/Font Definitions
|
||||
Themes/Font definitions
|
||||
=======================
|
||||
|
||||
.. seealso::
|
||||
@ -8,6 +8,7 @@ Themes/Font Definitions
|
||||
"""
|
||||
|
||||
from kivy.core.text import LabelBase
|
||||
from kivy.metrics import sp
|
||||
|
||||
from kivymd import fonts_path
|
||||
|
||||
@ -48,22 +49,102 @@ fonts = [
|
||||
for font in fonts:
|
||||
LabelBase.register(**font)
|
||||
|
||||
theme_font_styles = [
|
||||
"H1",
|
||||
"H2",
|
||||
"H3",
|
||||
"H4",
|
||||
"H5",
|
||||
"H6",
|
||||
"Subtitle1",
|
||||
"Subtitle2",
|
||||
"Body1",
|
||||
"Body2",
|
||||
"Button",
|
||||
"Caption",
|
||||
"Overline",
|
||||
"Icon",
|
||||
]
|
||||
# TODO: Add `weight` properties.
|
||||
theme_font_styles = {
|
||||
"Icon": {
|
||||
"large": {
|
||||
"line-height": 1,
|
||||
"font-name": "Icons",
|
||||
"font-size": sp(24),
|
||||
},
|
||||
},
|
||||
"Display": {
|
||||
"large": {
|
||||
"line-height": 1.64,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(57),
|
||||
},
|
||||
"medium": {
|
||||
"line-height": 1.52,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(45),
|
||||
},
|
||||
"small": {
|
||||
"line-height": 1.44,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(36),
|
||||
},
|
||||
},
|
||||
"Headline": {
|
||||
"large": {
|
||||
"line-height": 1.40,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(32),
|
||||
},
|
||||
"medium": {
|
||||
"line-height": 1.36,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(28),
|
||||
},
|
||||
"small": {
|
||||
"line-height": 1.32,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(24),
|
||||
},
|
||||
},
|
||||
"Title": {
|
||||
"large": {
|
||||
"line-height": 1.28,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(22),
|
||||
},
|
||||
"medium": {
|
||||
"line-height": 1.24,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(16),
|
||||
},
|
||||
"small": {
|
||||
"line-height": 1.20,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(14),
|
||||
},
|
||||
},
|
||||
"Body": {
|
||||
"large": {
|
||||
"line-height": 1.24,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(16),
|
||||
},
|
||||
"medium": {
|
||||
"line-height": 1.20,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(14),
|
||||
},
|
||||
"small": {
|
||||
"line-height": 1.16,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(12),
|
||||
},
|
||||
},
|
||||
"Label": {
|
||||
"large": {
|
||||
"line-height": 1.20,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(14),
|
||||
},
|
||||
"medium": {
|
||||
"line-height": 1.16,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(12),
|
||||
},
|
||||
"small": {
|
||||
"line-height": 1.16,
|
||||
"font-name": "Roboto",
|
||||
"font-size": sp(11),
|
||||
},
|
||||
},
|
||||
}
|
||||
"""
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/font-styles-2.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/label-font-style-preview.png
|
||||
:align: center
|
||||
"""
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -2,17 +2,17 @@
|
||||
Themes/Icon Definitions
|
||||
=======================
|
||||
|
||||
.. seealso::
|
||||
.. seealso::Updateeeee
|
||||
|
||||
`Material Design Icons <https://materialdesignicons.com/>`_
|
||||
`Material Design Icons <https://m3.material.io/styles/icons/overview>`_
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/material-icons.png
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/material-m3-icons.png
|
||||
:align: center
|
||||
|
||||
List of icons from materialdesignicons.com. These expanded material design
|
||||
icons are maintained by Austin Andrews (Templarian on Github).
|
||||
|
||||
LAST UPDATED: Version 7.2.96
|
||||
Version 7.4.47
|
||||
|
||||
To preview the icons and their names, you can use the following application:
|
||||
----------------------------------------------------------------------------
|
||||
@ -21,25 +21,28 @@ To preview the icons and their names, you can use the following application:
|
||||
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import StringProperty
|
||||
from kivy.uix.screenmanager import Screen
|
||||
|
||||
from kivymd.icon_definitions import md_icons
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.list import OneLineIconListItem
|
||||
|
||||
from kivymd.uix.list import MDListItem
|
||||
|
||||
Builder.load_string(
|
||||
'''
|
||||
#:import images_path kivymd.images_path
|
||||
|
||||
|
||||
<CustomOneLineIconListItem>
|
||||
<IconItem>
|
||||
|
||||
IconLeftWidget:
|
||||
MDListItemLeadingIcon:
|
||||
icon: root.icon
|
||||
|
||||
MDListItemSupportingText:
|
||||
text: root.text
|
||||
|
||||
|
||||
<PreviousMDIcons>
|
||||
md_bg_color: self.theme_cls.backgroundColor
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: 'vertical'
|
||||
@ -51,6 +54,7 @@ To preview the icons and their names, you can use the following application:
|
||||
|
||||
MDIconButton:
|
||||
icon: 'magnify'
|
||||
pos_hint: {'center_y': .5}
|
||||
|
||||
MDTextField:
|
||||
id: search_field
|
||||
@ -63,7 +67,7 @@ To preview the icons and their names, you can use the following application:
|
||||
key_size: 'height'
|
||||
|
||||
RecycleBoxLayout:
|
||||
padding: dp(10)
|
||||
padding: dp(10), dp(10), 0, dp(10)
|
||||
default_size: None, dp(48)
|
||||
default_size_hint: 1, None
|
||||
size_hint_y: None
|
||||
@ -73,19 +77,19 @@ To preview the icons and their names, you can use the following application:
|
||||
)
|
||||
|
||||
|
||||
class CustomOneLineIconListItem(OneLineIconListItem):
|
||||
class IconItem(MDListItem):
|
||||
icon = StringProperty()
|
||||
text = StringProperty()
|
||||
|
||||
|
||||
class PreviousMDIcons(Screen):
|
||||
|
||||
class PreviousMDIcons(MDScreen):
|
||||
def set_list_md_icons(self, text="", search=False):
|
||||
'''Builds a list of icons for the screen MDIcons.'''
|
||||
|
||||
def add_icon_item(name_icon):
|
||||
self.ids.rv.data.append(
|
||||
{
|
||||
"viewclass": "CustomOneLineIconListItem",
|
||||
"viewclass": "IconItem",
|
||||
"icon": name_icon,
|
||||
"text": name_icon,
|
||||
"callback": lambda x: x,
|
||||
@ -115,7 +119,7 @@ To preview the icons and their names, you can use the following application:
|
||||
|
||||
MainApp().run()
|
||||
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/md-icons-previous.gif
|
||||
.. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/m3-icons-previous.gif
|
||||
:align: center
|
||||
|
||||
"""
|
||||
@ -149,9 +153,12 @@ md_icons = {
|
||||
"account-badge": "\U000F1B0A",
|
||||
"account-badge-outline": "\U000F1B0B",
|
||||
"account-box": "\U000F0006",
|
||||
"account-box-edit-outline": "\U000F1CC8",
|
||||
"account-box-minus-outline": "\U000F1CC9",
|
||||
"account-box-multiple": "\U000F0934",
|
||||
"account-box-multiple-outline": "\U000F100A",
|
||||
"account-box-outline": "\U000F0007",
|
||||
"account-box-plus-outline": "\U000F1CCA",
|
||||
"account-cancel": "\U000F12DF",
|
||||
"account-cancel-outline": "\U000F12E0",
|
||||
"account-card": "\U000F1BA4",
|
||||
@ -181,6 +188,10 @@ md_icons = {
|
||||
"account-edit-outline": "\U000F0FFB",
|
||||
"account-eye": "\U000F0420",
|
||||
"account-eye-outline": "\U000F127B",
|
||||
"account-file": "\U000F1CA7",
|
||||
"account-file-outline": "\U000F1CA8",
|
||||
"account-file-text": "\U000F1CA9",
|
||||
"account-file-text-outline": "\U000F1CAA",
|
||||
"account-filter": "\U000F0936",
|
||||
"account-filter-outline": "\U000F0F9D",
|
||||
"account-group": "\U000F0849",
|
||||
@ -669,6 +680,8 @@ md_icons = {
|
||||
"arrow-left-thin-circle-outline": "\U000F159A",
|
||||
"arrow-left-top": "\U000F17A7",
|
||||
"arrow-left-top-bold": "\U000F17A8",
|
||||
"arrow-oscillating": "\U000F1C91",
|
||||
"arrow-oscillating-off": "\U000F1C92",
|
||||
"arrow-projectile": "\U000F1840",
|
||||
"arrow-projectile-multiple": "\U000F183F",
|
||||
"arrow-right": "\U000F0054",
|
||||
@ -840,6 +853,8 @@ md_icons = {
|
||||
"bag-personal-off": "\U000F0E11",
|
||||
"bag-personal-off-outline": "\U000F0E12",
|
||||
"bag-personal-outline": "\U000F0E13",
|
||||
"bag-personal-plus": "\U000F1CA4",
|
||||
"bag-personal-plus-outline": "\U000F1CA5",
|
||||
"bag-personal-tag": "\U000F1B0C",
|
||||
"bag-personal-tag-outline": "\U000F1B0D",
|
||||
"bag-suitcase": "\U000F158B",
|
||||
@ -1145,10 +1160,12 @@ md_icons = {
|
||||
"book-off-outline": "\U000F1695",
|
||||
"book-open": "\U000F00BD",
|
||||
"book-open-blank-variant": "\U000F00BE",
|
||||
"book-open-blank-variant-outline": "\U000F1CCB",
|
||||
"book-open-outline": "\U000F0B63",
|
||||
"book-open-page-variant": "\U000F05DA",
|
||||
"book-open-page-variant-outline": "\U000F15D6",
|
||||
"book-open-variant": "\U000F14F7",
|
||||
"book-open-variant-outline": "\U000F1CCC",
|
||||
"book-outline": "\U000F0B64",
|
||||
"book-play": "\U000F0E82",
|
||||
"book-play-outline": "\U000F0E83",
|
||||
@ -1339,9 +1356,11 @@ md_icons = {
|
||||
"bus-multiple": "\U000F0F3F",
|
||||
"bus-school": "\U000F079F",
|
||||
"bus-side": "\U000F07A0",
|
||||
"bus-sign": "\U000F1CC1",
|
||||
"bus-stop": "\U000F1012",
|
||||
"bus-stop-covered": "\U000F1013",
|
||||
"bus-stop-uncovered": "\U000F1014",
|
||||
"bus-wrench": "\U000F1CC2",
|
||||
"butterfly": "\U000F1589",
|
||||
"butterfly-outline": "\U000F158A",
|
||||
"button-cursor": "\U000F1B4F",
|
||||
@ -1521,6 +1540,7 @@ md_icons = {
|
||||
"car-defrost-rear": "\U000F0D62",
|
||||
"car-door": "\U000F0B6B",
|
||||
"car-door-lock": "\U000F109D",
|
||||
"car-door-lock-open": "\U000F1C81",
|
||||
"car-electric": "\U000F0B6C",
|
||||
"car-electric-outline": "\U000F15B5",
|
||||
"car-emergency": "\U000F160F",
|
||||
@ -1639,6 +1659,7 @@ md_icons = {
|
||||
"cash-100": "\U000F0115",
|
||||
"cash-check": "\U000F14EE",
|
||||
"cash-clock": "\U000F1A91",
|
||||
"cash-edit": "\U000F1CAB",
|
||||
"cash-fast": "\U000F185C",
|
||||
"cash-lock": "\U000F14EA",
|
||||
"cash-lock-open": "\U000F14EB",
|
||||
@ -1702,6 +1723,7 @@ md_icons = {
|
||||
"chair-school": "\U000F0125",
|
||||
"chandelier": "\U000F1793",
|
||||
"charity": "\U000F0C4F",
|
||||
"charity-search": "\U000F1C82",
|
||||
"chart-arc": "\U000F0126",
|
||||
"chart-areaspline": "\U000F0127",
|
||||
"chart-areaspline-variant": "\U000F0E91",
|
||||
@ -1710,6 +1732,8 @@ md_icons = {
|
||||
"chart-bell-curve": "\U000F0C50",
|
||||
"chart-bell-curve-cumulative": "\U000F0FA7",
|
||||
"chart-box": "\U000F154D",
|
||||
"chart-box-multiple": "\U000F1CCD",
|
||||
"chart-box-multiple-outline": "\U000F1CCE",
|
||||
"chart-box-outline": "\U000F154E",
|
||||
"chart-box-plus-outline": "\U000F154F",
|
||||
"chart-bubble": "\U000F05E3",
|
||||
@ -2026,6 +2050,8 @@ md_icons = {
|
||||
"cloud-cog-outline": "\U000F1BF1",
|
||||
"cloud-download": "\U000F0162",
|
||||
"cloud-download-outline": "\U000F0B7D",
|
||||
"cloud-key": "\U000F1CA1",
|
||||
"cloud-key-outline": "\U000F1CA2",
|
||||
"cloud-lock": "\U000F11F1",
|
||||
"cloud-lock-open": "\U000F1BF2",
|
||||
"cloud-lock-open-outline": "\U000F1BF3",
|
||||
@ -2063,6 +2089,10 @@ md_icons = {
|
||||
"coach-lamp-variant": "\U000F1A37",
|
||||
"coat-rack": "\U000F109E",
|
||||
"code-array": "\U000F0168",
|
||||
"code-block-braces": "\U000F1C83",
|
||||
"code-block-brackets": "\U000F1C84",
|
||||
"code-block-parentheses": "\U000F1C85",
|
||||
"code-block-tags": "\U000F1C86",
|
||||
"code-braces": "\U000F0169",
|
||||
"code-braces-box": "\U000F10D6",
|
||||
"code-brackets": "\U000F016A",
|
||||
@ -2501,6 +2531,7 @@ md_icons = {
|
||||
"diamond": "\U000F0B8A",
|
||||
"diamond-outline": "\U000F0B8B",
|
||||
"diamond-stone": "\U000F01C8",
|
||||
"diaper-outline": "\U000F1CCF",
|
||||
"dice-1": "\U000F01CA",
|
||||
"dice-1-outline": "\U000F114A",
|
||||
"dice-2": "\U000F01CB",
|
||||
@ -2584,6 +2615,7 @@ md_icons = {
|
||||
"donkey": "\U000F07C2",
|
||||
"door": "\U000F081A",
|
||||
"door-closed": "\U000F081B",
|
||||
"door-closed-cancel": "\U000F1C93",
|
||||
"door-closed-lock": "\U000F10AF",
|
||||
"door-open": "\U000F081C",
|
||||
"door-sliding": "\U000F181E",
|
||||
@ -2611,6 +2643,7 @@ md_icons = {
|
||||
"download-lock": "\U000F1320",
|
||||
"download-lock-outline": "\U000F1321",
|
||||
"download-multiple": "\U000F09E9",
|
||||
"download-multiple-outline": "\U000F1CD0",
|
||||
"download-network": "\U000F06F4",
|
||||
"download-network-outline": "\U000F0C66",
|
||||
"download-off": "\U000F10B0",
|
||||
@ -2643,7 +2676,10 @@ md_icons = {
|
||||
"earbuds-off-outline": "\U000F1851",
|
||||
"earbuds-outline": "\U000F1852",
|
||||
"earth": "\U000F01E7",
|
||||
"earth-arrow-down": "\U000F1C87",
|
||||
"earth-arrow-left": "\U000F1C88",
|
||||
"earth-arrow-right": "\U000F1311",
|
||||
"earth-arrow-up": "\U000F1C89",
|
||||
"earth-box": "\U000F06CD",
|
||||
"earth-box-minus": "\U000F1407",
|
||||
"earth-box-off": "\U000F06CE",
|
||||
@ -2747,11 +2783,17 @@ md_icons = {
|
||||
"emoticon-kiss-outline": "\U000F0C73",
|
||||
"emoticon-lol": "\U000F1214",
|
||||
"emoticon-lol-outline": "\U000F1215",
|
||||
"emoticon-minus": "\U000F1CB2",
|
||||
"emoticon-minus-outline": "\U000F1CB3",
|
||||
"emoticon-neutral": "\U000F0C74",
|
||||
"emoticon-neutral-outline": "\U000F01F6",
|
||||
"emoticon-outline": "\U000F01F2",
|
||||
"emoticon-plus": "\U000F1CB4",
|
||||
"emoticon-plus-outline": "\U000F1CB5",
|
||||
"emoticon-poop": "\U000F01F7",
|
||||
"emoticon-poop-outline": "\U000F0C75",
|
||||
"emoticon-remove": "\U000F1CB6",
|
||||
"emoticon-remove-outline": "\U000F1CB7",
|
||||
"emoticon-sad": "\U000F0C76",
|
||||
"emoticon-sad-outline": "\U000F01F8",
|
||||
"emoticon-sick": "\U000F157C",
|
||||
@ -2781,6 +2823,7 @@ md_icons = {
|
||||
"ethernet": "\U000F0200",
|
||||
"ethernet-cable": "\U000F0201",
|
||||
"ethernet-cable-off": "\U000F0202",
|
||||
"ethernet-off": "\U000F1CD1",
|
||||
"ev-plug-ccs1": "\U000F1519",
|
||||
"ev-plug-ccs2": "\U000F151A",
|
||||
"ev-plug-chademo": "\U000F151B",
|
||||
@ -2811,6 +2854,7 @@ md_icons = {
|
||||
"eye-check-outline": "\U000F0D05",
|
||||
"eye-circle": "\U000F0B94",
|
||||
"eye-circle-outline": "\U000F0B95",
|
||||
"eye-closed": "\U000F1CA3",
|
||||
"eye-lock": "\U000F1C06",
|
||||
"eye-lock-open": "\U000F1C07",
|
||||
"eye-lock-open-outline": "\U000F1C08",
|
||||
@ -3090,6 +3134,7 @@ md_icons = {
|
||||
"fire-hydrant-alert": "\U000F1138",
|
||||
"fire-hydrant-off": "\U000F1139",
|
||||
"fire-off": "\U000F1722",
|
||||
"fire-station": "\U000F1CC3",
|
||||
"fire-truck": "\U000F08AB",
|
||||
"firebase": "\U000F0967",
|
||||
"firefox": "\U000F0239",
|
||||
@ -3531,6 +3576,8 @@ md_icons = {
|
||||
"gas-burner": "\U000F1A1B",
|
||||
"gas-cylinder": "\U000F0647",
|
||||
"gas-station": "\U000F0298",
|
||||
"gas-station-in-use": "\U000F1CC4",
|
||||
"gas-station-in-use-outline": "\U000F1CC5",
|
||||
"gas-station-off": "\U000F1409",
|
||||
"gas-station-off-outline": "\U000F140A",
|
||||
"gas-station-outline": "\U000F0EB8",
|
||||
@ -3559,6 +3606,9 @@ md_icons = {
|
||||
"gender-male-female-variant": "\U000F113F",
|
||||
"gender-non-binary": "\U000F1140",
|
||||
"gender-transgender": "\U000F029F",
|
||||
"generator-mobile": "\U000F1C8A",
|
||||
"generator-portable": "\U000F1C8B",
|
||||
"generator-stationary": "\U000F1C8C",
|
||||
"gentoo": "\U000F08E8",
|
||||
"gesture": "\U000F07CB",
|
||||
"gesture-double-tap": "\U000F073C",
|
||||
@ -3794,6 +3844,7 @@ md_icons = {
|
||||
"heart-pulse": "\U000F05F6",
|
||||
"heart-remove": "\U000F1430",
|
||||
"heart-remove-outline": "\U000F1433",
|
||||
"heart-search": "\U000F1C8D",
|
||||
"heart-settings": "\U000F1665",
|
||||
"heart-settings-outline": "\U000F1666",
|
||||
"heat-pump": "\U000F1A43",
|
||||
@ -3918,7 +3969,10 @@ md_icons = {
|
||||
"hospital-building": "\U000F02E1",
|
||||
"hospital-marker": "\U000F02E2",
|
||||
"hot-tub": "\U000F0828",
|
||||
"hours-12": "\U000F1C94",
|
||||
"hours-24": "\U000F1478",
|
||||
"hub": "\U000F1C95",
|
||||
"hub-outline": "\U000F1C96",
|
||||
"hubspot": "\U000F0D17",
|
||||
"hulu": "\U000F0829",
|
||||
"human": "\U000F02E6",
|
||||
@ -3933,6 +3987,7 @@ md_icons = {
|
||||
"human-female-boy": "\U000F0A59",
|
||||
"human-female-dance": "\U000F15C9",
|
||||
"human-female-female": "\U000F0A5A",
|
||||
"human-female-female-child": "\U000F1C8E",
|
||||
"human-female-girl": "\U000F0A5B",
|
||||
"human-greeting": "\U000F17C4",
|
||||
"human-greeting-proximity": "\U000F159D",
|
||||
@ -3950,6 +4005,7 @@ md_icons = {
|
||||
"human-male-height": "\U000F0EFB",
|
||||
"human-male-height-variant": "\U000F0EFC",
|
||||
"human-male-male": "\U000F0A5E",
|
||||
"human-male-male-child": "\U000F1C8F",
|
||||
"human-non-binary": "\U000F1848",
|
||||
"human-pregnant": "\U000F05CF",
|
||||
"human-queue": "\U000F1571",
|
||||
@ -4063,6 +4119,59 @@ md_icons = {
|
||||
"integrated-circuit-chip": "\U000F1913",
|
||||
"invert-colors": "\U000F0301",
|
||||
"invert-colors-off": "\U000F0E4A",
|
||||
"invoice": "\U000F1CD2",
|
||||
"invoice-arrow-left": "\U000F1CD3",
|
||||
"invoice-arrow-left-outline": "\U000F1CD4",
|
||||
"invoice-arrow-right": "\U000F1CD5",
|
||||
"invoice-arrow-right-outline": "\U000F1CD6",
|
||||
"invoice-check": "\U000F1CD7",
|
||||
"invoice-check-outline": "\U000F1CD8",
|
||||
"invoice-clock": "\U000F1CD9",
|
||||
"invoice-clock-outline": "\U000F1CDA",
|
||||
"invoice-edit": "\U000F1CDB",
|
||||
"invoice-edit-outline": "\U000F1CDC",
|
||||
"invoice-export-outline": "\U000F1CDD",
|
||||
"invoice-fast": "\U000F1CDE",
|
||||
"invoice-fast-outline": "\U000F1CDF",
|
||||
"invoice-import": "\U000F1CE0",
|
||||
"invoice-import-outline": "\U000F1CE1",
|
||||
"invoice-list": "\U000F1CE2",
|
||||
"invoice-list-outline": "\U000F1CE3",
|
||||
"invoice-minus": "\U000F1CE4",
|
||||
"invoice-minus-outline": "\U000F1CE5",
|
||||
"invoice-multiple": "\U000F1CE6",
|
||||
"invoice-multiple-outline": "\U000F1CE7",
|
||||
"invoice-outline": "\U000F1CE8",
|
||||
"invoice-plus": "\U000F1CE9",
|
||||
"invoice-plus-outline": "\U000F1CEA",
|
||||
"invoice-remove": "\U000F1CEB",
|
||||
"invoice-remove-outline": "\U000F1CEC",
|
||||
"invoice-send": "\U000F1CED",
|
||||
"invoice-send-outline": "\U000F1CEE",
|
||||
"invoice-text": "\U000F1CEF",
|
||||
"invoice-text-arrow-left": "\U000F1CF0",
|
||||
"invoice-text-arrow-left-outline": "\U000F1CF1",
|
||||
"invoice-text-arrow-right": "\U000F1CF2",
|
||||
"invoice-text-arrow-right-outline": "\U000F1CF3",
|
||||
"invoice-text-check": "\U000F1CF4",
|
||||
"invoice-text-check-outline": "\U000F1CF5",
|
||||
"invoice-text-clock": "\U000F1CF6",
|
||||
"invoice-text-clock-outline": "\U000F1CF7",
|
||||
"invoice-text-edit": "\U000F1CF8",
|
||||
"invoice-text-edit-outline": "\U000F1CF9",
|
||||
"invoice-text-fast": "\U000F1CFA",
|
||||
"invoice-text-fast-outline": "\U000F1CFB",
|
||||
"invoice-text-minus": "\U000F1CFC",
|
||||
"invoice-text-minus-outline": "\U000F1CFD",
|
||||
"invoice-text-multiple": "\U000F1CFE",
|
||||
"invoice-text-multiple-outline": "\U000F1CFF",
|
||||
"invoice-text-outline": "\U000F1D00",
|
||||
"invoice-text-plus": "\U000F1D01",
|
||||
"invoice-text-plus-outline": "\U000F1D02",
|
||||
"invoice-text-remove": "\U000F1D03",
|
||||
"invoice-text-remove-outline": "\U000F1D04",
|
||||
"invoice-text-send": "\U000F1D05",
|
||||
"invoice-text-send-outline": "\U000F1D06",
|
||||
"iobroker": "\U000F12E8",
|
||||
"ip": "\U000F0A5F",
|
||||
"ip-network": "\U000F0A60",
|
||||
@ -4073,6 +4182,7 @@ md_icons = {
|
||||
"iron-board": "\U000F1838",
|
||||
"iron-outline": "\U000F1825",
|
||||
"island": "\U000F104F",
|
||||
"island-variant": "\U000F1CC6",
|
||||
"iv-bag": "\U000F10B9",
|
||||
"jabber": "\U000F0DD5",
|
||||
"jeepney": "\U000F0302",
|
||||
@ -4313,6 +4423,9 @@ md_icons = {
|
||||
"link-box-outline": "\U000F0D1B",
|
||||
"link-box-variant": "\U000F0D1C",
|
||||
"link-box-variant-outline": "\U000F0D1D",
|
||||
"link-circle": "\U000F1CAC",
|
||||
"link-circle-outline": "\U000F1CAD",
|
||||
"link-edit": "\U000F1CAE",
|
||||
"link-lock": "\U000F10BA",
|
||||
"link-off": "\U000F0338",
|
||||
"link-plus": "\U000F0C94",
|
||||
@ -4487,9 +4600,11 @@ md_icons = {
|
||||
"medication-outline": "\U000F1B15",
|
||||
"meditation": "\U000F117B",
|
||||
"memory": "\U000F035B",
|
||||
"memory-arrow-down": "\U000F1CA6",
|
||||
"menorah": "\U000F17D4",
|
||||
"menorah-fire": "\U000F17D5",
|
||||
"menu": "\U000F035C",
|
||||
"menu-close": "\U000F1C90",
|
||||
"menu-down": "\U000F035D",
|
||||
"menu-down-outline": "\U000F06B6",
|
||||
"menu-left": "\U000F035E",
|
||||
@ -4694,10 +4809,16 @@ md_icons = {
|
||||
"motorbike-off": "\U000F1B16",
|
||||
"mouse": "\U000F037D",
|
||||
"mouse-bluetooth": "\U000F098B",
|
||||
"mouse-left-click": "\U000F1D07",
|
||||
"mouse-left-click-outline": "\U000F1D08",
|
||||
"mouse-move-down": "\U000F1550",
|
||||
"mouse-move-up": "\U000F1551",
|
||||
"mouse-move-vertical": "\U000F1552",
|
||||
"mouse-off": "\U000F037E",
|
||||
"mouse-outline": "\U000F1D09",
|
||||
"mouse-right-click": "\U000F1D0A",
|
||||
"mouse-right-click-outline": "\U000F1D0B",
|
||||
"mouse-scroll-wheel": "\U000F1D0C",
|
||||
"mouse-variant": "\U000F037F",
|
||||
"mouse-variant-off": "\U000F0380",
|
||||
"move-resize": "\U000F0655",
|
||||
@ -5139,7 +5260,13 @@ md_icons = {
|
||||
"parking": "\U000F03E3",
|
||||
"party-popper": "\U000F1056",
|
||||
"passport": "\U000F07E3",
|
||||
"passport-alert": "\U000F1CB8",
|
||||
"passport-biometric": "\U000F0DE1",
|
||||
"passport-cancel": "\U000F1CB9",
|
||||
"passport-check": "\U000F1CBA",
|
||||
"passport-minus": "\U000F1CBB",
|
||||
"passport-plus": "\U000F1CBC",
|
||||
"passport-remove": "\U000F1CBD",
|
||||
"pasta": "\U000F1160",
|
||||
"patio-heater": "\U000F0F80",
|
||||
"patreon": "\U000F0882",
|
||||
@ -5349,6 +5476,7 @@ md_icons = {
|
||||
"plus-network-outline": "\U000F0CBA",
|
||||
"plus-outline": "\U000F0705",
|
||||
"plus-thick": "\U000F11EC",
|
||||
"pocket": "\U000F1CBE",
|
||||
"podcast": "\U000F0994",
|
||||
"podium": "\U000F0D25",
|
||||
"podium-bronze": "\U000F0D26",
|
||||
@ -5478,6 +5606,7 @@ md_icons = {
|
||||
"progress-question": "\U000F1522",
|
||||
"progress-star": "\U000F1788",
|
||||
"progress-star-four-points": "\U000F1C3D",
|
||||
"progress-tag": "\U000F1D0D",
|
||||
"progress-upload": "\U000F0998",
|
||||
"progress-wrench": "\U000F0CBD",
|
||||
"projector": "\U000F042E",
|
||||
@ -5531,6 +5660,7 @@ md_icons = {
|
||||
"quality-high": "\U000F0435",
|
||||
"quality-low": "\U000F0A0C",
|
||||
"quality-medium": "\U000F0A0D",
|
||||
"queue-first-in-last-out": "\U000F1CAF",
|
||||
"quora": "\U000F0D29",
|
||||
"rabbit": "\U000F0907",
|
||||
"rabbit-variant": "\U000F1A61",
|
||||
@ -5779,6 +5909,7 @@ md_icons = {
|
||||
"rounded-corner": "\U000F0607",
|
||||
"router": "\U000F11E2",
|
||||
"router-network": "\U000F1087",
|
||||
"router-network-wireless": "\U000F1C97",
|
||||
"router-wireless": "\U000F0469",
|
||||
"router-wireless-off": "\U000F15A3",
|
||||
"router-wireless-settings": "\U000F0A69",
|
||||
@ -5923,10 +6054,14 @@ md_icons = {
|
||||
"serial-port": "\U000F065C",
|
||||
"server": "\U000F048B",
|
||||
"server-minus": "\U000F048C",
|
||||
"server-minus-outline": "\U000F1C98",
|
||||
"server-network": "\U000F048D",
|
||||
"server-network-off": "\U000F048E",
|
||||
"server-network-outline": "\U000F1C99",
|
||||
"server-off": "\U000F048F",
|
||||
"server-outline": "\U000F1C9A",
|
||||
"server-plus": "\U000F0490",
|
||||
"server-plus-outline": "\U000F1C9B",
|
||||
"server-remove": "\U000F0491",
|
||||
"server-security": "\U000F0492",
|
||||
"set-all": "\U000F0778",
|
||||
@ -6466,6 +6601,7 @@ md_icons = {
|
||||
"swap-horizontal-bold": "\U000F0BCD",
|
||||
"swap-horizontal-circle": "\U000F0FE1",
|
||||
"swap-horizontal-circle-outline": "\U000F0FE2",
|
||||
"swap-horizontal-hidden": "\U000F1D0E",
|
||||
"swap-horizontal-variant": "\U000F08C1",
|
||||
"swap-vertical": "\U000F04E2",
|
||||
"swap-vertical-bold": "\U000F0BCE",
|
||||
@ -6563,6 +6699,8 @@ md_icons = {
|
||||
"tag-arrow-up-outline": "\U000F1732",
|
||||
"tag-check": "\U000F1A7A",
|
||||
"tag-check-outline": "\U000F1A7B",
|
||||
"tag-edit": "\U000F1C9C",
|
||||
"tag-edit-outline": "\U000F1C9D",
|
||||
"tag-faces": "\U000F04FA",
|
||||
"tag-heart": "\U000F068B",
|
||||
"tag-heart-outline": "\U000F0BCF",
|
||||
@ -6838,6 +6976,7 @@ md_icons = {
|
||||
"traffic-light": "\U000F052B",
|
||||
"traffic-light-outline": "\U000F182A",
|
||||
"train": "\U000F052C",
|
||||
"train-bus": "\U000F1CC7",
|
||||
"train-car": "\U000F0BD8",
|
||||
"train-car-autorack": "\U000F1B2D",
|
||||
"train-car-box": "\U000F1B2E",
|
||||
@ -6931,6 +7070,8 @@ md_icons = {
|
||||
"truck-flatbed": "\U000F1891",
|
||||
"truck-minus": "\U000F19AE",
|
||||
"truck-minus-outline": "\U000F19BD",
|
||||
"truck-off-road": "\U000F1C9E",
|
||||
"truck-off-road-off": "\U000F1C9F",
|
||||
"truck-outline": "\U000F129D",
|
||||
"truck-plus": "\U000F19AD",
|
||||
"truck-plus-outline": "\U000F19BC",
|
||||
@ -6975,6 +7116,7 @@ md_icons = {
|
||||
"umbrella-closed-outline": "\U000F13E2",
|
||||
"umbrella-closed-variant": "\U000F13E1",
|
||||
"umbrella-outline": "\U000F054B",
|
||||
"underwear-outline": "\U000F1D0F",
|
||||
"undo": "\U000F054C",
|
||||
"undo-variant": "\U000F054D",
|
||||
"unfold-less-horizontal": "\U000F054E",
|
||||
@ -6990,15 +7132,21 @@ md_icons = {
|
||||
"unreal": "\U000F09B1",
|
||||
"update": "\U000F06B0",
|
||||
"upload": "\U000F0552",
|
||||
"upload-box": "\U000F1D10",
|
||||
"upload-box-outline": "\U000F1D11",
|
||||
"upload-circle": "\U000F1D12",
|
||||
"upload-circle-outline": "\U000F1D13",
|
||||
"upload-lock": "\U000F1373",
|
||||
"upload-lock-outline": "\U000F1374",
|
||||
"upload-multiple": "\U000F083D",
|
||||
"upload-multiple-outline": "\U000F1D14",
|
||||
"upload-network": "\U000F06F6",
|
||||
"upload-network-outline": "\U000F0CD8",
|
||||
"upload-off": "\U000F10C6",
|
||||
"upload-off-outline": "\U000F10C7",
|
||||
"upload-outline": "\U000F0E07",
|
||||
"usb": "\U000F0553",
|
||||
"usb-c-port": "\U000F1CBF",
|
||||
"usb-flash-drive": "\U000F129E",
|
||||
"usb-flash-drive-outline": "\U000F129F",
|
||||
"usb-port": "\U000F11F0",
|
||||
@ -7083,6 +7231,7 @@ md_icons = {
|
||||
"video-plus": "\U000F09B3",
|
||||
"video-plus-outline": "\U000F01D3",
|
||||
"video-stabilization": "\U000F091B",
|
||||
"video-standard-definition": "\U000F1CA0",
|
||||
"video-switch": "\U000F0569",
|
||||
"video-switch-outline": "\U000F0790",
|
||||
"video-vintage": "\U000F0A1C",
|
||||
@ -7233,6 +7382,9 @@ md_icons = {
|
||||
"watering-can-outline": "\U000F1482",
|
||||
"watermark": "\U000F0612",
|
||||
"wave": "\U000F0F2E",
|
||||
"wave-arrow-down": "\U000F1CB0",
|
||||
"wave-arrow-up": "\U000F1CB1",
|
||||
"wave-undercurrent": "\U000F1CC0",
|
||||
"waveform": "\U000F147D",
|
||||
"waves": "\U000F078D",
|
||||
"waves-arrow-left": "\U000F1859",
|
||||
@ -7251,6 +7403,9 @@ md_icons = {
|
||||
"weather-hurricane-outline": "\U000F1C78",
|
||||
"weather-lightning": "\U000F0593",
|
||||
"weather-lightning-rainy": "\U000F067E",
|
||||
"weather-moonset": "\U000F1D15",
|
||||
"weather-moonset-down": "\U000F1D16",
|
||||
"weather-moonset-up": "\U000F1D17",
|
||||
"weather-night": "\U000F0594",
|
||||
"weather-night-partly-cloudy": "\U000F0F31",
|
||||
"weather-partly-cloudy": "\U000F0595",
|
||||
@ -7424,23 +7579,27 @@ md_icons = {
|
||||
if __name__ == "__main__":
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import StringProperty
|
||||
from kivy.uix.screenmanager import Screen
|
||||
|
||||
from kivymd.uix.screen import MDScreen
|
||||
from kivymd.app import MDApp
|
||||
from kivymd.uix.list import OneLineIconListItem
|
||||
from kivymd.uix.list import MDListItem
|
||||
|
||||
Builder.load_string(
|
||||
"""
|
||||
#:import images_path kivymd.images_path
|
||||
|
||||
|
||||
<CustomOneLineIconListItem>
|
||||
<IconItem>
|
||||
|
||||
IconLeftWidget:
|
||||
MDListItemLeadingIcon:
|
||||
icon: root.icon
|
||||
|
||||
MDListItemSupportingText:
|
||||
text: root.text
|
||||
|
||||
|
||||
<PreviousMDIcons>
|
||||
md_bg_color: self.theme_cls.backgroundColor
|
||||
|
||||
MDBoxLayout:
|
||||
orientation: 'vertical'
|
||||
@ -7452,6 +7611,7 @@ if __name__ == "__main__":
|
||||
|
||||
MDIconButton:
|
||||
icon: 'magnify'
|
||||
pos_hint: {'center_y': .5}
|
||||
|
||||
MDTextField:
|
||||
id: search_field
|
||||
@ -7464,7 +7624,7 @@ if __name__ == "__main__":
|
||||
key_size: 'height'
|
||||
|
||||
RecycleBoxLayout:
|
||||
padding: dp(10)
|
||||
padding: dp(10), dp(10), 0, dp(10)
|
||||
default_size: None, dp(48)
|
||||
default_size_hint: 1, None
|
||||
size_hint_y: None
|
||||
@ -7473,17 +7633,18 @@ if __name__ == "__main__":
|
||||
"""
|
||||
)
|
||||
|
||||
class CustomOneLineIconListItem(OneLineIconListItem):
|
||||
class IconItem(MDListItem):
|
||||
icon = StringProperty()
|
||||
text = StringProperty()
|
||||
|
||||
class PreviousMDIcons(Screen):
|
||||
class PreviousMDIcons(MDScreen):
|
||||
def set_list_md_icons(self, text="", search=False):
|
||||
"""Builds a list of icons for the screen MDIcons."""
|
||||
|
||||
def add_icon_item(name_icon):
|
||||
self.ids.rv.data.append(
|
||||
{
|
||||
"viewclass": "CustomOneLineIconListItem",
|
||||
"viewclass": "IconItem",
|
||||
"icon": name_icon,
|
||||
"text": name_icon,
|
||||
"callback": lambda x: x,
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 553 B |
Binary file not shown.
Before Width: | Height: | Size: 147 B |
Binary file not shown.
Before Width: | Height: | Size: 147 B |
Binary file not shown.
Before Width: | Height: | Size: 147 B |
Binary file not shown.
Before Width: | Height: | Size: 147 B |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user