diff --git a/src/bitmessagekivy/__init__.py b/src/bitmessagekivy/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/src/bitmessagekivy/kivy_helper_search.py b/src/bitmessagekivy/kivy_helper_search.py deleted file mode 100644 index 684a1722..00000000 --- a/src/bitmessagekivy/kivy_helper_search.py +++ /dev/null @@ -1,45 +0,0 @@ -from helper_sql import * - - -def search_sql(xAddress="toaddress", account=None, folder="inbox", where=None, what=None, unreadOnly=False): - if what is not None and what != "": - what = "%" + what + "%" - else: - what = None - - if folder == "sent": - sqlStatementBase = ''' - SELECT toaddress, fromaddress, subject, status, ackdata, lastactiontime - FROM sent ''' - else: - sqlStatementBase = '''SELECT folder, msgid, toaddress, fromaddress, subject, received, read - FROM inbox ''' - sqlStatementParts = [] - sqlArguments = [] - if account is not None: - if xAddress == 'both': - sqlStatementParts.append("(fromaddress = ? OR toaddress = ?)") - sqlArguments.append(account) - sqlArguments.append(account) - else: - sqlStatementParts.append(xAddress + " = ? ") - sqlArguments.append(account) - if folder is not None: - if folder == "new": - folder = "inbox" - unreadOnly = True - sqlStatementParts.append("folder = ? ") - sqlArguments.append(folder) - else: - sqlStatementParts.append("folder != ?") - sqlArguments.append("trash") - if what is not None: - sqlStatementParts.append("%s LIKE ?" % (where)) - sqlArguments.append(what) - if unreadOnly: - sqlStatementParts.append("read = 0") - if len(sqlStatementParts) > 0: - sqlStatementBase += "WHERE " + " AND ".join(sqlStatementParts) - if folder == "sent": - sqlStatementBase += " ORDER BY lastactiontime" - return sqlQuery(sqlStatementBase, sqlArguments) diff --git a/src/bitmessagekivy/main.kv b/src/bitmessagekivy/main.kv deleted file mode 100644 index ea8936c5..00000000 --- a/src/bitmessagekivy/main.kv +++ /dev/null @@ -1,354 +0,0 @@ -#:import la kivy.adapters.listadapter -#:import factory kivy.factory -#:import mpybit bitmessagekivy.mpybit -#:import C kivy.utils.get_color_from_hex - -: - id: nav_drawer - NavigationDrawerIconButton: - Spinner: - pos_hint:{"x":0,"y":.3} - id: btn - background_color: app.theme_cls.primary_dark - text: app.showmeaddresses(name='text') - values: app.showmeaddresses(name='values') - on_text:app.getCurrentAccountData(self.text) - - NavigationDrawerIconButton: - icon: 'email-open' - text: "inbox" - on_release: app.root.ids.scr_mngr.current = 'inbox' - NavigationDrawerIconButton: - icon: 'mail-send' - text: "sent" - on_release: app.root.ids.scr_mngr.current = 'sent' - NavigationDrawerIconButton: - icon: 'dropbox' - text: "trash" - on_release: app.root.ids.scr_mngr.current = 'trash' - NavigationDrawerIconButton: - icon: 'email' - text: "drafts" - on_release: app.root.ids.scr_mngr.current = 'dialog' - NavigationDrawerIconButton: - icon: 'markunread-mailbox' - text: "test" - on_release: app.root.ids.scr_mngr.current = 'test' - NavigationDrawerIconButton: - text: "new identity" - icon:'accounts-add' - on_release: app.root.ids.scr_mngr.current = 'newidentity' - -BoxLayout: - orientation: 'vertical' - Toolbar: - id: toolbar - title: app.getCurrentAccount() - background_color: app.theme_cls.primary_dark - left_action_items: [['menu', lambda x: app.nav_drawer.toggle()]] - Button: - text:"EXIT" - color: 0,0,0,1 - background_color: (0,0,0,0) - size_hint_y: 0.4 - size_hint_x: 0.1 - pos_hint: {'x': 0.8, 'y':0.4} - on_press: app.say_exit() - - - ScreenManager: - id: scr_mngr - Inbox: - id:sc1 - Sent: - id:sc2 - Trash: - id:sc3 - Dialog: - id:sc4 - Test: - id:sc5 - Create: - id:sc6 - NewIdentity: - id:sc7 - Page: - id:sc8 - AddressSuccessful: - id:sc9 - - Button: - id:create - height:100 - size_hint_y: 0.13 - size_hint_x: 0.1 - pos_hint: {'x': 0.85, 'y': 0.5} - background_color: (0,0,0,0) - on_press: scr_mngr.current = 'create' - Image: - source: 'images/plus.png' - y: self.parent.y - 7.5 - x: self.parent.x + self.parent.width - 50 - size: 70, 70 - -: - text: '' - size_hint_y: None - height: 48 - ignore_perpendicular_swipes: True - data_index: 0 - min_move: 20 / self.width - - on__offset: app.update_index(root.data_index, self.index) - - canvas.before: - Color: - rgba: C('FFFFFF33') - - Rectangle: - pos: self.pos - size: self.size - - Line: - rectangle: self.pos + self.size - - Button: - text: 'delete ({}:{})'.format(root.text, root.data_index) - on_press: app.delete(root.data_index) - - Button: - text: root.text - on_press: app.getInboxMessageDetail(self.text) - - Button: - text: 'archive' - on_press: app.archive(root.data_index) - -: - name: 'inbox' - RecycleView: - data: root.data - viewclass: 'SwipeButton' - do_scroll_x: False - scroll_timeout: 100 - - RecycleBoxLayout: - id:rc - orientation: 'vertical' - size_hint_y: None - height: self.minimum_height - default_size_hint: 1, None - canvas.before: - Color: - rgba: 0,0,0, 1 - Rectangle: - pos: self.pos - size: self.size - -: - name: 'sent' - RecycleView: - data: root.data - viewclass: 'SwipeButton' - do_scroll_x: False - scroll_timeout: 100 - - RecycleBoxLayout: - id:rc - orientation: 'vertical' - size_hint_y: None - height: self.minimum_height - default_size_hint: 1, None - canvas.before: - Color: - rgba: 0,0,0, 1 - Rectangle: - pos: self.pos - size: self.size - -: - name: 'trash' - RecycleView: - data: root.data - viewclass: 'SwipeButton' - do_scroll_x: False - scroll_timeout: 100 - - RecycleBoxLayout: - id:rc - orientation: 'vertical' - size_hint_y: None - height: self.minimum_height - default_size_hint: 1, None - canvas.before: - Color: - rgba: 0,0,0, 1 - Rectangle: - pos: self.pos - size: self.size - -: - name: 'dialog' - Label: - text:"I have a good dialox box" - color: 0,0,0,1 -: - name: 'test' - Label: - text:"I am in test" - color: 0,0,0,1 - -: - name: 'create' - GridLayout: - rows: 5 - cols: 1 - padding: 60,60,60,60 - spacing: 50 - BoxLayout: - size_hint_y: None - height: '32dp' - Label: - text: 'FROM' - color: 0,0,0,1 - Spinner: - size_hint: 1,1 - pos_hint: {"x":0,"top":1.} - pos: 10,10 - id: spinner_id - text: app.showmeaddresses(name='text') - values: app.showmeaddresses(name='values') - - BoxLayout: - size_hint_y: None - height: '32dp' - Label: - text: 'TO' - color: 0,0,0,1 - TextInput: - id: recipent - hint_text: 'To' - - BoxLayout: - size_hint_y: None - height: '32dp' - Label: - text: 'SUBJECT' - color: 0,0,0,1 - TextInput: - id: subject - hint_text: 'SUBJECT' - - BoxLayout: - size_hint_y: None - height: '32dp' - Label: - text: 'BODY' - color: 0,0,0,1 - TextInput: - id: message - multiline:True - size_hint: 1,2 - - Button: - text: 'send' - size_hint_y: 0.1 - size_hint_x: 0.2 - height: '32dp' - pos_hint: {'x': .5, 'y': 0.1} - on_press: root.send() - Button: - text: 'cancel' - size_hint_y: 0.1 - size_hint_x: 0.2 - height: '32dp' - pos_hint: {'x': .72, 'y': 0.1} - on_press: root.cancel() - -: - name: 'newidentity' - GridLayout: - padding: '120dp' - cols: 1 - Label: - text:"""Here you may generate as many addresses as you like. Indeed, creating and abandoning addresses is encouraged.""" - line_height:1.5 - text_size:(700,None) - color: 0,0,0,1 - BoxLayout: - CheckBox: - canvas.before: - Color: - rgb: 1,0,0 - Ellipse: - pos:self.center_x-8, self.center_y-8 - size:[16,16] - group: "money" - id:chk - text:"use a random number generator to make an address" - on_active: - root.checked = self.text - active:root.is_active - - Label: - text: "use a random number generator to make an address" - color: 0,0,0,1 - BoxLayout: - CheckBox: - canvas.before: - Color: - rgb: 1,0,0 - Ellipse: - pos:self.center_x-8, self.center_y-8 - size:[16,16] - group: "money" - id:chk - text:"use a pseudo number generator to make an address" - on_active: - root.checked = self.text - active:not root.is_active - Label: - text: "use a pseudo number generator to make an address" - color: 0,0,0,1 - Label: - color: 0,0,0,1 - size_hint_x: .35 - markup: True - text: "[b]{}[/b]".format("Randomly generated addresses") - BoxLayout: - size_hint_y: None - height: '32dp' - Label: - text: "Label (not shown to anyone except you)" - color: 0,0,0,1 - BoxLayout: - size_hint_y: None - height: '32dp' - TextInput: - id: label - - Button: - text: 'Cancel' - size_hint_y: 0.1 - size_hint_x: 0.3 - height: '32dp' - pos_hint: {'x': .1, 'y': 0.1} - Button: - text: 'Ok' - size_hint_y: 0.1 - size_hint_x: 0.3 - height: '32dp' - pos_hint: {'x': .5, 'y': 0.1} - on_press: root.generateaddress() - -: - name: 'page' - Label: - text: 'I am on description of my email yooooo' - color: 0,0,0,1 - -: - name: 'add_sucess' - Label: - text: 'Successfully created a new bit address' - color: 0,0,0,1 diff --git a/src/bitmessagekivy/mpybit.py b/src/bitmessagekivy/mpybit.py deleted file mode 100644 index 3f9b198b..00000000 --- a/src/bitmessagekivy/mpybit.py +++ /dev/null @@ -1,393 +0,0 @@ -import kivy_helper_search -import os -import queues -import shutdown -import state -import time - -from kivy.app import App -from kivy.lang import Builder -from kivy.properties import BooleanProperty -from kivy.clock import Clock -from navigationdrawer import NavigationDrawer -from kivy.properties import ObjectProperty, StringProperty, ListProperty -from kivy.uix.screenmanager import Screen -from kivy.uix.textinput import TextInput -from kivymd.theming import ThemeManager -from kivymd.toolbar import Toolbar -from bmconfigparser import BMConfigParser -from helper_ackPayload import genAckPayload -from addresses import decodeAddress, addBMIfNotPresent -from helper_sql import sqlExecute - -statusIconColor = 'red' - - -class NavigateApp(App, TextInput): - """Application uses kivy in which base Class of Navigate App inherits from the App class.""" - - theme_cls = ThemeManager() - nav_drawer = ObjectProperty() - - def build(self): - """Return a main_widget as a root widget. - - An application can be built if you return a widget on build(), or if you set - self.root. - """ - main_widget = Builder.load_file( - os.path.join(os.path.dirname(__file__), 'main.kv')) - self.nav_drawer = Navigator() - return main_widget - - def getCurrentAccountData(self, text): - """Get Current Address Account Data.""" - state.association = text - self.root.ids.sc1.clear_widgets() - self.root.ids.sc2.clear_widgets() - self.root.ids.sc3.clear_widgets() - self.root.ids.sc1.add_widget(Inbox()) - self.root.ids.sc2.add_widget(Sent()) - self.root.ids.sc3.add_widget(Trash()) - self.root.ids.toolbar.title = BMConfigParser().get( - state.association, 'label') + '({})'.format(state.association) - Inbox() - Sent() - Trash() - - def say_exit(self): - """Exit the application as uses shutdown PyBitmessage.""" - print("**************************EXITING FROM APPLICATION*****************************") - App.get_running_app().stop() - shutdown.doCleanShutdown() - - @staticmethod - def showmeaddresses(name="text"): - """Show the addresses in spinner to make as dropdown.""" - if name == "text": - return BMConfigParser().addresses()[0] - elif name == "values": - return BMConfigParser().addresses() - - def update_index(self, data_index, index): - """Update index after archieve message to trash.""" - if self.root.ids.scr_mngr.current == 'inbox': - self.root.ids.sc1.data[data_index]['index'] = index - elif self.root.ids.scr_mngr.current == 'sent': - self.root.ids.sc2.data[data_index]['index'] = index - elif self.root.ids.scr_mngr.current == 'trash': - self.root.ids.sc3.data[data_index]['index'] = index - - def delete(self, data_index): - """It will make delete using remove function.""" - print("delete {}".format(data_index)) - self._remove(data_index) - - def archive(self, data_index): - """It will make archieve using remove function.""" - print("archive {}".format(data_index)) - self._remove(data_index) - - def _remove(self, data_index): - """It will remove message by resetting the values in recycleview data.""" - if self.root.ids.scr_mngr.current == 'inbox': - self.root.ids.sc1.data.pop(data_index) - self.root.ids.sc1.data = [{ - 'data_index': i, - 'index': d['index'], - 'height': d['height'], - 'text': d['text']} - for i, d in enumerate(self.root.ids.sc1.data) - ] - elif self.root.ids.scr_mngr.current == 'sent': - self.root.ids.sc2.data.pop(data_index) - self.root.ids.sc2.data = [{ - 'data_index': i, - 'index': d['index'], - 'height': d['height'], - 'text': d['text']} - for i, d in enumerate(self.root.ids.sc2.data) - ] - elif self.root.ids.scr_mngr.current == 'trash': - self.root.ids.sc3.data.pop(data_index) - self.root.ids.sc3.data = [{ - 'data_index': i, - 'index': d['index'], - 'height': d['height'], - 'text': d['text']} - for i, d in enumerate(self.root.ids.sc3.data) - ] - - def getInboxMessageDetail(self, instance): - """It will get message detail after make selected message description.""" - try: - self.root.ids.scr_mngr.current = 'page' - except AttributeError: - self.parent.manager.current = 'page' - print('Message Clicked {}'.format(instance)) - - @staticmethod - def getCurrentAccount(): - """It uses to get current account label.""" - return BMConfigParser().get(state.association, 'label') + '({})'.format(state.association) - - -class Navigator(NavigationDrawer): - """Navigator class uses NavigationDrawer. - - It is an UI panel that shows our app's main navigation menu - It is hidden when not in use, but appears when the user swipes - a finger from the left edge of the screen or, when at the top - level of the app, the user touches the drawer icon in the app bar - """ - - image_source = StringProperty('images/qidenticon_two.png') - title = StringProperty('Navigation') - - -class Inbox(Screen): - """Inbox Screen uses screen to show widgets of screens.""" - - data = ListProperty() - - def __init__(self, *args, **kwargs): - super(Inbox, self).__init__(*args, **kwargs) - if state.association == '': - state.association = Navigator().ids.btn.text - Clock.schedule_once(self.init_ui, 0) - - def init_ui(self, dt=0): - """Clock Schdule for method inbox accounts.""" - self.inboxaccounts() - print(dt) - - def inboxaccounts(self): - """Load inbox accounts.""" - account = state.association - self.loadMessagelist(account, 'All', '') - - def loadMessagelist(self, account, where="", what=""): - """Load Inbox list for inbox messages.""" - xAddress = "toaddress" - queryreturn = kivy_helper_search.search_sql( - xAddress, account, 'inbox', where, what, False) - if queryreturn: - self.data = [{ - 'data_index': i, - 'index': 1, - 'height': 48, - 'text': row[4]} - for i, row in enumerate(queryreturn) - ] - else: - self.data = [{ - 'data_index': 1, - 'index': 1, - 'height': 48, - 'text': "yet no message for this account!!!!!!!!!!!!!"} - ] - - -class Page(Screen): - pass - - -class AddressSuccessful(Screen): - pass - - -class Sent(Screen): - """Sent Screen uses screen to show widgets of screens.""" - - data = ListProperty() - - def __init__(self, *args, **kwargs): - super(Sent, self).__init__(*args, **kwargs) - if state.association == '': - state.association = Navigator().ids.btn.text - Clock.schedule_once(self.init_ui, 0) - - def init_ui(self, dt=0): - """Clock Schdule for method sent accounts.""" - self.sentaccounts() - print(dt) - - def sentaccounts(self): - """Load sent accounts.""" - account = state.association - self.loadSent(account, 'All', '') - - def loadSent(self, account, where="", what=""): - """Load Sent list for Sent messages.""" - xAddress = 'fromaddress' - queryreturn = kivy_helper_search.search_sql( - xAddress, account, "sent", where, what, False) - if queryreturn: - self.data = [{ - 'data_index': i, - 'index': 1, - 'height': 48, - 'text': row[2]} - for i, row in enumerate(queryreturn) - ] - else: - self.data = [{ - 'data_index': 1, - 'index': 1, - 'height': 48, - 'text': "yet no message for this account!!!!!!!!!!!!!"} - ] - - -class Trash(Screen): - """Trash Screen uses screen to show widgets of screens.""" - - data = ListProperty() - - def __init__(self, *args, **kwargs): - super(Trash, self).__init__(*args, **kwargs) - if state.association == '': - state.association = Navigator().ids.btn.text - Clock.schedule_once(self.init_ui, 0) - - def init_ui(self, dt=0): - """Clock Schdule for method inbox accounts.""" - self.inboxaccounts() - print(dt) - - def inboxaccounts(self): - """Load inbox accounts.""" - account = state.association - self.loadTrashlist(account, 'All', '') - - def loadTrashlist(self, account, where="", what=""): - """Load Trash list for trashed messages.""" - xAddress = "toaddress" - queryreturn = kivy_helper_search.search_sql( - xAddress, account, 'trash', where, what, False) - if queryreturn: - self.data = [{ - 'data_index': i, - 'index': 1, - 'height': 48, - 'text': row[4]} - for i, row in enumerate(queryreturn) - ] - else: - self.data = [{ - 'data_index': 1, - 'index': 1, - 'height': 48, - 'text': "yet no message for this account!!!!!!!!!!!!!"} - ] - - -class Dialog(Screen): - """Dialog Screen uses screen to show widgets of screens.""" - - pass - - -class Test(Screen): - """Test Screen uses screen to show widgets of screens.""" - - pass - - -class Create(Screen): - """Create Screen uses screen to show widgets of screens.""" - - def __init__(self, *args, **kwargs): - super(Create, self).__init__(*args, **kwargs) - - def send(self): - """Send message from one address to another.""" - fromAddress = self.ids.spinner_id.text - # For now we are using static address i.e we are not using recipent field value. - toAddress = "BM-2cWyUfBdY2FbgyuCb7abFZ49JYxSzUhNFe" - message = self.ids.message.text - subject = self.ids.subject.text - encoding = 3 - print("message: ", self.ids.message.text) - sendMessageToPeople = True - if sendMessageToPeople: - if toAddress != '': - status, addressVersionNumber, streamNumber, ripe = decodeAddress( - toAddress) - if status == 'success': - toAddress = addBMIfNotPresent(toAddress) - - if addressVersionNumber > 4 or addressVersionNumber <= 1: - print("addressVersionNumber > 4 or addressVersionNumber <= 1") - if streamNumber > 1 or streamNumber == 0: - print("streamNumber > 1 or streamNumber == 0") - if statusIconColor == 'red': - print("shared.statusIconColor == 'red'") - stealthLevel = BMConfigParser().safeGetInt( - 'bitmessagesettings', 'ackstealthlevel') - ackdata = genAckPayload(streamNumber, stealthLevel) - t = () - sqlExecute( - '''INSERT INTO sent VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)''', - '', - toAddress, - ripe, - fromAddress, - subject, - message, - ackdata, - int(time.time()), - int(time.time()), - 0, - 'msgqueued', - 0, - 'sent', - encoding, - BMConfigParser().getint('bitmessagesettings', 'ttl')) - toLabel = '' - queues.workerQueue.put(('sendmessage', toAddress)) - print("sqlExecute successfully ##### ##################") - self.ids.message.text = '' - self.ids.spinner_id.text = '' - self.ids.subject.text = '' - self.ids.recipent.text = '' - return None - - -class NewIdentity(Screen): - """Create new address for PyBitmessage.""" - - is_active = BooleanProperty(False) - checked = StringProperty("") - # self.manager.parent.ids.create.children[0].source = 'images/plus-4-xxl.png' - - def generateaddress(self): - """Generate new address.""" - if self.checked == 'use a random number generator to make an address': - queues.apiAddressGeneratorReturnQueue.queue.clear() - streamNumberForAddress = 1 - label = self.ids.label.text - eighteenByteRipe = False - nonceTrialsPerByte = 1000 - payloadLengthExtraBytes = 1000 - - queues.addressGeneratorQueue.put(( - 'createRandomAddress', - 4, streamNumberForAddress, - label, 1, "", eighteenByteRipe, - nonceTrialsPerByte, - payloadLengthExtraBytes) - ) - self.manager.current = 'add_sucess' - - -if __name__ == '__main__': - NavigateApp().run() diff --git a/src/bitmessagemain.py b/src/bitmessagemain.py index 06b8b8a5..4a27f967 100755 --- a/src/bitmessagemain.py +++ b/src/bitmessagemain.py @@ -353,8 +353,8 @@ class Main(object): bitmessagecurses.runwrapper() elif state.kivy: config.remove_option('bitmessagesettings', 'dontconnect') - from bitmessagekivy.mpybit import NavigateApp - NavigateApp().run() + # from bitmessagekivy.mpybit import NavigateApp + # NavigateApp().run() else: import bitmessageqt bitmessageqt.run() diff --git a/src/kivymd/LICENSE b/src/kivymd/LICENSE deleted file mode 100644 index a17ea136..00000000 --- a/src/kivymd/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Andrés Rodríguez and KivyMD contributors - -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. \ No newline at end of file diff --git a/src/kivymd/__init__.py b/src/kivymd/__init__.py deleted file mode 100644 index bc07270c..00000000 --- a/src/kivymd/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -# -*- coding: utf-8 -*- -import os - -path = os.path.dirname(__file__) -fonts_path = os.path.join(path, "fonts/") -images_path = os.path.join(path, 'images/') diff --git a/src/kivymd/accordion.py b/src/kivymd/accordion.py deleted file mode 100644 index 6e816ca6..00000000 --- a/src/kivymd/accordion.py +++ /dev/null @@ -1,254 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.properties import StringProperty, ListProperty, OptionProperty -from kivy.utils import get_color_from_hex -from kivymd.color_definitions import colors -from kivymd.theming import ThemableBehavior -from kivy.uix.accordion import Accordion, AccordionItem -from kivymd.backgroundcolorbehavior import BackgroundColorBehavior -from kivy.uix.boxlayout import BoxLayout - - -class MDAccordionItemTitleLayout(ThemableBehavior, BackgroundColorBehavior, BoxLayout): - pass - - -class MDAccordion(ThemableBehavior, BackgroundColorBehavior, Accordion): - pass - - -class MDAccordionItem(ThemableBehavior, AccordionItem): - title_theme_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - ''' Color theme for title text and icon ''' - - title_color = ListProperty(None, allownone=True) - ''' Color for title text and icon if `title_theme_color` is Custom ''' - - background_color = ListProperty(None, allownone=True) - ''' Color for the background of the accordian item title in rgba format. - ''' - - divider_color = ListProperty(None, allownone=True) - ''' Color for dividers between different titles in rgba format - To remove the divider set a color with an alpha of 0. - ''' - - indicator_color = ListProperty(None, allownone=True) - ''' Color for the indicator on the side of the active item in rgba format - To remove the indicator set a color with an alpha of 0. - ''' - - font_style = OptionProperty( - 'Subhead', options=['Body1', 'Body2', 'Caption', 'Subhead', 'Title', - 'Headline', 'Display1', 'Display2', 'Display3', - 'Display4', 'Button', 'Icon']) - ''' Font style to use for the title text ''' - - title_template = StringProperty('MDAccordionItemTitle') - ''' Template to use for the title ''' - - icon = StringProperty(None,allownone=True) - ''' Icon name to use when this item is expanded ''' - - icon_expanded = StringProperty('chevron-up') - ''' Icon name to use when this item is expanded ''' - - icon_collapsed = StringProperty('chevron-down') - ''' Icon name to use when this item is collapsed ''' - - -Builder.load_string(''' -#:import MDLabel kivymd.label.MDLabel -#:import md_icons kivymd.icon_definitions.md_icons - - -: - canvas.before: - Color: - rgba: self.background_color or self.theme_cls.primary_color - Rectangle: - size:self.size - pos:self.pos - - PushMatrix - Translate: - xy: (dp(2),0) if self.orientation == 'vertical' else (0,dp(2)) - canvas.after: - PopMatrix - Color: - rgba: self.divider_color or self.theme_cls.divider_color - Rectangle: - size:(dp(1),self.height) if self.orientation == 'horizontal' else (self.width,dp(1)) - pos:self.pos - Color: - rgba: [0,0,0,0] if self.collapse else (self.indicator_color or self.theme_cls.accent_color) - Rectangle: - size:(dp(2),self.height) if self.orientation == 'vertical' else (self.width,dp(2)) - pos:self.pos - -[MDAccordionItemTitle@MDAccordionItemTitleLayout]: - padding: '12dp' - spacing: '12dp' - orientation: 'horizontal' if ctx.item.orientation=='vertical' else 'vertical' - canvas: - PushMatrix - Translate: - xy: (-dp(2),0) if ctx.item.orientation == 'vertical' else (0,-dp(2)) - - Color: - rgba: self.background_color or self.theme_cls.primary_color - Rectangle: - size:self.size - pos:self.pos - - canvas.after: - Color: - rgba: [0,0,0,0] if ctx.item.collapse else (ctx.item.indicator_color or self.theme_cls.accent_color) - Rectangle: - size:(dp(2),self.height) if ctx.item.orientation == 'vertical' else (self.width,dp(2)) - pos:self.pos - PopMatrix - MDLabel: - id:_icon - theme_text_color:ctx.item.title_theme_color if ctx.item.icon else 'Custom' - text_color:ctx.item.title_color if ctx.item.icon else [0,0,0,0] - text: md_icons[ctx.item.icon if ctx.item.icon else 'menu'] - font_style:'Icon' - size_hint: (None,1) if ctx.item.orientation == 'vertical' else (1,None) - size: ((self.texture_size[0],1) if ctx.item.orientation == 'vertical' else (1,self.texture_size[1])) \ - if ctx.item.icon else (0,0) - text_size: (self.width, None) if ctx.item.orientation=='vertical' else (None,self.width) - canvas.before: - PushMatrix - Rotate: - angle: 90 if ctx.item.orientation == 'horizontal' else 0 - origin: self.center - canvas.after: - PopMatrix - MDLabel: - id:_label - theme_text_color:ctx.item.title_theme_color - text_color:ctx.item.title_color - text: ctx.item.title - font_style:ctx.item.font_style - text_size: (self.width, None) if ctx.item.orientation=='vertical' else (None,self.width) - canvas.before: - PushMatrix - Rotate: - angle: 90 if ctx.item.orientation == 'horizontal' else 0 - origin: self.center - canvas.after: - PopMatrix - - MDLabel: - id:_expand_icon - theme_text_color:ctx.item.title_theme_color - text_color:ctx.item.title_color - font_style:'Icon' - size_hint: (None,1) if ctx.item.orientation == 'vertical' else (1,None) - size: (self.texture_size[0],1) if ctx.item.orientation == 'vertical' else (1,self.texture_size[1]) - text:md_icons[ctx.item.icon_collapsed if ctx.item.collapse else ctx.item.icon_expanded] - halign: 'right' if ctx.item.orientation=='vertical' else 'center' - #valign: 'middle' if ctx.item.orientation=='vertical' else 'bottom' - canvas.before: - PushMatrix - Rotate: - angle: 90 if ctx.item.orientation == 'horizontal' else 0 - origin:self.center - canvas.after: - PopMatrix - -''') - -if __name__ == '__main__': - from kivy.app import App - from kivymd.theming import ThemeManager - - class AccordionApp(App): - theme_cls = ThemeManager() - - def build(self): - # self.theme_cls.primary_palette = 'Indigo' - return Builder.load_string(""" -#:import MDLabel kivymd.label.MDLabel -#:import MDList kivymd.list.MDList -#:import OneLineListItem kivymd.list.OneLineListItem -BoxLayout: - spacing: '64dp' - MDAccordion: - orientation:'vertical' - MDAccordionItem: - title:'Item 1' - icon: 'home' - ScrollView: - MDList: - OneLineListItem: - text: "Subitem 1" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - OneLineListItem: - text: "Subitem 2" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - OneLineListItem: - text: "Subitem 3" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - MDAccordionItem: - title:'Item 2' - icon: 'globe' - ScrollView: - MDList: - OneLineListItem: - text: "Subitem 4" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - OneLineListItem: - text: "Subitem 5" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - OneLineListItem: - text: "Subitem 6" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - MDAccordionItem: - title:'Item 3' - ScrollView: - MDList: - OneLineListItem: - text: "Subitem 7" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - OneLineListItem: - text: "Subitem 8" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - OneLineListItem: - text: "Subitem 9" - theme_text_color: 'Custom' - text_color: [1,1,1,1] - MDAccordion: - orientation:'horizontal' - MDAccordionItem: - title:'Item 1' - icon: 'home' - MDLabel: - text:'Content 1' - theme_text_color:'Primary' - MDAccordionItem: - title:'Item 2' - MDLabel: - text:'Content 2' - theme_text_color:'Primary' - MDAccordionItem: - title:'Item 3' - MDLabel: - text:'Content 3' - theme_text_color:'Primary' -""") - - - AccordionApp().run() diff --git a/src/kivymd/backgroundcolorbehavior.py b/src/kivymd/backgroundcolorbehavior.py deleted file mode 100644 index bd98f129..00000000 --- a/src/kivymd/backgroundcolorbehavior.py +++ /dev/null @@ -1,23 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.lang import Builder -from kivy.properties import BoundedNumericProperty, ReferenceListProperty -from kivy.uix.widget import Widget - -Builder.load_string(''' - - canvas: - Color: - rgba: self.background_color - Rectangle: - size: self.size - pos: self.pos -''') - - -class BackgroundColorBehavior(Widget): - r = BoundedNumericProperty(1., min=0., max=1.) - g = BoundedNumericProperty(1., min=0., max=1.) - b = BoundedNumericProperty(1., min=0., max=1.) - a = BoundedNumericProperty(0., min=0., max=1.) - - background_color = ReferenceListProperty(r, g, b, a) diff --git a/src/kivymd/bottomsheet.py b/src/kivymd/bottomsheet.py deleted file mode 100644 index 901322b0..00000000 --- a/src/kivymd/bottomsheet.py +++ /dev/null @@ -1,211 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Bottom Sheets -============= - -`Material Design spec Bottom Sheets page `_ - -In this module there's the :class:`MDBottomSheet` class which will let you implement your own Material Design Bottom Sheets, and there are two classes called :class:`MDListBottomSheet` and :class:`MDGridBottomSheet` implementing the ones mentioned in the spec. - -Examples --------- - -.. note:: - - These widgets are designed to be called from Python code only. - -For :class:`MDListBottomSheet`: - -.. code-block:: python - - bs = MDListBottomSheet() - bs.add_item("Here's an item with text only", lambda x: x) - bs.add_item("Here's an item with an icon", lambda x: x, icon='md-cast') - bs.add_item("Here's another!", lambda x: x, icon='md-nfc') - bs.open() - -For :class:`MDListBottomSheet`: - -.. code-block:: python - - bs = MDGridBottomSheet() - bs.add_item("Facebook", lambda x: x, icon_src='./assets/facebook-box.png') - bs.add_item("YouTube", lambda x: x, icon_src='./assets/youtube-play.png') - bs.add_item("Twitter", lambda x: x, icon_src='./assets/twitter.png') - bs.add_item("Da Cloud", lambda x: x, icon_src='./assets/cloud-upload.png') - bs.add_item("Camera", lambda x: x, icon_src='./assets/camera.png') - bs.open() - -API ---- -''' -from kivy.clock import Clock -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.properties import ObjectProperty, StringProperty -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.floatlayout import FloatLayout -from kivy.uix.gridlayout import GridLayout -from kivy.uix.modalview import ModalView -from kivy.uix.scrollview import ScrollView -from kivymd.backgroundcolorbehavior import BackgroundColorBehavior -from kivymd.label import MDLabel -from kivymd.list import MDList, OneLineListItem, ILeftBody, \ - OneLineIconListItem -from kivymd.theming import ThemableBehavior - -Builder.load_string(''' - - background: 'atlas://data/images/defaulttheme/action_group_disabled' - background_color: 0,0,0,.8 - sv: sv - upper_padding: upper_padding - gl_content: gl_content - ScrollView: - id: sv - do_scroll_x: False - BoxLayout: - size_hint_y: None - orientation: 'vertical' - padding: 0,1,0,0 - height: upper_padding.height + gl_content.height + 1 # +1 to allow overscroll - BsPadding: - id: upper_padding - size_hint_y: None - height: root.height - min(root.width * 9 / 16, gl_content.height) - on_release: root.dismiss() - BottomSheetContent: - id: gl_content - size_hint_y: None - background_color: root.theme_cls.bg_normal - cols: 1 -''') - - -class BsPadding(ButtonBehavior, FloatLayout): - pass - - -class BottomSheetContent(BackgroundColorBehavior, GridLayout): - pass - - -class MDBottomSheet(ThemableBehavior, ModalView): - sv = ObjectProperty() - upper_padding = ObjectProperty() - gl_content = ObjectProperty() - dismiss_zone_scroll = 1000 # Arbitrary high number - - def open(self, *largs): - super(MDBottomSheet, self).open(*largs) - Clock.schedule_once(self.set_dismiss_zone, 0) - - def set_dismiss_zone(self, *largs): - # Scroll to right below overscroll threshold: - self.sv.scroll_y = 1 - self.sv.convert_distance_to_scroll(0, 1)[1] - - # This is a line where m (slope) is 1/6 and b (y-intercept) is 80: - self.dismiss_zone_scroll = self.sv.convert_distance_to_scroll( - 0, (self.height - self.upper_padding.height) * (1 / 6.0) + 80)[ - 1] - # Uncomment next line if the limit should just be half of - # visible content on open (capped by specs to 16 units to width/9: - # self.dismiss_zone_scroll = (self.sv.convert_distance_to_scroll( - # 0, self.height - self.upper_padding.height)[1] * 0.50) - - # Check if user has overscrolled enough to dismiss bottom sheet: - self.sv.bind(on_scroll_stop=self.check_if_scrolled_to_death) - - def check_if_scrolled_to_death(self, *largs): - if self.sv.scroll_y >= 1 + self.dismiss_zone_scroll: - self.dismiss() - - def add_widget(self, widget, index=0): - if type(widget) == ScrollView: - super(MDBottomSheet, self).add_widget(widget, index) - else: - self.gl_content.add_widget(widget,index) - - -Builder.load_string(''' -#:import md_icons kivymd.icon_definitions.md_icons - - font_style: 'Icon' - text: u"{}".format(md_icons[root.icon]) - halign: 'center' - theme_text_color: 'Primary' - valign: 'middle' -''') - - -class ListBSIconLeft(ILeftBody, MDLabel): - icon = StringProperty() - - -class MDListBottomSheet(MDBottomSheet): - mlist = ObjectProperty() - - def __init__(self, **kwargs): - super(MDListBottomSheet, self).__init__(**kwargs) - self.mlist = MDList() - self.gl_content.add_widget(self.mlist) - Clock.schedule_once(self.resize_content_layout, 0) - - def resize_content_layout(self, *largs): - self.gl_content.height = self.mlist.height - - def add_item(self, text, callback, icon=None): - if icon: - item = OneLineIconListItem(text=text, on_release=callback) - item.add_widget(ListBSIconLeft(icon=icon)) - else: - item = OneLineListItem(text=text, on_release=callback) - - item.bind(on_release=lambda x: self.dismiss()) - self.mlist.add_widget(item) - - -Builder.load_string(''' - - orientation: 'vertical' - padding: 0, dp(24), 0, 0 - size_hint_y: None - size: dp(64), dp(96) - BoxLayout: - padding: dp(8), 0, dp(8), dp(8) - size_hint_y: None - height: dp(48) - Image: - source: root.source - MDLabel: - font_style: 'Caption' - theme_text_color: 'Secondary' - text: root.caption - halign: 'center' -''') - - -class GridBSItem(ButtonBehavior, BoxLayout): - source = StringProperty() - - caption = StringProperty() - - -class MDGridBottomSheet(MDBottomSheet): - def __init__(self, **kwargs): - super(MDGridBottomSheet, self).__init__(**kwargs) - self.gl_content.padding = (dp(16), 0, dp(16), dp(24)) - self.gl_content.height = dp(24) - self.gl_content.cols = 3 - - def add_item(self, text, callback, icon_src): - item = GridBSItem( - caption=text, - on_release=callback, - source=icon_src - ) - item.bind(on_release=lambda x: self.dismiss()) - if len(self.gl_content.children) % 3 == 0: - self.gl_content.height += dp(96) - self.gl_content.add_widget(item) diff --git a/src/kivymd/button.py b/src/kivymd/button.py deleted file mode 100644 index 75016716..00000000 --- a/src/kivymd/button.py +++ /dev/null @@ -1,453 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Buttons -======= - -`Material Design spec, Buttons page `_ - -`Material Design spec, Buttons: Floating Action Button page `_ - -TO-DO: DOCUMENT MODULE -''' -from kivy.clock import Clock -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.utils import get_color_from_hex -from kivy.properties import StringProperty, BoundedNumericProperty, \ - ListProperty, AliasProperty, BooleanProperty, NumericProperty, \ - OptionProperty -from kivy.uix.anchorlayout import AnchorLayout -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.boxlayout import BoxLayout -from kivy.animation import Animation -from kivymd.backgroundcolorbehavior import BackgroundColorBehavior -from kivymd.ripplebehavior import CircularRippleBehavior, \ - RectangularRippleBehavior -from kivymd.elevationbehavior import ElevationBehavior, \ - RoundElevationBehavior -from kivymd.theming import ThemableBehavior -from kivymd.color_definitions import colors - -Builder.load_string(''' -#:import md_icons kivymd.icon_definitions.md_icons -#:import colors kivymd.color_definitions.colors -#:import MDLabel kivymd.label.MDLabel - - size_hint: (None, None) - size: (dp(48), dp(48)) - padding: dp(12) - theme_text_color: 'Primary' - MDLabel: - id: _label - font_style: 'Icon' - text: u"{}".format(md_icons[root.icon]) - halign: 'center' - theme_text_color: root.theme_text_color - text_color: root.text_color - opposite_colors: root.opposite_colors - valign: 'middle' - - - canvas: - Color: - #rgba: self.background_color if self.state == 'normal' else self._bg_color_down - rgba: self._current_button_color - Rectangle: - size: self.size - pos: self.pos - size_hint: (None, None) - height: dp(36) - width: _label.texture_size[0] + dp(16) - padding: (dp(8), 0) - theme_text_color: 'Custom' - text_color: root.theme_cls.primary_color - MDLabel: - id: _label - text: root._text - font_style: 'Button' - size_hint_x: None - text_size: (None, root.height) - height: self.texture_size[1] - theme_text_color: root.theme_text_color - text_color: root.text_color - valign: 'middle' - halign: 'center' - opposite_colors: root.opposite_colors - -: - canvas: - Clear - Color: - rgba: self.background_color_disabled if self.disabled else \ - (self.background_color if self.state == 'normal' else self.background_color_down) - Rectangle: - size: self.size - pos: self.pos - - anchor_x: 'center' - anchor_y: 'center' - background_color: root.theme_cls.primary_color - background_color_down: root.theme_cls.primary_dark - background_color_disabled: root.theme_cls.divider_color - theme_text_color: 'Primary' - MDLabel: - id: label - font_style: 'Button' - text: root._text - size_hint: None, None - width: root.width - text_size: self.width, None - height: self.texture_size[1] - theme_text_color: root.theme_text_color - text_color: root.text_color - opposite_colors: root.opposite_colors - disabled: root.disabled - halign: 'center' - valign: 'middle' - -: - canvas: - Clear - Color: - rgba: self.background_color_disabled if self.disabled else \ - (self.background_color if self.state == 'normal' else self.background_color_down) - Ellipse: - size: self.size - pos: self.pos - - anchor_x: 'center' - anchor_y: 'center' - background_color: root.theme_cls.accent_color - background_color_down: root.theme_cls.accent_dark - background_color_disabled: root.theme_cls.divider_color - theme_text_color: 'Primary' - MDLabel: - id: label - font_style: 'Icon' - text: u"{}".format(md_icons[root.icon]) - size_hint: None, None - size: dp(24), dp(24) - text_size: self.size - theme_text_color: root.theme_text_color - text_color: root.text_color - opposite_colors: root.opposite_colors - disabled: root.disabled - halign: 'center' - valign: 'middle' -''') - - -class MDIconButton(CircularRippleBehavior, ButtonBehavior, BoxLayout): - icon = StringProperty('circle') - theme_text_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - text_color = ListProperty(None, allownone=True) - opposite_colors = BooleanProperty(False) - - -class MDFlatButton(ThemableBehavior, RectangularRippleBehavior, - ButtonBehavior, BackgroundColorBehavior, AnchorLayout): - width = BoundedNumericProperty(dp(64), min=dp(64), max=None, - errorhandler=lambda x: dp(64)) - - text_color = ListProperty() - - text = StringProperty('') - theme_text_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - text_color = ListProperty(None, allownone=True) - - _text = StringProperty('') - _bg_color_down = ListProperty([0, 0, 0, 0]) - _current_button_color = ListProperty([0, 0, 0, 0]) - - def __init__(self, **kwargs): - super(MDFlatButton, self).__init__(**kwargs) - self._current_button_color = self.background_color - self._bg_color_down = get_color_from_hex( - colors[self.theme_cls.theme_style]['FlatButtonDown']) - - Clock.schedule_once(lambda x: self.ids._label.bind( - texture_size=self.update_width_on_label_texture)) - - def update_width_on_label_texture(self, instance, value): - self.ids._label.width = value[0] - - def on_text(self, instance, value): - self._text = value.upper() - - def on_touch_down(self, touch): - if touch.is_mouse_scrolling: - return False - elif not self.collide_point(touch.x, touch.y): - return False - elif self in touch.ud: - return False - elif self.disabled: - return False - else: - self.fade_bg = Animation(duration=.2, _current_button_color=get_color_from_hex( - colors[self.theme_cls.theme_style]['FlatButtonDown'])) - self.fade_bg.start(self) - return super(MDFlatButton, self).on_touch_down(touch) - - def on_touch_up(self, touch): - if touch.grab_current is self: - self.fade_bg.stop_property(self, '_current_button_color') - Animation(duration=.05, _current_button_color=self.background_color).start(self) - return super(MDFlatButton, self).on_touch_up(touch) - - -class MDRaisedButton(ThemableBehavior, RectangularRippleBehavior, - ElevationBehavior, ButtonBehavior, - AnchorLayout): - _bg_color_down = ListProperty([]) - background_color = ListProperty() - background_color_down = ListProperty() - background_color_disabled = ListProperty() - theme_text_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - text_color = ListProperty(None, allownone=True) - - def _get_bg_color_down(self): - return self._bg_color_down - - def _set_bg_color_down(self, color, alpha=None): - if len(color) == 2: - self._bg_color_down = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._bg_color_down[3] = alpha - elif len(color) == 4: - self._bg_color_down = color - - background_color_down = AliasProperty(_get_bg_color_down, - _set_bg_color_down, - bind=('_bg_color_down',)) - - _bg_color_disabled = ListProperty([]) - - def _get_bg_color_disabled(self): - return self._bg_color_disabled - - def _set_bg_color_disabled(self, color, alpha=None): - if len(color) == 2: - self._bg_color_disabled = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._bg_color_disabled[3] = alpha - elif len(color) == 4: - self._bg_color_disabled = color - - background_color_disabled = AliasProperty(_get_bg_color_disabled, - _set_bg_color_disabled, - bind=('_bg_color_disabled',)) - - _elev_norm = NumericProperty(2) - - def _get_elev_norm(self): - return self._elev_norm - - def _set_elev_norm(self, value): - self._elev_norm = value if value <= 12 else 12 - self._elev_raised = (value + 6) if value + 6 <= 12 else 12 - self.elevation = self._elev_norm - - elevation_normal = AliasProperty(_get_elev_norm, _set_elev_norm, - bind=('_elev_norm',)) - - _elev_raised = NumericProperty(8) - - def _get_elev_raised(self): - return self._elev_raised - - def _set_elev_raised(self, value): - self._elev_raised = value if value + self._elev_norm <= 12 else 12 - - elevation_raised = AliasProperty(_get_elev_raised, _set_elev_raised, - bind=('_elev_raised',)) - - text = StringProperty() - - _text = StringProperty() - - def __init__(self, **kwargs): - super(MDRaisedButton, self).__init__(**kwargs) - self.elevation_press_anim = Animation(elevation=self.elevation_raised, - duration=.2, t='out_quad') - self.elevation_release_anim = Animation( - elevation=self.elevation_normal, duration=.2, t='out_quad') - - def on_disabled(self, instance, value): - if value: - self.elevation = 0 - else: - self.elevation = self.elevation_normal - super(MDRaisedButton, self).on_disabled(instance, value) - - def on_touch_down(self, touch): - if not self.disabled: - if touch.is_mouse_scrolling: - return False - if not self.collide_point(touch.x, touch.y): - return False - if self in touch.ud: - return False - Animation.cancel_all(self, 'elevation') - self.elevation_press_anim.start(self) - return super(MDRaisedButton, self).on_touch_down(touch) - - def on_touch_up(self, touch): - if not self.disabled: - if touch.grab_current is not self: - return super(ButtonBehavior, self).on_touch_up(touch) - Animation.cancel_all(self, 'elevation') - self.elevation_release_anim.start(self) - else: - Animation.cancel_all(self, 'elevation') - self.elevation = 0 - return super(MDRaisedButton, self).on_touch_up(touch) - - def on_text(self, instance, text): - self._text = text.upper() - - def on__elev_norm(self, instance, value): - self.elevation_release_anim = Animation(elevation=value, - duration=.2, t='out_quad') - - def on__elev_raised(self, instance, value): - self.elevation_press_anim = Animation(elevation=value, - duration=.2, t='out_quad') - - -class MDFloatingActionButton(ThemableBehavior, CircularRippleBehavior, - RoundElevationBehavior, ButtonBehavior, - AnchorLayout): - _bg_color_down = ListProperty([]) - background_color = ListProperty() - background_color_down = ListProperty() - background_color_disabled = ListProperty() - theme_text_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - text_color = ListProperty(None, allownone=True) - - def _get_bg_color_down(self): - return self._bg_color_down - - def _set_bg_color_down(self, color, alpha=None): - if len(color) == 2: - self._bg_color_down = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._bg_color_down[3] = alpha - elif len(color) == 4: - self._bg_color_down = color - - background_color_down = AliasProperty(_get_bg_color_down, - _set_bg_color_down, - bind=('_bg_color_down',)) - - _bg_color_disabled = ListProperty([]) - - def _get_bg_color_disabled(self): - return self._bg_color_disabled - - def _set_bg_color_disabled(self, color, alpha=None): - if len(color) == 2: - self._bg_color_disabled = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._bg_color_disabled[3] = alpha - elif len(color) == 4: - self._bg_color_disabled = color - - background_color_disabled = AliasProperty(_get_bg_color_disabled, - _set_bg_color_disabled, - bind=('_bg_color_disabled',)) - icon = StringProperty('android') - - _elev_norm = NumericProperty(6) - - def _get_elev_norm(self): - return self._elev_norm - - def _set_elev_norm(self, value): - self._elev_norm = value if value <= 12 else 12 - self._elev_raised = (value + 6) if value + 6 <= 12 else 12 - self.elevation = self._elev_norm - - elevation_normal = AliasProperty(_get_elev_norm, _set_elev_norm, - bind=('_elev_norm',)) - - # _elev_raised = NumericProperty(12) - _elev_raised = NumericProperty(6) - - def _get_elev_raised(self): - return self._elev_raised - - def _set_elev_raised(self, value): - self._elev_raised = value if value + self._elev_norm <= 12 else 12 - - elevation_raised = AliasProperty(_get_elev_raised, _set_elev_raised, - bind=('_elev_raised',)) - - def __init__(self, **kwargs): - if self.elevation_raised == 0 and self.elevation_normal + 6 <= 12: - self.elevation_raised = self.elevation_normal + 6 - elif self.elevation_raised == 0: - self.elevation_raised = 12 - - super(MDFloatingActionButton, self).__init__(**kwargs) - - self.elevation_press_anim = Animation(elevation=self.elevation_raised, - duration=.2, t='out_quad') - self.elevation_release_anim = Animation( - elevation=self.elevation_normal, duration=.2, t='out_quad') - - def _set_ellipse(self, instance, value): - ellipse = self.ellipse - ripple_rad = self.ripple_rad - - ellipse.size = (ripple_rad, ripple_rad) - ellipse.pos = (self.center_x - ripple_rad / 2., - self.center_y - ripple_rad / 2.) - - def on_disabled(self, instance, value): - super(MDFloatingActionButton, self).on_disabled(instance, value) - if self.disabled: - self.elevation = 0 - else: - self.elevation = self.elevation_normal - - def on_touch_down(self, touch): - if not self.disabled: - if touch.is_mouse_scrolling: - return False - if not self.collide_point(touch.x, touch.y): - return False - if self in touch.ud: - return False - self.elevation_press_anim.stop(self) - self.elevation_press_anim.start(self) - return super(MDFloatingActionButton, self).on_touch_down(touch) - - def on_touch_up(self, touch): - if not self.disabled: - if touch.grab_current is not self: - return super(ButtonBehavior, self).on_touch_up(touch) - self.elevation_release_anim.stop(self) - self.elevation_release_anim.start(self) - return super(MDFloatingActionButton, self).on_touch_up(touch) - - def on_elevation_normal(self, instance, value): - self.elevation = value - - def on_elevation_raised(self, instance, value): - if self.elevation_raised == 0 and self.elevation_normal + 6 <= 12: - self.elevation_raised = self.elevation_normal + 6 - elif self.elevation_raised == 0: - self.elevation_raised = 12 diff --git a/src/kivymd/card.py b/src/kivymd/card.py deleted file mode 100644 index d411644b..00000000 --- a/src/kivymd/card.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.lang import Builder -from kivy.properties import BoundedNumericProperty, ReferenceListProperty, ListProperty,BooleanProperty -from kivy.uix.boxlayout import BoxLayout -from kivymd.elevationbehavior import ElevationBehavior -from kivymd.theming import ThemableBehavior -from kivy.metrics import dp -from kivy.uix.widget import Widget - -Builder.load_string(''' - - canvas: - Color: - rgba: self.background_color - RoundedRectangle: - size: self.size - pos: self.pos - radius: [self.border_radius] - Color: - rgba: self.theme_cls.divider_color - a: self.border_color_a - Line: - rounded_rectangle: (self.pos[0],self.pos[1],self.size[0],self.size[1],self.border_radius) - background_color: self.theme_cls.bg_light - - - canvas: - Color: - rgba: self.theme_cls.divider_color - Rectangle: - size: self.size - pos: self.pos -''') - - -class MDSeparator(ThemableBehavior, BoxLayout): - """ A separator line """ - def __init__(self, *args, **kwargs): - super(MDSeparator, self).__init__(*args, **kwargs) - self.on_orientation() - - def on_orientation(self,*args): - self.size_hint = (1, None) if self.orientation == 'horizontal' else (None, 1) - if self.orientation == 'horizontal': - self.height = dp(1) - else: - self.width = dp(1) - - -class MDCard(ThemableBehavior, ElevationBehavior, BoxLayout): - r = BoundedNumericProperty(1., min=0., max=1.) - g = BoundedNumericProperty(1., min=0., max=1.) - b = BoundedNumericProperty(1., min=0., max=1.) - a = BoundedNumericProperty(0., min=0., max=1.) - - border_radius = BoundedNumericProperty(dp(3),min=0) - border_color_a = BoundedNumericProperty(0, min=0., max=1.) - background_color = ReferenceListProperty(r, g, b, a) diff --git a/src/kivymd/color_definitions.py b/src/kivymd/color_definitions.py deleted file mode 100644 index c81bd731..00000000 --- a/src/kivymd/color_definitions.py +++ /dev/null @@ -1,360 +0,0 @@ -colors = { - 'Pink': { - '50': 'fce4ec', - '100': 'f8bbd0', - '200': 'f48fb1', - '300': 'f06292', - '400': 'ec407a', - '500': 'e91e63', - '600': 'd81b60', - '700': 'C2185B', - '800': 'ad1457', - '900': '88e4ff', - 'A100': 'ff80ab', - 'A400': 'F50057', - 'A700': 'c51162', - 'A200': 'ff4081' - }, - - 'Blue': { - '200': '90caf9', - '900': '0D47A1', - '600': '1e88e5', - 'A100': '82b1ff', - '300': '64b5f6', - 'A400': '2979ff', - '700': '1976d2', - '50': 'e3f2fd', - 'A700': '2962ff', - '400': '42a5f5', - '100': 'bbdefb', - '800': '1565c0', - 'A200': '448aff', - '500': '2196f3' - }, - - 'Indigo': { - '200': '9fa8da', - '900': '1a237e', - '600': '3949ab', - 'A100': '8c9eff', - '300': '7986cb', - 'A400': '3d5afe', - '700': '303f9f', - '50': 'e8eaf6', - 'A700': '304ffe', - '400': '5c6bc0', - '100': 'c5cae9', - '800': '283593', - 'A200': '536dfe', - '500': '3f51b5' - }, - - 'BlueGrey': { - '200': 'b0bec5', - '900': '263238', - '600': '546e7a', - '300': '90a4ae', - '700': '455a64', - '50': 'eceff1', - '400': '78909c', - '100': 'cfd8dc', - '800': '37474f', - '500': '607d8b' - }, - - 'Brown': { - '200': 'bcaaa4', - '900': '3e2723', - '600': '6d4c41', - '300': 'a1887f', - '700': '5d4037', - '50': 'efebe9', - '400': '8d6e63', - '100': 'd7ccc8', - '800': '4e342e', - '500': '795548' - }, - - 'LightBlue': { - '200': '81d4fa', - '900': '01579B', - '600': '039BE5', - 'A100': '80d8ff', - '300': '4fc3f7', - 'A400': '00B0FF', - '700': '0288D1', - '50': 'e1f5fe', - 'A700': '0091EA', - '400': '29b6f6', - '100': 'b3e5fc', - '800': '0277BD', - 'A200': '40c4ff', - '500': '03A9F4' - }, - - 'Purple': { - '200': 'ce93d8', - '900': '4a148c', - '600': '8e24aa', - 'A100': 'ea80fc', - '300': 'ba68c8', - 'A400': 'D500F9', - '700': '7b1fa2', - '50': 'f3e5f5', - 'A700': 'AA00FF', - '400': 'ab47bc', - '100': 'e1bee7', - '800': '6a1b9a', - 'A200': 'e040fb', - '500': '9c27b0' - }, - - 'Grey': { - '200': 'eeeeee', - '900': '212121', - '600': '757575', - '300': 'e0e0e0', - '700': '616161', - '50': 'fafafa', - '400': 'bdbdbd', - '100': 'f5f5f5', - '800': '424242', - '500': '9e9e9e' - }, - - 'Yellow': { - '200': 'fff59d', - '900': 'f57f17', - '600': 'fdd835', - 'A100': 'ffff8d', - '300': 'fff176', - 'A400': 'FFEA00', - '700': 'fbc02d', - '50': 'fffde7', - 'A700': 'FFD600', - '400': 'ffee58', - '100': 'fff9c4', - '800': 'f9a825', - 'A200': 'FFFF00', - '500': 'ffeb3b' - }, - - 'LightGreen': { - '200': 'c5e1a5', - '900': '33691e', - '600': '7cb342', - 'A100': 'ccff90', - '300': 'aed581', - 'A400': '76FF03', - '700': '689f38', - '50': 'f1f8e9', - 'A700': '64dd17', - '400': '9ccc65', - '100': 'dcedc8', - '800': '558b2f', - 'A200': 'b2ff59', - '500': '8bc34a' - }, - - 'DeepOrange': { - '200': 'ffab91', - '900': 'bf36c', - '600': 'f4511e', - 'A100': 'ff9e80', - '300': 'ff8a65', - 'A400': 'FF3D00', - '700': 'e64a19', - '50': 'fbe9e7', - 'A700': 'DD2C00', - '400': 'ff7043', - '100': 'ffccbc', - '800': 'd84315', - 'A200': 'ff6e40', - '500': 'ff5722' - }, - - 'Green': { - '200': 'a5d6a7', - '900': '1b5e20', - '600': '43a047', - 'A100': 'b9f6ca', - '300': '81c784', - 'A400': '00E676', - '700': '388e3c', - '50': 'e8f5e9', - 'A700': '00C853', - '400': '66bb6a', - '100': 'c8e6c9', - '800': '2e7d32', - 'A200': '69f0ae', - '500': '4caf50' - }, - - 'Red': { - '200': 'ef9a9a', - '900': 'b71c1c', - '600': 'e53935', - 'A100': 'ff8a80', - '300': 'e57373', - 'A400': 'ff1744', - '700': 'd32f2f', - '50': 'ffebee', - 'A700': 'd50000', - '400': 'ef5350', - '100': 'ffcdd2', - '800': 'c62828', - 'A200': 'ff5252', - '500': 'f44336' - }, - - 'Teal': { - '200': '80cbc4', - '900': '004D40', - '600': '00897B', - 'A100': 'a7ffeb', - '300': '4db6ac', - 'A400': '1de9b6', - '700': '00796B', - '50': 'e0f2f1', - 'A700': '00BFA5', - '400': '26a69a', - '100': 'b2dfdb', - '800': '00695C', - 'A200': '64ffda', - '500': '009688' - }, - - 'Orange': { - '200': 'ffcc80', - '900': 'E65100', - '600': 'FB8C00', - 'A100': 'ffd180', - '300': 'ffb74d', - 'A400': 'FF9100', - '700': 'F57C00', - '50': 'fff3e0', - 'A700': 'FF6D00', - '400': 'ffa726', - '100': 'ffe0b2', - '800': 'EF6C00', - 'A200': 'ffab40', - '500': 'FF9800' - }, - - 'Cyan': { - '200': '80deea', - '900': '006064', - '600': '00ACC1', - 'A100': '84ffff', - '300': '4dd0e1', - 'A400': '00E5FF', - '700': '0097A7', - '50': 'e0f7fa', - 'A700': '00B8D4', - '400': '26c6da', - '100': 'b2ebf2', - '800': '00838F', - 'A200': '18ffff', - '500': '00BCD4' - }, - - 'Amber': { - '200': 'ffe082', - '900': 'FF6F00', - '600': 'FFB300', - 'A100': 'ffe57f', - '300': 'ffd54f', - 'A400': 'FFC400', - '700': 'FFA000', - '50': 'fff8e1', - 'A700': 'FFAB00', - '400': 'ffca28', - '100': 'ffecb3', - '800': 'FF8F00', - 'A200': 'ffd740', - '500': 'FFC107' - }, - - 'DeepPurple': { - '200': 'b39ddb', - '900': '311b92', - '600': '5e35b1', - 'A100': 'b388ff', - '300': '9575cd', - 'A400': '651fff', - '700': '512da8', - '50': 'ede7f6', - 'A700': '6200EA', - '400': '7e57c2', - '100': 'd1c4e9', - '800': '4527a0', - 'A200': '7c4dff', - '500': '673ab7' - }, - - 'Lime': { - '200': 'e6ee9c', - '900': '827717', - '600': 'c0ca33', - 'A100': 'f4ff81', - '300': 'dce775', - 'A400': 'C6FF00', - '700': 'afb42b', - '50': 'f9fbe7', - 'A700': 'AEEA00', - '400': 'd4e157', - '100': 'f0f4c3', - '800': '9e9d24', - 'A200': 'eeff41', - '500': 'cddc39' - }, - - 'Light': { - 'StatusBar': 'E0E0E0', - 'AppBar': 'F5F5F5', - 'Background': 'FAFAFA', - 'CardsDialogs': 'FFFFFF', - 'FlatButtonDown': 'cccccc' - }, - - 'Dark': { - 'StatusBar': '000000', - 'AppBar': '212121', - 'Background': '303030', - 'CardsDialogs': '424242', - 'FlatButtonDown': '999999' - } -} - -light_colors = { - 'Pink': ['50' '100', '200', 'A100'], - 'Blue': ['50' '100', '200', '300', '400', 'A100'], - 'Indigo': ['50' '100', '200', 'A100'], - 'BlueGrey': ['50' '100', '200', '300'], - 'Brown': ['50' '100', '200'], - 'LightBlue': ['50' '100', '200', '300', '400', '500', 'A100', 'A200', - 'A400'], - 'Purple': ['50' '100', '200', 'A100'], - 'Grey': ['50' '100', '200', '300', '400', '500'], - 'Yellow': ['50' '100', '200', '300', '400', '500', '600', '700', '800', - '900', 'A100', 'A200', 'A400', 'A700'], - 'LightGreen': ['50' '100', '200', '300', '400', '500', '600', 'A100', - 'A200', 'A400', 'A700'], - 'DeepOrange': ['50' '100', '200', '300', '400', 'A100', 'A200'], - 'Green': ['50' '100', '200', '300', '400', '500', 'A100', 'A200', 'A400', - 'A700'], - 'Red': ['50' '100', '200', '300', 'A100'], - 'Teal': ['50' '100', '200', '300', '400', 'A100', 'A200', 'A400', 'A700'], - 'Orange': ['50' '100', '200', '300', '400', '500', '600', '700', 'A100', - 'A200', 'A400', 'A700'], - 'Cyan': ['50' '100', '200', '300', '400', '500', '600', 'A100', 'A200', - 'A400', 'A700'], - 'Amber': ['50' '100', '200', '300', '400', '500', '600', '700', '800', - '900', 'A100', 'A200', 'A400', 'A700'], - 'DeepPurple': ['50' '100', '200', 'A100'], - 'Lime': ['50' '100', '200', '300', '400', '500', '600', '700', '800', - 'A100', 'A200', 'A400', 'A700'], - 'Dark': [], - 'Light': ['White', 'MainBackground', 'DialogBackground'] -} diff --git a/src/kivymd/date_picker.py b/src/kivymd/date_picker.py deleted file mode 100644 index 5194298e..00000000 --- a/src/kivymd/date_picker.py +++ /dev/null @@ -1,325 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.lang import Builder -from kivy.uix.modalview import ModalView -from kivymd.label import MDLabel -from kivymd.theming import ThemableBehavior -from kivy.uix.floatlayout import FloatLayout -from kivymd.elevationbehavior import ElevationBehavior -import calendar -from datetime import date -import datetime -from kivy.properties import StringProperty, NumericProperty, ObjectProperty, \ - BooleanProperty -from kivy.uix.anchorlayout import AnchorLayout -from kivy.uix.behaviors import ButtonBehavior -from kivymd.ripplebehavior import CircularRippleBehavior -from kivy.clock import Clock -from kivy.core.window import Window - -Builder.load_string(""" -#:import calendar calendar - - cal_layout: cal_layout - - size_hint: (None, None) - size: [dp(328), dp(484)] if self.theme_cls.device_orientation == 'portrait'\ - else [dp(512), dp(304)] - pos_hint: {'center_x': .5, 'center_y': .5} - canvas: - Color: - rgb: app.theme_cls.primary_color - Rectangle: - size: [dp(328), dp(96)] if self.theme_cls.device_orientation == 'portrait'\ - else [dp(168), dp(304)] - pos: [root.pos[0], root.pos[1] + root.height-dp(96)] if self.theme_cls.device_orientation == 'portrait'\ - else [root.pos[0], root.pos[1] + root.height-dp(304)] - Color: - rgb: app.theme_cls.bg_normal - Rectangle: - size: [dp(328), dp(484)-dp(96)] if self.theme_cls.device_orientation == 'portrait'\ - else [dp(344), dp(304)] - pos: [root.pos[0], root.pos[1] + root.height-dp(96)-(dp(484)-dp(96))]\ - if self.theme_cls.device_orientation == 'portrait' else [root.pos[0]+dp(168), root.pos[1]] #+dp(334) - MDLabel: - id: label_full_date - font_style: 'Display1' - text_color: 1, 1, 1, 1 - theme_text_color: 'Custom' - size_hint: (None, None) - size: [root.width, dp(30)] if root.theme_cls.device_orientation == 'portrait'\ - else [dp(168), dp(30)] - pos: [root.pos[0]+dp(23), root.pos[1] + root.height - dp(74)] \ - if root.theme_cls.device_orientation == 'portrait' \ - else [root.pos[0]+dp(3), root.pos[1] + dp(214)] - line_height: 0.84 - valign: 'middle' - text_size: [root.width, None] if root.theme_cls.device_orientation == 'portrait'\ - else [dp(149), None] - bold: True - text: root.fmt_lbl_date(root.sel_year, root.sel_month, root.sel_day, root.theme_cls.device_orientation) - MDLabel: - id: label_year - font_style: 'Subhead' - text_color: 1, 1, 1, 1 - theme_text_color: 'Custom' - size_hint: (None, None) - size: root.width, dp(30) - pos: (root.pos[0]+dp(23), root.pos[1]+root.height-dp(40)) if root.theme_cls.device_orientation == 'portrait'\ - else (root.pos[0]+dp(16), root.pos[1]+root.height-dp(41)) - valign: 'middle' - text: str(root.sel_year) - GridLayout: - id: cal_layout - cols: 7 - size: (dp(44*7), dp(40*7)) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(46*7), dp(32*7)) - col_default_width: dp(42) if root.theme_cls.device_orientation == 'portrait'\ - else dp(39) - size_hint: (None, None) - padding: (dp(2), 0) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(7), 0) - spacing: (dp(2), 0) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(7), 0) - pos: (root.pos[0]+dp(10), root.pos[1]+dp(60)) if root.theme_cls.device_orientation == 'portrait'\ - else (root.pos[0]+dp(168)+dp(8), root.pos[1]+dp(48)) - MDLabel: - id: label_month_selector - font_style: 'Body2' - text: calendar.month_name[root.month].capitalize() + ' ' + str(root.year) - size_hint: (None, None) - size: root.width, dp(30) - pos: root.pos - theme_text_color: 'Primary' - pos_hint: {'center_x': 0.5, 'center_y': 0.75} if self.theme_cls.device_orientation == 'portrait'\ - else {'center_x': 0.67, 'center_y': 0.915} - valign: "middle" - halign: "center" - MDIconButton: - icon: 'chevron-left' - theme_text_color: 'Secondary' - pos_hint: {'center_x': 0.09, 'center_y': 0.745} if root.theme_cls.device_orientation == 'portrait'\ - else {'center_x': 0.39, 'center_y': 0.925} - on_release: root.change_month('prev') - MDIconButton: - icon: 'chevron-right' - theme_text_color: 'Secondary' - pos_hint: {'center_x': 0.92, 'center_y': 0.745} if root.theme_cls.device_orientation == 'portrait'\ - else {'center_x': 0.94, 'center_y': 0.925} - on_release: root.change_month('next') - MDFlatButton: - pos: root.pos[0]+root.size[0]-dp(72)*2, root.pos[1] + dp(7) - text: "Cancel" - on_release: root.dismiss() - MDFlatButton: - pos: root.pos[0]+root.size[0]-dp(72), root.pos[1] + dp(7) - text: "OK" - on_release: root.ok_click() - - - size_hint: None, None - size: (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(32), dp(32)) - MDLabel: - font_style: 'Caption' - theme_text_color: 'Custom' if root.is_today and not root.is_selected else 'Primary' - text_color: root.theme_cls.primary_color - opposite_colors: root.is_selected if root.owner.sel_month == root.owner.month \ - and root.owner.sel_year == root.owner.year and str(self.text) == str(root.owner.sel_day) else False - size_hint_x: None - valign: 'middle' - halign: 'center' - text: root.text - - - font_style: 'Caption' - theme_text_color: 'Secondary' - size: (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(32), dp(32)) - size_hint: None, None - text_size: self.size - valign: 'middle' if root.theme_cls.device_orientation == 'portrait' else 'bottom' - halign: 'center' - - - size: (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(32), dp(32)) - size_hint: (None, None) - canvas: - Color: - rgba: self.theme_cls.primary_color if self.shown else [0, 0, 0, 0] - Ellipse: - size: (dp(40), dp(40)) if root.theme_cls.device_orientation == 'portrait'\ - else (dp(32), dp(32)) - pos: self.pos if root.theme_cls.device_orientation == 'portrait'\ - else [self.pos[0] + dp(3), self.pos[1]] -""") - - -class DaySelector(ThemableBehavior, AnchorLayout): - shown = BooleanProperty(False) - - def __init__(self, parent): - super(DaySelector, self).__init__() - self.parent_class = parent - self.parent_class.add_widget(self, index=7) - self.selected_widget = None - Window.bind(on_resize=self.move_resize) - - def update(self): - parent = self.parent_class - if parent.sel_month == parent.month and parent.sel_year == parent.year: - self.shown = True - else: - self.shown = False - - def set_widget(self, widget): - self.selected_widget = widget - self.pos = widget.pos - self.move_resize(do_again=True) - self.update() - - def move_resize(self, window=None, width=None, height=None, do_again=True): - self.pos = self.selected_widget.pos - if do_again: - Clock.schedule_once(lambda x: self.move_resize(do_again=False), 0.01) - - -class DayButton(ThemableBehavior, CircularRippleBehavior, ButtonBehavior, - AnchorLayout): - text = StringProperty() - owner = ObjectProperty() - is_today = BooleanProperty(False) - is_selected = BooleanProperty(False) - - def on_release(self): - self.owner.set_selected_widget(self) - - -class WeekdayLabel(MDLabel): - pass - - -class MDDatePicker(FloatLayout, ThemableBehavior, ElevationBehavior, - ModalView): - _sel_day_widget = ObjectProperty() - cal_list = None - cal_layout = ObjectProperty() - sel_year = NumericProperty() - sel_month = NumericProperty() - sel_day = NumericProperty() - day = NumericProperty() - month = NumericProperty() - year = NumericProperty() - today = date.today() - callback = ObjectProperty() - - class SetDateError(Exception): - pass - - def __init__(self, callback, year=None, month=None, day=None, - firstweekday=0, - **kwargs): - self.callback = callback - self.cal = calendar.Calendar(firstweekday) - self.sel_year = year if year else self.today.year - self.sel_month = month if month else self.today.month - self.sel_day = day if day else self.today.day - self.month = self.sel_month - self.year = self.sel_year - self.day = self.sel_day - super(MDDatePicker, self).__init__(**kwargs) - self.selector = DaySelector(parent=self) - self.generate_cal_widgets() - self.update_cal_matrix(self.sel_year, self.sel_month) - self.set_month_day(self.sel_day) - self.selector.update() - - def ok_click(self): - self.callback(date(self.sel_year, self.sel_month, self.sel_day)) - self.dismiss() - - def fmt_lbl_date(self, year, month, day, orientation): - d = datetime.date(int(year), int(month), int(day)) - separator = '\n' if orientation == 'landscape' else ' ' - return d.strftime('%a,').capitalize() + separator + d.strftime( - '%b').capitalize() + ' ' + str(day).lstrip('0') - - def set_date(self, year, month, day): - try: - date(year, month, day) - except Exception as e: - print(e) - if str(e) == "day is out of range for month": - raise self.SetDateError(" Day %s day is out of range for month %s" % (day, month)) - elif str(e) == "month must be in 1..12": - raise self.SetDateError("Month must be between 1 and 12, got %s" % month) - elif str(e) == "year is out of range": - raise self.SetDateError("Year must be between %s and %s, got %s" % - (datetime.MINYEAR, datetime.MAXYEAR, year)) - else: - self.sel_year = year - self.sel_month = month - self.sel_day = day - self.month = self.sel_month - self.year = self.sel_year - self.day = self.sel_day - self.update_cal_matrix(self.sel_year, self.sel_month) - self.set_month_day(self.sel_day) - self.selector.update() - - def set_selected_widget(self, widget): - if self._sel_day_widget: - self._sel_day_widget.is_selected = False - widget.is_selected = True - self.sel_month = int(self.month) - self.sel_year = int(self.year) - self.sel_day = int(widget.text) - self._sel_day_widget = widget - self.selector.set_widget(widget) - - def set_month_day(self, day): - for idx in range(len(self.cal_list)): - if str(day) == str(self.cal_list[idx].text): - self._sel_day_widget = self.cal_list[idx] - self.sel_day = int(self.cal_list[idx].text) - if self._sel_day_widget: - self._sel_day_widget.is_selected = False - self._sel_day_widget = self.cal_list[idx] - self.cal_list[idx].is_selected = True - self.selector.set_widget(self.cal_list[idx]) - - def update_cal_matrix(self, year, month): - try: - dates = [x for x in self.cal.itermonthdates(year, month)] - except ValueError as e: - if str(e) == "year is out of range": - pass - else: - self.year = year - self.month = month - for idx in range(len(self.cal_list)): - if idx >= len(dates) or dates[idx].month != month: - self.cal_list[idx].disabled = True - self.cal_list[idx].text = '' - else: - self.cal_list[idx].disabled = False - self.cal_list[idx].text = str(dates[idx].day) - self.cal_list[idx].is_today = dates[idx] == self.today - self.selector.update() - - def generate_cal_widgets(self): - cal_list = [] - for i in calendar.day_abbr: - self.cal_layout.add_widget(WeekdayLabel(text=i[0].upper())) - for i in range(6 * 7): # 6 weeks, 7 days a week - db = DayButton(owner=self) - cal_list.append(db) - self.cal_layout.add_widget(db) - self.cal_list = cal_list - - def change_month(self, operation): - op = 1 if operation is 'next' else -1 - sl, sy = self.month, self.year - m = 12 if sl + op == 0 else 1 if sl + op == 13 else sl + op - y = sy - 1 if sl + op == 0 else sy + 1 if sl + op == 13 else sy - self.update_cal_matrix(y, m) diff --git a/src/kivymd/dialog.py b/src/kivymd/dialog.py deleted file mode 100644 index cb6b7601..00000000 --- a/src/kivymd/dialog.py +++ /dev/null @@ -1,176 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.properties import StringProperty, ObjectProperty, ListProperty -from kivy.metrics import dp -from kivy.uix.modalview import ModalView -from kivy.animation import Animation -from kivymd.theming import ThemableBehavior -from kivymd.elevationbehavior import ElevationBehavior -from kivymd.button import MDFlatButton - -Builder.load_string(''' -: - canvas: - Color: - rgba: self.theme_cls.bg_light - Rectangle: - size: self.size - pos: self.pos - - _container: container - _action_area: action_area - elevation: 12 - GridLayout: - cols: 1 - - GridLayout: - cols: 1 - padding: dp(24), dp(24), dp(24), 0 - spacing: dp(20) - MDLabel: - text: root.title - font_style: 'Title' - theme_text_color: 'Primary' - halign: 'left' - valign: 'middle' - size_hint_y: None - text_size: self.width, None - height: self.texture_size[1] - - BoxLayout: - id: container - - AnchorLayout: - anchor_x: 'right' - anchor_y: 'center' - size_hint: 1, None - height: dp(48) - padding: dp(8), dp(8) - spacing: dp(4) - - GridLayout: - id: action_area - rows: 1 - size_hint: None, None if len(root._action_buttons) > 0 else 1 - height: dp(36) if len(root._action_buttons) > 0 else 0 - width: self.minimum_width -''') - - -class MDDialog(ThemableBehavior, ElevationBehavior, ModalView): - title = StringProperty('') - - content = ObjectProperty(None) - - background_color = ListProperty([0, 0, 0, .2]) - - _container = ObjectProperty() - _action_buttons = ListProperty([]) - _action_area = ObjectProperty() - - def __init__(self, **kwargs): - super(MDDialog, self).__init__(**kwargs) - self.bind(_action_buttons=self._update_action_buttons, - auto_dismiss=lambda *x: setattr(self.shadow, 'on_release', - self.shadow.dismiss if self.auto_dismiss else None)) - - def add_action_button(self, text, action=None): - """Add an :class:`FlatButton` to the right of the action area. - - :param icon: Unicode character for the icon - :type icon: str or None - :param action: Function set to trigger when on_release fires - :type action: function or None - """ - button = MDFlatButton(text=text, - size_hint=(None, None), - height=dp(36)) - if action: - button.bind(on_release=action) - button.text_color = self.theme_cls.primary_color - button.background_color = self.theme_cls.bg_light - self._action_buttons.append(button) - - def add_widget(self, widget): - if self._container: - if self.content: - raise PopupException( - 'Popup can have only one widget as content') - self.content = widget - else: - super(MDDialog, self).add_widget(widget) - - def open(self, *largs): - '''Show the view window from the :attr:`attach_to` widget. If set, it - will attach to the nearest window. If the widget is not attached to any - window, the view will attach to the global - :class:`~kivy.core.window.Window`. - ''' - if self._window is not None: - Logger.warning('ModalView: you can only open once.') - return self - # search window - self._window = self._search_window() - if not self._window: - Logger.warning('ModalView: cannot open view, no window found.') - return self - self._window.add_widget(self) - self._window.bind(on_resize=self._align_center, - on_keyboard=self._handle_keyboard) - self.center = self._window.center - self.bind(size=self._align_center) - a = Animation(_anim_alpha=1., d=self._anim_duration) - a.bind(on_complete=lambda *x: self.dispatch('on_open')) - a.start(self) - return self - - def dismiss(self, *largs, **kwargs): - '''Close the view if it is open. If you really want to close the - view, whatever the on_dismiss event returns, you can use the *force* - argument: - :: - - view = ModalView(...) - view.dismiss(force=True) - - When the view is dismissed, it will be faded out before being - removed from the parent. If you don't want animation, use:: - - view.dismiss(animation=False) - - ''' - if self._window is None: - return self - if self.dispatch('on_dismiss') is True: - if kwargs.get('force', False) is not True: - return self - if kwargs.get('animation', True): - Animation(_anim_alpha=0., d=self._anim_duration).start(self) - else: - self._anim_alpha = 0 - self._real_remove_widget() - return self - - def on_content(self, instance, value): - if self._container: - self._container.clear_widgets() - self._container.add_widget(value) - - def on__container(self, instance, value): - if value is None or self.content is None: - return - self._container.clear_widgets() - self._container.add_widget(self.content) - - def on_touch_down(self, touch): - if self.disabled and self.collide_point(*touch.pos): - return True - return super(MDDialog, self).on_touch_down(touch) - - def _update_action_buttons(self, *args): - self._action_area.clear_widgets() - for btn in self._action_buttons: - btn.ids._label.texture_update() - btn.width = btn.ids._label.texture_size[0] + dp(16) - self._action_area.add_widget(btn) diff --git a/src/kivymd/elevationbehavior.py b/src/kivymd/elevationbehavior.py deleted file mode 100644 index 19d7985d..00000000 --- a/src/kivymd/elevationbehavior.py +++ /dev/null @@ -1,187 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.app import App -from kivy.lang import Builder -from kivy.properties import (ListProperty, ObjectProperty, NumericProperty) -from kivy.properties import AliasProperty -from kivy.metrics import dp - -Builder.load_string(''' - - canvas.before: - Color: - a: self._soft_shadow_a - Rectangle: - texture: self._soft_shadow_texture - size: self._soft_shadow_size - pos: self._soft_shadow_pos - Color: - a: self._hard_shadow_a - Rectangle: - texture: self._hard_shadow_texture - size: self._hard_shadow_size - pos: self._hard_shadow_pos - Color: - a: 1 - - - canvas.before: - Color: - a: self._soft_shadow_a - Rectangle: - texture: self._soft_shadow_texture - size: self._soft_shadow_size - pos: self._soft_shadow_pos - Color: - a: self._hard_shadow_a - Rectangle: - texture: self._hard_shadow_texture - size: self._hard_shadow_size - pos: self._hard_shadow_pos - Color: - a: 1 -''') - - -class ElevationBehavior(object): - _elevation = NumericProperty(1) - - def _get_elevation(self): - return self._elevation - - def _set_elevation(self, elevation): - try: - self._elevation = elevation - except: - self._elevation = 1 - - elevation = AliasProperty(_get_elevation, _set_elevation, - bind=('_elevation',)) - - _soft_shadow_texture = ObjectProperty() - _soft_shadow_size = ListProperty([0, 0]) - _soft_shadow_pos = ListProperty([0, 0]) - _soft_shadow_a = NumericProperty(0) - _hard_shadow_texture = ObjectProperty() - _hard_shadow_size = ListProperty([0, 0]) - _hard_shadow_pos = ListProperty([0, 0]) - _hard_shadow_a = NumericProperty(0) - - def __init__(self, **kwargs): - super(ElevationBehavior, self).__init__(**kwargs) - self.bind(elevation=self._update_shadow, - pos=self._update_shadow, - size=self._update_shadow) - - def _update_shadow(self, *args): - if self.elevation > 0: - ratio = self.width / (self.height if self.height != 0 else 1) - if ratio > -2 and ratio < 2: - self._shadow = App.get_running_app().theme_cls.quad_shadow - width = soft_width = self.width * 1.9 - height = soft_height = self.height * 1.9 - elif ratio <= -2: - self._shadow = App.get_running_app().theme_cls.rec_st_shadow - ratio = abs(ratio) - if ratio > 5: - ratio = ratio * 22 - else: - ratio = ratio * 11.5 - - width = soft_width = self.width * 1.9 - height = self.height + dp(ratio) - soft_height = self.height + dp(ratio) + dp(self.elevation) * .5 - else: - self._shadow = App.get_running_app().theme_cls.quad_shadow - width = soft_width = self.width * 1.8 - height = soft_height = self.height * 1.8 - # self._shadow = App.get_running_app().theme_cls.rec_shadow - # ratio = abs(ratio) - # if ratio > 5: - # ratio = ratio * 22 - # else: - # ratio = ratio * 11.5 - # - # width = self.width + dp(ratio) - # soft_width = self.width + dp(ratio) + dp(self.elevation) * .9 - # height = soft_height = self.height * 1.9 - - x = self.center_x - width / 2 - soft_x = self.center_x - soft_width / 2 - self._soft_shadow_size = (soft_width, soft_height) - self._hard_shadow_size = (width, height) - - y = self.center_y - soft_height / 2 - dp( - .1 * 1.5 ** self.elevation) - self._soft_shadow_pos = (soft_x, y) - self._soft_shadow_a = 0.1 * 1.1 ** self.elevation - self._soft_shadow_texture = self._shadow.textures[ - str(int(round(self.elevation - 1)))] - - y = self.center_y - height / 2 - dp(.5 * 1.18 ** self.elevation) - self._hard_shadow_pos = (x, y) - self._hard_shadow_a = .4 * .9 ** self.elevation - self._hard_shadow_texture = self._shadow.textures[ - str(int(round(self.elevation)))] - - else: - self._soft_shadow_a = 0 - self._hard_shadow_a = 0 - - -class RoundElevationBehavior(object): - _elevation = NumericProperty(1) - - def _get_elevation(self): - return self._elevation - - def _set_elevation(self, elevation): - try: - self._elevation = elevation - except: - self._elevation = 1 - - elevation = AliasProperty(_get_elevation, _set_elevation, - bind=('_elevation',)) - - _soft_shadow_texture = ObjectProperty() - _soft_shadow_size = ListProperty([0, 0]) - _soft_shadow_pos = ListProperty([0, 0]) - _soft_shadow_a = NumericProperty(0) - _hard_shadow_texture = ObjectProperty() - _hard_shadow_size = ListProperty([0, 0]) - _hard_shadow_pos = ListProperty([0, 0]) - _hard_shadow_a = NumericProperty(0) - - def __init__(self, **kwargs): - super(RoundElevationBehavior, self).__init__(**kwargs) - self._shadow = App.get_running_app().theme_cls.round_shadow - self.bind(elevation=self._update_shadow, - pos=self._update_shadow, - size=self._update_shadow) - - def _update_shadow(self, *args): - if self.elevation > 0: - width = self.width * 2 - height = self.height * 2 - - x = self.center_x - width / 2 - self._soft_shadow_size = (width, height) - - self._hard_shadow_size = (width, height) - - y = self.center_y - height / 2 - dp(.1 * 1.5 ** self.elevation) - self._soft_shadow_pos = (x, y) - self._soft_shadow_a = 0.1 * 1.1 ** self.elevation - self._soft_shadow_texture = self._shadow.textures[ - str(int(round(self.elevation)))] - - y = self.center_y - height / 2 - dp(.5 * 1.18 ** self.elevation) - self._hard_shadow_pos = (x, y) - self._hard_shadow_a = .4 * .9 ** self.elevation - self._hard_shadow_texture = self._shadow.textures[ - str(int(round(self.elevation - 1)))] - - else: - self._soft_shadow_a = 0 - self._hard_shadow_a = 0 diff --git a/src/kivymd/fonts/Material-Design-Iconic-Font.ttf b/src/kivymd/fonts/Material-Design-Iconic-Font.ttf deleted file mode 100644 index 5d489fdd..00000000 Binary files a/src/kivymd/fonts/Material-Design-Iconic-Font.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-Bold.ttf b/src/kivymd/fonts/Roboto-Bold.ttf deleted file mode 100644 index 91ec2122..00000000 Binary files a/src/kivymd/fonts/Roboto-Bold.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-Italic.ttf b/src/kivymd/fonts/Roboto-Italic.ttf deleted file mode 100644 index 2041cbc0..00000000 Binary files a/src/kivymd/fonts/Roboto-Italic.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-Light.ttf b/src/kivymd/fonts/Roboto-Light.ttf deleted file mode 100644 index 664e1b2f..00000000 Binary files a/src/kivymd/fonts/Roboto-Light.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-LightItalic.ttf b/src/kivymd/fonts/Roboto-LightItalic.ttf deleted file mode 100644 index a85444f2..00000000 Binary files a/src/kivymd/fonts/Roboto-LightItalic.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-Medium.ttf b/src/kivymd/fonts/Roboto-Medium.ttf deleted file mode 100644 index aa00de0e..00000000 Binary files a/src/kivymd/fonts/Roboto-Medium.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-MediumItalic.ttf b/src/kivymd/fonts/Roboto-MediumItalic.ttf deleted file mode 100644 index b8282055..00000000 Binary files a/src/kivymd/fonts/Roboto-MediumItalic.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-Regular.ttf b/src/kivymd/fonts/Roboto-Regular.ttf deleted file mode 100644 index 3e6e2e76..00000000 Binary files a/src/kivymd/fonts/Roboto-Regular.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-Thin.ttf b/src/kivymd/fonts/Roboto-Thin.ttf deleted file mode 100644 index d262d144..00000000 Binary files a/src/kivymd/fonts/Roboto-Thin.ttf and /dev/null differ diff --git a/src/kivymd/fonts/Roboto-ThinItalic.ttf b/src/kivymd/fonts/Roboto-ThinItalic.ttf deleted file mode 100644 index b79cb26d..00000000 Binary files a/src/kivymd/fonts/Roboto-ThinItalic.ttf and /dev/null differ diff --git a/src/kivymd/grid.py b/src/kivymd/grid.py deleted file mode 100644 index db310193..00000000 --- a/src/kivymd/grid.py +++ /dev/null @@ -1,168 +0,0 @@ -# coding=utf-8 -from kivy.lang import Builder -from kivy.properties import StringProperty, BooleanProperty, ObjectProperty, \ - NumericProperty, ListProperty, OptionProperty -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.floatlayout import FloatLayout -from kivymd.ripplebehavior import RectangularRippleBehavior -from kivymd.theming import ThemableBehavior - -Builder.load_string(""" - - _img_widget: img - _img_overlay: img_overlay - _box_overlay: box - AsyncImage: - id: img - allow_stretch: root.allow_stretch - anim_delay: root.anim_delay - anim_loop: root.anim_loop - color: root.img_color - keep_ratio: root.keep_ratio - mipmap: root.mipmap - source: root.source - size_hint_y: 1 if root.overlap else None - x: root.x - y: root.y if root.overlap or root.box_position == 'header' else box.top - BoxLayout: - id: img_overlay - size_hint: img.size_hint - size: img.size - pos: img.pos - BoxLayout: - canvas: - Color: - rgba: root.box_color - Rectangle: - pos: self.pos - size: self.size - id: box - size_hint_y: None - height: dp(68) if root.lines == 2 else dp(48) - x: root.x - y: root.y if root.box_position == 'footer' else root.y + root.height - self.height - - - _img_widget: img - _img_overlay: img_overlay - _box_overlay: box - _box_label: boxlabel - AsyncImage: - id: img - allow_stretch: root.allow_stretch - anim_delay: root.anim_delay - anim_loop: root.anim_loop - color: root.img_color - keep_ratio: root.keep_ratio - mipmap: root.mipmap - source: root.source - size_hint_y: 1 if root.overlap else None - x: root.x - y: root.y if root.overlap or root.box_position == 'header' else box.top - BoxLayout: - id: img_overlay - size_hint: img.size_hint - size: img.size - pos: img.pos - BoxLayout: - canvas: - Color: - rgba: root.box_color - Rectangle: - pos: self.pos - size: self.size - id: box - size_hint_y: None - height: dp(68) if root.lines == 2 else dp(48) - x: root.x - y: root.y if root.box_position == 'footer' else root.y + root.height - self.height - MDLabel: - id: boxlabel - font_style: "Caption" - halign: "center" - text: root.text -""") - - -class Tile(ThemableBehavior, RectangularRippleBehavior, ButtonBehavior, - BoxLayout): - """A simple tile. It does nothing special, just inherits the right behaviors - to work as a building block. - """ - pass - - -class SmartTile(ThemableBehavior, RectangularRippleBehavior, ButtonBehavior, - FloatLayout): - """A tile for more complex needs. - - Includes an image, a container to place overlays and a box that can act - as a header or a footer, as described in the Material Design specs. - """ - - box_color = ListProperty([0, 0, 0, 0.5]) - """Sets the color and opacity for the information box.""" - - box_position = OptionProperty('footer', options=['footer', 'header']) - """Determines wether the information box acts as a header or footer to the - image. - """ - - lines = OptionProperty(1, options=[1, 2]) - """Number of lines in the header/footer. - - As per Material Design specs, only 1 and 2 are valid values. - """ - - overlap = BooleanProperty(True) - """Determines if the header/footer overlaps on top of the image or not""" - - # Img properties - allow_stretch = BooleanProperty(True) - anim_delay = NumericProperty(0.25) - anim_loop = NumericProperty(0) - img_color = ListProperty([1, 1, 1, 1]) - keep_ratio = BooleanProperty(False) - mipmap = BooleanProperty(False) - source = StringProperty() - - _img_widget = ObjectProperty() - _img_overlay = ObjectProperty() - _box_overlay = ObjectProperty() - _box_label = ObjectProperty() - - def reload(self): - self._img_widget.reload() - - def add_widget(self, widget, index=0): - if issubclass(widget.__class__, IOverlay): - self._img_overlay.add_widget(widget, index) - elif issubclass(widget.__class__, IBoxOverlay): - self._box_overlay.add_widget(widget, index) - else: - super(SmartTile, self).add_widget(widget, index) - - -class SmartTileWithLabel(SmartTile): - _box_label = ObjectProperty() - - # MDLabel properties - font_style = StringProperty("Caption") - theme_text_color = StringProperty("") - text = StringProperty("") - """Determines the text for the box footer/header""" - - -class IBoxOverlay(): - """An interface to specify widgets that belong to to the image overlay - in the :class:`SmartTile` widget when added as a child. - """ - pass - - -class IOverlay(): - """An interface to specify widgets that belong to to the image overlay - in the :class:`SmartTile` widget when added as a child. - """ - pass diff --git a/src/kivymd/icon_definitions.py b/src/kivymd/icon_definitions.py deleted file mode 100644 index 5b717356..00000000 --- a/src/kivymd/icon_definitions.py +++ /dev/null @@ -1,1569 +0,0 @@ -# -*- coding: utf-8 -*- - -# Thanks to Sergey Kupletsky (github.com/zavoloklom) for its Material Design -# Iconic Font, which provides KivyMD's icons. - -# GALLERY HERE: -# https://zavoloklom.github.io/material-design-iconic-font/icons.html - -# LAST UPDATED: version 2.2.0 of Material Design Iconic Font - -md_icons = { - '3d-rotation': u'', - - 'airplane-off': u'', - - 'address': u'', - - 'airplane': u'', - - 'album': u'', - - 'archive': u'', - - 'assignment-account': u'', - - 'assignment-alert': u'', - - 'assignment-check': u'', - - 'assignment-o': u'', - - 'assignment-return': u'', - - 'assignment-returned': u'', - - 'assignment': u'', - - 'attachment-alt': u'', - - 'attachment': u'', - - 'audio': u'', - - 'badge-check': u'', - - 'balance-wallet': u'', - - 'balance': u'', - - 'battery-alert': u'', - - 'battery-flash': u'', - - 'battery-unknown': u'', - - 'battery': u'', - - 'bike': u'', - - 'block-alt': u'', - - 'block': u'', - - 'boat': u'', - - 'book-image': u'', - - 'book': u'', - - 'bookmark-outline': u'', - - 'bookmark': u'', - - 'brush': u'', - - 'bug': u'', - - 'bus': u'', - - 'cake': u'', - - 'car-taxi': u'', - - 'car-wash': u'', - - 'car': u'', - - 'card-giftcard': u'', - - 'card-membership': u'', - - 'card-travel': u'', - - 'card': u'', - - 'case-check': u'', - - 'case-download': u'', - - 'case-play': u'', - - 'case': u'', - - 'cast-connected': u'', - - 'cast': u'', - - 'chart-donut': u'', - - 'chart': u'', - - 'city-alt': u'', - - 'city': u'', - - 'close-circle-o': u'', - - 'close-circle': u'', - - 'close': u'', - - 'cocktail': u'', - - 'code-setting': u'', - - 'code-smartphone': u'', - - 'code': u'', - - 'coffee': u'', - - 'collection-bookmark': u'', - - 'collection-case-play': u'', - - 'collection-folder-image': u'', - - 'collection-image-o': u'', - - 'collection-image': u'', - - 'collection-item-1': u'', - - 'collection-item-2': u'', - - 'collection-item-3': u'', - - 'collection-item-4': u'', - - 'collection-item-5': u'', - - 'collection-item-6': u'', - - 'collection-item-7': u'', - - 'collection-item-8': u'', - - 'collection-item-9-plus': u'', - - 'collection-item-9': u'', - - 'collection-item': u'', - - 'collection-music': u'', - - 'collection-pdf': u'', - - 'collection-plus': u'', - - 'collection-speaker': u'', - - 'collection-text': u'', - - 'collection-video': u'', - - 'compass': u'', - - 'cutlery': u'', - - 'delete': u'', - - 'dialpad': u'', - - 'dns': u'', - - 'drink': u'', - - 'edit': u'', - - 'email-open': u'', - - 'email': u'', - - 'eye-off': u'', - - 'eye': u'', - - 'eyedropper': u'', - - 'favorite-outline': u'', - - 'favorite': u'', - - 'filter-list': u'', - - 'fire': u'', - - 'flag': u'', - - 'flare': u'', - - 'flash-auto': u'', - - 'flash-off': u'', - - 'flash': u'', - - 'flip': u'', - - 'flower-alt': u'', - - 'flower': u'', - - 'font': u'', - - 'fullscreen-alt': u'', - - 'fullscreen-exit': u'', - - 'fullscreen': u'', - - 'functions': u'', - - 'gas-station': u'', - - 'gesture': u'', - - 'globe-alt': u'', - - 'globe-lock': u'', - - 'globe': u'', - - 'graduation-cap': u'', - - 'group': u'', - - 'home': u'', - - 'hospital-alt': u'', - - 'hospital': u'', - - 'hotel': u'', - - 'hourglass-alt': u'', - - 'hourglass-outline': u'', - - 'hourglass': u'', - - 'http': u'', - - 'image-alt': u'', - - 'image-o': u'', - - 'image': u'', - - 'inbox': u'', - - 'invert-colors-off': u'', - - 'invert-colors': u'', - - 'key': u'', - - 'label-alt-outline': u'', - - 'label-alt': u'', - - 'label-heart': u'', - - 'label': u'', - - 'labels': u'', - - 'lamp': u'', - - 'landscape': u'', - - 'layers-off': u'', - - 'layers': u'', - - 'library': u'', - - 'link': u'', - - 'lock-open': u'', - - 'lock-outline': u'', - - 'lock': u'', - - 'mail-reply-all': u'', - - 'mail-reply': u'', - - 'mail-send': u'', - - 'mall': u'', - - 'map': u'', - - 'menu': u'', - - 'money-box': u'', - - 'money-off': u'', - - 'money': u'', - - 'more-vert': u'', - - 'more': u'', - - 'movie-alt': u'', - - 'movie': u'', - - 'nature-people': u'', - - 'nature': u'', - - 'navigation': u'', - - 'open-in-browser': u'', - - 'open-in-new': u'', - - 'palette': u'', - - 'parking': u'', - - 'pin-account': u'', - - 'pin-assistant': u'', - - 'pin-drop': u'', - - 'pin-help': u'', - - 'pin-off': u'', - - 'pin': u'', - - 'pizza': u'', - - 'plaster': u'', - - 'power-setting': u'', - - 'power': u'', - - 'print': u'', - - 'puzzle-piece': u'', - - 'quote': u'', - - 'railway': u'', - - 'receipt': u'', - - 'refresh-alt': u'', - - 'refresh-sync-alert': u'', - - 'refresh-sync-off': u'', - - 'refresh-sync': u'', - - 'refresh': u'', - - 'roller': u'', - - 'ruler': u'', - - 'scissors': u'', - - 'screen-rotation-lock': u'', - - 'screen-rotation': u'', - - 'search-for': u'', - - 'search-in-file': u'', - - 'search-in-page': u'', - - 'search-replace': u'', - - 'search': u'', - - 'seat': u'', - - 'settings-square': u'', - - 'settings': u'', - - 'shape': u'', - - 'shield-check': u'', - - 'shield-security': u'', - - 'shopping-basket': u'', - - 'shopping-cart-plus': u'', - - 'shopping-cart': u'', - - 'sign-in': u'', - - 'sort-amount-asc': u'', - - 'sort-amount-desc': u'', - - 'sort-asc': u'', - - 'sort-desc': u'', - - 'spellcheck': u'', - - 'spinner': u'', - - 'storage': u'', - - 'store-24': u'', - - 'store': u'', - - 'subway': u'', - - 'sun': u'', - - 'tab-unselected': u'', - - 'tab': u'', - - 'tag-close': u'', - - 'tag-more': u'', - - 'tag': u'', - - 'thumb-down': u'', - - 'thumb-up-down': u'', - - 'thumb-up': u'', - - 'ticket-star': u'', - - 'toll': u'', - - 'toys': u'', - - 'traffic': u'', - - 'translate': u'', - - 'triangle-down': u'', - - 'triangle-up': u'', - - 'truck': u'', - - 'turning-sign': u'', - - ' ungroup': u'', - - 'wallpaper': u'', - - 'washing-machine': u'', - - 'window-maximize': u'', - - 'window-minimize': u'', - - 'window-restore': u'', - - 'wrench': u'', - - 'zoom-in': u'', - - 'zoom-out': u'', - - 'alert-circle-o': u'', - - 'alert-circle': u'', - - 'alert-octagon': u'', - - 'alert-polygon': u'', - - 'alert-triangle': u'', - - 'help-outline': u'', - - 'help': u'', - - 'info-outline': u'', - - 'info': u'', - - 'notifications-active': u'', - - 'notifications-add': u'', - - 'notifications-none': u'', - - 'notifications-off': u'', - - 'notifications-paused': u'', - - 'notifications': u'', - - 'account-add': u'', - - 'account-box-mail': u'', - - 'account-box-o': u'', - - 'account-box-phone': u'', - - 'account-box': u'', - - 'account-calendar': u'', - - 'account-circle': u'', - - 'account-o': u'', - - 'account': u'', - - 'accounts-add': u'', - - 'accounts-alt': u'', - - 'accounts-list-alt': u'', - - 'accounts-list': u'', - - 'accounts-outline': u'', - - 'accounts': u'', - - 'face': u'', - - 'female': u'', - - 'male-alt': u'', - - 'male-female': u'', - - 'male': u'', - - 'mood-bad': u'', - - 'mood': u'', - - 'run': u'', - - 'walk': u'', - - 'cloud-box': u'', - - 'cloud-circle': u'', - - 'cloud-done': u'', - - 'cloud-download': u'', - - 'cloud-off': u'', - - 'cloud-outline-alt': u'', - - 'cloud-outline': u'', - - 'cloud-upload': u'', - - 'cloud': u'', - - 'download': u'', - - 'file-plus': u'', - - 'file-text': u'', - - 'file': u'', - - 'folder-outline': u'', - - 'folder-person': u'', - - 'folder-star-alt': u'', - - 'folder-star': u'', - - 'folder': u'', - - 'gif': u'', - - 'upload': u'', - - 'border-all': u'', - - 'border-bottom': u'', - - 'border-clear': u'', - - 'border-color': u'', - - 'border-horizontal': u'', - - 'border-inner': u'', - - 'border-left': u'', - - 'border-outer': u'', - - 'border-right': u'', - - 'border-style': u'', - - 'border-top': u'', - - 'border-vertical': u'', - - 'copy': u'', - - 'crop': u'', - - 'format-align-center': u'', - - 'format-align-justify': u'', - - 'format-align-left': u'', - - 'format-align-right': u'', - - 'format-bold': u'', - - 'format-clear-all': u'', - - 'format-clear': u'', - - 'format-color-fill': u'', - - 'format-color-reset': u'', - - 'format-color-text': u'', - - 'format-indent-decrease': u'', - - 'format-indent-increase': u'', - - 'format-italic': u'', - - 'format-line-spacing': u'', - - 'format-list-bulleted': u'', - - 'format-list-numbered': u'', - - 'format-ltr': u'', - - 'format-rtl': u'', - - 'format-size': u'', - - 'format-strikethrough-s': u'', - - 'format-strikethrough': u'', - - 'format-subject': u'', - - 'format-underlined': u'', - - 'format-valign-bottom': u'', - - 'format-valign-center': u'', - - 'format-valign-top': u'', - - 'redo': u'', - - 'select-all': u'', - - 'space-bar': u'', - - 'text-format': u'', - - 'transform': u'', - - 'undo': u'', - - 'wrap-text': u'', - - 'comment-alert': u'', - - 'comment-alt-text': u'', - - 'comment-alt': u'', - - 'comment-edit': u'', - - 'comment-image': u'', - - 'comment-list': u'', - - 'comment-more': u'', - - 'comment-outline': u'', - - 'comment-text-alt': u'', - - 'comment-text': u'', - - 'comment-video': u'', - - 'comment': u'', - - 'comments': u'', - - 'rm': u'F', - - 'check-all': u'', - - 'check-circle-u': u'', - - 'check-circle': u'', - - 'check-square': u'', - - 'check': u'', - - 'circle-o': u'', - - 'circle': u'', - - 'dot-circle-alt': u'', - - 'dot-circle': u'', - - 'minus-circle-outline': u'', - - 'minus-circle': u'', - - 'minus-square': u'', - - 'minus': u'', - - 'plus-circle-o-duplicate': u'', - - 'plus-circle-o': u'', - - 'plus-circle': u'', - - 'plus-square': u'', - - 'plus': u'', - - 'square-o': u'', - - 'star-circle': u'', - - 'star-half': u'', - - 'star-outline': u'', - - 'star': u'', - - 'bluetooth-connected': u'', - - 'bluetooth-off': u'', - - 'bluetooth-search': u'', - - 'bluetooth-setting': u'', - - 'bluetooth': u'', - - 'camera-add': u'', - - 'camera-alt': u'', - - 'camera-bw': u'', - - 'camera-front': u'', - - 'camera-mic': u'', - - 'camera-party-mode': u'', - - 'camera-rear': u'', - - 'camera-roll': u'', - - 'camera-switch': u'', - - 'camera': u'', - - 'card-alert': u'', - - 'card-off': u'', - - 'card-sd': u'', - - 'card-sim': u'', - - 'desktop-mac': u'', - - 'desktop-windows': u'', - - 'device-hub': u'', - - 'devices-off': u'', - - 'devices': u'', - - 'dock': u'', - - 'floppy': u'', - - 'gamepad': u'', - - 'gps-dot': u'', - - 'gps-off': u'', - - 'gps': u'', - - 'headset-mic': u'', - - 'headset': u'', - - 'input-antenna': u'', - - 'input-composite': u'', - - 'input-hdmi': u'', - - 'input-power': u'', - - 'input-svideo': u'', - - 'keyboard-hide': u'', - - 'keyboard': u'', - - 'laptop-chromebook': u'', - - 'laptop-mac': u'', - - 'laptop': u'', - - 'mic-off': u'', - - 'mic-outline': u'', - - 'mic-setting': u'', - - 'mic': u'', - - 'mouse': u'', - - 'network-alert': u'', - - 'network-locked': u'', - - 'network-off': u'', - - 'network-outline': u'', - - 'network-setting': u'', - - 'network': u'', - - 'phone-bluetooth': u'', - - 'phone-end': u'', - - 'phone-forwarded': u'', - - 'phone-in-talk': u'', - - 'phone-locked': u'', - - 'phone-missed': u'', - - 'phone-msg': u'', - - 'phone-paused': u'', - - 'phone-ring': u'', - - 'phone-setting': u'', - - 'phone-sip': u'', - - 'phone': u'', - - 'portable-wifi-changes': u'', - - 'portable-wifi-off': u'', - - 'portable-wifi': u'', - - 'radio': u'', - - 'reader': u'', - - 'remote-control-alt': u'', - - 'remote-control': u'', - - 'router': u'', - - 'scanner': u'', - - 'smartphone-android': u'', - - 'smartphone-download': u'', - - 'smartphone-erase': u'', - - 'smartphone-info': u'', - - 'smartphone-iphone': u'', - - 'smartphone-landscape-lock': u'', - - 'smartphone-landscape': u'', - - 'smartphone-lock': u'', - - 'smartphone-portrait-lock': u'', - - 'smartphone-ring': u'', - - 'smartphone-setting': u'', - - 'smartphone-setup': u'', - - 'smartphone': u'', - - 'speaker': u'', - - 'tablet-android': u'', - - 'tablet-mac': u'', - - 'tablet': u'', - - 'tv-alt-play': u'', - - 'tv-list': u'', - - 'tv-play': u'', - - 'tv': u'', - - 'usb': u'', - - 'videocam-off': u'', - - 'videocam-switch': u'', - - 'videocam': u'', - - 'watch': u'', - - 'wifi-alt-2': u'', - - 'wifi-alt': u'', - - 'wifi-info': u'', - - 'wifi-lock': u'', - - 'wifi-off': u'', - - 'wifi-outline': u'', - - 'wifi': u'', - - 'arrow-left-bottom': u'', - - 'arrow-left': u'', - - 'arrow-merge': u'', - - 'arrow-missed': u'', - - 'arrow-right-top': u'', - - 'arrow-right': u'', - - 'arrow-split': u'', - - 'arrows': u'', - - 'caret-down-circle': u'', - - 'caret-down': u'', - - 'caret-left-circle': u'', - - 'caret-left': u'', - - 'caret-right-circle': u'', - - 'caret-right': u'', - - 'caret-up-circle': u'', - - 'caret-up': u'', - - 'chevron-down': u'', - - 'chevron-left': u'', - - 'chevron-right': u'', - - 'chevron-up': u'', - - 'forward': u'', - - 'long-arrow-down': u'', - - 'long-arrow-left': u'', - - 'long-arrow-return': u'', - - 'long-arrow-right': u'', - - 'long-arrow-tab': u'', - - 'long-arrow-up': u'', - - 'rotate-ccw': u'', - - 'rotate-cw': u'', - - 'rotate-left': u'', - - 'rotate-right': u'', - - 'square-down': u'', - - 'square-right': u'', - - 'swap-alt': u'', - - 'swap-vertical-circle': u'', - - 'swap-vertical': u'', - - 'swap': u'', - - 'trending-down': u'', - - 'trending-flat': u'', - - 'trending-up': u'', - - 'unfold-less': u'', - - 'unfold-more': u'', - - 'apps': u'', - - 'grid-off': u'', - - 'grid': u'', - - 'view-agenda': u'', - - 'view-array': u'', - - 'view-carousel': u'', - - 'view-column': u'', - - 'view-comfy': u'', - - 'view-compact': u'', - - 'view-dashboard': u'', - - 'view-day': u'', - - 'view-headline': u'', - - 'view-list-alt': u'', - - 'view-list': u'', - - 'view-module': u'', - - 'view-quilt': u'', - - 'view-stream': u'', - - 'view-subtitles': u'', - - 'view-toc': u'', - - 'view-web': u'', - - 'view-week': u'', - - 'widgets': u'', - - 'alarm-check': u'', - - 'alarm-off': u'', - - 'alarm-plus': u'', - - 'alarm-snooze': u'', - - 'alarm': u'', - - 'calendar-alt': u'', - - 'calendar-check': u'', - - 'calendar-close': u'', - - 'calendar-note': u'', - - 'calendar': u'', - - 'time-countdown': u'', - - 'time-interval': u'', - - 'time-restore-setting': u'', - - 'time-restore': u'', - - 'time': u'', - - 'timer-off': u'', - - 'timer': u'', - - 'android-alt': u'', - - 'android': u'', - - 'apple': u'', - - 'behance': u'', - - 'codepen': u'', - - 'dribbble': u'', - - 'dropbox': u'', - - 'evernote': u'', - - 'facebook-box': u'', - - 'facebook': u'', - - 'github-box': u'', - - 'github': u'', - - 'google-drive': u'', - - 'google-earth': u'', - - 'google-glass': u'', - - 'google-maps': u'', - - 'google-pages': u'', - - 'google-play': u'', - - 'google-plus-box': u'', - - 'google-plus': u'', - - 'google': u'', - - 'instagram': u'', - - 'language-css3': u'', - - 'language-html5': u'', - - 'language-javascript': u'', - - 'language-python-alt': u'', - - 'language-python': u'', - - 'lastfm': u'', - - 'linkedin-box': u'', - - 'paypal': u'', - - 'pinterest-box': u'', - - 'pocket': u'', - - 'polymer': u'', - - 'rss': u'', - - 'share': u'', - - 'stackoverflow': u'', - - 'steam-square': u'', - - 'steam': u'', - - 'twitter-box': u'', - - 'twitter': u'', - - 'vk': u'', - - 'wikipedia': u'', - - 'windows': u'', - - '500px': u'', - - '8tracks': u'', - - 'amazon': u'', - - 'blogger': u'', - - 'delicious': u'', - - 'disqus': u'', - - 'flattr': u'', - - 'flickr': u'', - - 'github-alt': u'', - - 'google-old': u'', - - 'linkedin': u'', - - 'odnoklassniki': u'', - - 'outlook': u'', - - 'paypal-alt': u'', - - 'pinterest': u'', - - 'playstation': u'', - - 'reddit': u'', - - 'skype': u'', - - 'slideshare': u'', - - 'soundcloud': u'', - - 'tumblr': u'', - - 'twitch': u'', - - 'vimeo': u'', - - 'whatsapp': u'', - - 'xbox': u'', - - 'yahoo': u'', - - 'youtube-play': u'', - - 'youtube': u'', - - 'aspect-ratio-alt': u'', - - 'aspect-ratio': u'', - - 'blur-circular': u'', - - 'blur-linear': u'', - - 'blur-off': u'', - - 'blur': u'', - - 'brightness-2': u'', - - 'brightness-3': u'', - - 'brightness-4': u'', - - 'brightness-5': u'', - - 'brightness-6': u'', - - 'brightness-7': u'', - - 'brightness-auto': u'', - - 'brightness-setting': u'', - - 'broken-image': u'', - - 'center-focus-strong': u'', - - 'center-focus-weak': u'', - - 'compare': u'', - - 'crop-16-9': u'', - - 'crop-3-2': u'', - - 'crop-5-4': u'', - - 'crop-7-5': u'', - - 'crop-din': u'', - - 'crop-free': u'', - - 'crop-landscape': u'', - - 'crop-portrait': u'', - - 'crop-square': u'', - - 'exposure-alt': u'', - - 'exposure': u'', - - 'filter-b-and-w': u'', - - 'filter-center-focus': u'', - - 'filter-frames': u'', - - 'filter-tilt-shift': u'', - - 'gradient': u'', - - 'grain': u'', - - 'graphic-eq': u'', - - 'hdr-off': u'', - - 'hdr-strong': u'', - - 'hdr-weak': u'', - - 'hdr': u'', - - 'iridescent': u'', - - 'leak-off': u'', - - 'leak': u'', - - 'looks': u'', - - 'loupe': u'', - - 'panorama-horizontal': u'', - - 'panorama-vertical': u'', - - 'panorama-wide-angle': u'', - - 'photo-size-select-large': u'', - - 'photo-size-select-small': u'', - - 'picture-in-picture': u'', - - 'slideshow': u'', - - 'texture': u'', - - 'tonality': u'', - - 'vignette': u'', - - 'wb-auto': u'', - - 'eject-alt': u'', - - 'eject': u'', - - 'equalizer': u'', - - 'fast-forward': u'', - - 'fast-rewind': u'', - - 'forward-10': u'', - - 'forward-30': u'', - - 'forward-5': u'', - - 'hearing': u'', - - 'pause-circle-outline': u'', - - 'pause-circle': u'', - - 'pause': u'', - - 'play-circle-outline': u'', - - 'play-circle': u'', - - 'play': u'', - - 'playlist-audio': u'', - - 'playlist-plus': u'', - - 'repeat-one': u'', - - 'repeat': u'', - - 'replay-10': u'', - - 'replay-30': u'', - - 'replay-5': u'', - - 'replay': u'', - - 'shuffle': u'', - - 'skip-next': u'', - - 'skip-previous': u'', - - 'stop': u'', - - 'surround-sound': u'', - - 'tune': u'', - - 'volume-down': u'', - - 'volume-mute': u'', - - 'volume-off': u'', - - 'volume-up': u'', - - 'n-1-square': u'', - - 'n-2-square': u'', - - 'n-3-square': u'', - - 'n-4-square': u'', - - 'n-5-square': u'', - - 'n-6-square': u'', - - 'neg-1': u'', - - 'neg-2': u'', - - 'plus-1': u'', - - 'plus-2': u'', - - 'sec-10': u'', - - 'sec-3': u'', - - 'zero': u'', - - 'airline-seat-flat-angled': u'', - - 'airline-seat-flat': u'', - - 'airline-seat-individual-suite': u'', - - 'airline-seat-legroom-extra': u'', - - 'airline-seat-legroom-normal': u'', - - 'airline-seat-legroom-reduced': u'', - - 'airline-seat-recline-extra': u'', - - 'airline-seat-recline-normal': u'', - - 'airplay': u'', - - 'closed-caption': u'', - - 'confirmation-number': u'', - - 'developer-board': u'', - - 'disc-full': u'', - - 'explicit': u'', - - 'flight-land': u'', - - 'flight-takeoff': u'', - - 'flip-to-back': u'', - - 'flip-to-front': u'', - - 'group-work': u'', - - 'hd': u'', - - 'hq': u'', - - 'markunread-mailbox': u'', - - 'memory': u'', - - 'nfc': u'', - - 'play-for-work': u'', - - 'power-input': u'', - - 'present-to-all': u'', - - 'satellite': u'', - - 'tap-and-play': u'', - - 'vibration': u'', - - 'voicemail': u'', -} diff --git a/src/kivymd/images/kivymd_512.png b/src/kivymd/images/kivymd_512.png deleted file mode 100644 index 7dbae604..00000000 Binary files a/src/kivymd/images/kivymd_512.png and /dev/null differ diff --git a/src/kivymd/images/kivymd_logo.png b/src/kivymd/images/kivymd_logo.png deleted file mode 100644 index 64d956d4..00000000 Binary files a/src/kivymd/images/kivymd_logo.png and /dev/null differ diff --git a/src/kivymd/images/quad_shadow-0.png b/src/kivymd/images/quad_shadow-0.png deleted file mode 100644 index 5d64fde5..00000000 Binary files a/src/kivymd/images/quad_shadow-0.png and /dev/null differ diff --git a/src/kivymd/images/quad_shadow-1.png b/src/kivymd/images/quad_shadow-1.png deleted file mode 100644 index c0f1e226..00000000 Binary files a/src/kivymd/images/quad_shadow-1.png and /dev/null differ diff --git a/src/kivymd/images/quad_shadow-2.png b/src/kivymd/images/quad_shadow-2.png deleted file mode 100644 index 44619e56..00000000 Binary files a/src/kivymd/images/quad_shadow-2.png and /dev/null differ diff --git a/src/kivymd/images/quad_shadow.atlas b/src/kivymd/images/quad_shadow.atlas deleted file mode 100644 index 68e0aad2..00000000 --- a/src/kivymd/images/quad_shadow.atlas +++ /dev/null @@ -1 +0,0 @@ -{"quad_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "quad_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "quad_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}} \ No newline at end of file diff --git a/src/kivymd/images/rec_shadow-0.png b/src/kivymd/images/rec_shadow-0.png deleted file mode 100644 index f02b919a..00000000 Binary files a/src/kivymd/images/rec_shadow-0.png and /dev/null differ diff --git a/src/kivymd/images/rec_shadow-1.png b/src/kivymd/images/rec_shadow-1.png deleted file mode 100644 index f752fd26..00000000 Binary files a/src/kivymd/images/rec_shadow-1.png and /dev/null differ diff --git a/src/kivymd/images/rec_shadow.atlas b/src/kivymd/images/rec_shadow.atlas deleted file mode 100644 index 71b0e9d6..00000000 --- a/src/kivymd/images/rec_shadow.atlas +++ /dev/null @@ -1 +0,0 @@ -{"rec_shadow-1.png": {"20": [2, 266, 256, 128], "21": [260, 266, 256, 128], "22": [518, 266, 256, 128], "23": [776, 266, 256, 128], "3": [260, 136, 256, 128], "2": [2, 136, 256, 128], "5": [776, 136, 256, 128], "4": [518, 136, 256, 128], "7": [260, 6, 256, 128], "6": [2, 6, 256, 128], "9": [776, 6, 256, 128], "8": [518, 6, 256, 128]}, "rec_shadow-0.png": {"11": [518, 266, 256, 128], "10": [260, 266, 256, 128], "13": [2, 136, 256, 128], "12": [776, 266, 256, 128], "15": [518, 136, 256, 128], "14": [260, 136, 256, 128], "17": [2, 6, 256, 128], "16": [776, 136, 256, 128], "19": [518, 6, 256, 128], "18": [260, 6, 256, 128], "1": [776, 6, 256, 128], "0": [2, 266, 256, 128]}} \ No newline at end of file diff --git a/src/kivymd/images/rec_st_shadow-0.png b/src/kivymd/images/rec_st_shadow-0.png deleted file mode 100644 index 887327db..00000000 Binary files a/src/kivymd/images/rec_st_shadow-0.png and /dev/null differ diff --git a/src/kivymd/images/rec_st_shadow-1.png b/src/kivymd/images/rec_st_shadow-1.png deleted file mode 100644 index 759ee652..00000000 Binary files a/src/kivymd/images/rec_st_shadow-1.png and /dev/null differ diff --git a/src/kivymd/images/rec_st_shadow-2.png b/src/kivymd/images/rec_st_shadow-2.png deleted file mode 100644 index e9fdaccc..00000000 Binary files a/src/kivymd/images/rec_st_shadow-2.png and /dev/null differ diff --git a/src/kivymd/images/rec_st_shadow.atlas b/src/kivymd/images/rec_st_shadow.atlas deleted file mode 100644 index d4c24abe..00000000 --- a/src/kivymd/images/rec_st_shadow.atlas +++ /dev/null @@ -1 +0,0 @@ -{"rec_st_shadow-0.png": {"11": [262, 138, 128, 256], "10": [132, 138, 128, 256], "13": [522, 138, 128, 256], "12": [392, 138, 128, 256], "15": [782, 138, 128, 256], "14": [652, 138, 128, 256], "16": [912, 138, 128, 256], "0": [2, 138, 128, 256]}, "rec_st_shadow-1.png": {"20": [522, 138, 128, 256], "21": [652, 138, 128, 256], "17": [2, 138, 128, 256], "23": [912, 138, 128, 256], "19": [262, 138, 128, 256], "18": [132, 138, 128, 256], "22": [782, 138, 128, 256], "1": [392, 138, 128, 256]}, "rec_st_shadow-2.png": {"3": [132, 138, 128, 256], "2": [2, 138, 128, 256], "5": [392, 138, 128, 256], "4": [262, 138, 128, 256], "7": [652, 138, 128, 256], "6": [522, 138, 128, 256], "9": [912, 138, 128, 256], "8": [782, 138, 128, 256]}} \ No newline at end of file diff --git a/src/kivymd/images/round_shadow-0.png b/src/kivymd/images/round_shadow-0.png deleted file mode 100644 index 26d98405..00000000 Binary files a/src/kivymd/images/round_shadow-0.png and /dev/null differ diff --git a/src/kivymd/images/round_shadow-1.png b/src/kivymd/images/round_shadow-1.png deleted file mode 100644 index d0f4c0fd..00000000 Binary files a/src/kivymd/images/round_shadow-1.png and /dev/null differ diff --git a/src/kivymd/images/round_shadow-2.png b/src/kivymd/images/round_shadow-2.png deleted file mode 100644 index d5feef2c..00000000 Binary files a/src/kivymd/images/round_shadow-2.png and /dev/null differ diff --git a/src/kivymd/images/round_shadow.atlas b/src/kivymd/images/round_shadow.atlas deleted file mode 100644 index f25016dc..00000000 --- a/src/kivymd/images/round_shadow.atlas +++ /dev/null @@ -1 +0,0 @@ -{"round_shadow-1.png": {"20": [2, 136, 128, 128], "21": [132, 136, 128, 128], "22": [262, 136, 128, 128], "23": [2, 6, 128, 128], "19": [132, 266, 128, 128], "18": [2, 266, 128, 128], "1": [262, 266, 128, 128], "3": [262, 6, 128, 128], "2": [132, 6, 128, 128]}, "round_shadow-0.png": {"11": [262, 266, 128, 128], "10": [132, 266, 128, 128], "13": [132, 136, 128, 128], "12": [2, 136, 128, 128], "15": [2, 6, 128, 128], "14": [262, 136, 128, 128], "17": [262, 6, 128, 128], "16": [132, 6, 128, 128], "0": [2, 266, 128, 128]}, "round_shadow-2.png": {"5": [132, 266, 128, 128], "4": [2, 266, 128, 128], "7": [2, 136, 128, 128], "6": [262, 266, 128, 128], "9": [262, 136, 128, 128], "8": [132, 136, 128, 128]}} \ No newline at end of file diff --git a/src/kivymd/label.py b/src/kivymd/label.py deleted file mode 100644 index 844f2a07..00000000 --- a/src/kivymd/label.py +++ /dev/null @@ -1,94 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.lang import Builder -from kivy.metrics import sp -from kivy.properties import OptionProperty, DictProperty, ListProperty -from kivy.uix.label import Label -from kivymd.material_resources import DEVICE_TYPE -from kivymd.theming import ThemableBehavior - -Builder.load_string(''' - - disabled_color: self.theme_cls.disabled_hint_text_color - text_size: (self.width, None) -''') - - -class MDLabel(ThemableBehavior, Label): - font_style = OptionProperty( - 'Body1', options=['Body1', 'Body2', 'Caption', 'Subhead', 'Title', - 'Headline', 'Display1', 'Display2', 'Display3', - 'Display4', 'Button', 'Icon']) - - # Font, Bold, Mobile size, Desktop size (None if same as Mobile) - _font_styles = DictProperty({'Body1': ['Roboto', False, 14, 13], - 'Body2': ['Roboto', True, 14, 13], - 'Caption': ['Roboto', False, 12, None], - 'Subhead': ['Roboto', False, 16, 15], - 'Title': ['Roboto', True, 20, None], - 'Headline': ['Roboto', False, 24, None], - 'Display1': ['Roboto', False, 34, None], - 'Display2': ['Roboto', False, 45, None], - 'Display3': ['Roboto', False, 56, None], - 'Display4': ['RobotoLight', False, 112, None], - 'Button': ['Roboto', True, 14, None], - 'Icon': ['Icons', False, 24, None]}) - - theme_text_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - - text_color = ListProperty(None, allownone=True) - - _currently_bound_property = {} - - def __init__(self, **kwargs): - super(MDLabel, self).__init__(**kwargs) - self.on_theme_text_color(None, self.theme_text_color) - self.on_font_style(None, self.font_style) - self.on_opposite_colors(None, self.opposite_colors) - - def on_font_style(self, instance, style): - info = self._font_styles[style] - self.font_name = info[0] - self.bold = info[1] - if DEVICE_TYPE == 'desktop' and info[3] is not None: - self.font_size = sp(info[3]) - else: - self.font_size = sp(info[2]) - - def on_theme_text_color(self, instance, value): - t = self.theme_cls - op = self.opposite_colors - setter = self.setter('color') - t.unbind(**self._currently_bound_property) - c = {} - if value == 'Primary': - c = {'text_color' if not op else 'opposite_text_color': setter} - t.bind(**c) - self.color = t.text_color if not op else t.opposite_text_color - elif value == 'Secondary': - c = {'secondary_text_color' if not op else - 'opposite_secondary_text_color': setter} - t.bind(**c) - self.color = t.secondary_text_color if not op else \ - t.opposite_secondary_text_color - elif value == 'Hint': - c = {'disabled_hint_text_color' if not op else - 'opposite_disabled_hint_text_color': setter} - t.bind(**c) - self.color = t.disabled_hint_text_color if not op else \ - t.opposite_disabled_hint_text_color - elif value == 'Error': - c = {'error_color': setter} - t.bind(**c) - self.color = t.error_color - elif value == 'Custom': - self.color = self.text_color if self.text_color else (0, 0, 0, 1) - self._currently_bound_property = c - - def on_text_color(self, *args): - if self.theme_text_color == 'Custom': - self.color = self.text_color - - def on_opposite_colors(self, instance, value): - self.on_theme_text_color(self, self.theme_text_color) diff --git a/src/kivymd/list.py b/src/kivymd/list.py deleted file mode 100644 index 36162329..00000000 --- a/src/kivymd/list.py +++ /dev/null @@ -1,531 +0,0 @@ -# -*- coding: utf-8 -*- -''' -Lists -===== - -`Material Design spec, Lists page `_ - -`Material Design spec, Lists: Controls page `_ - -The class :class:`MDList` in combination with a ListItem like -:class:`OneLineListItem` will create a list that expands as items are added to -it, working nicely with Kivy's :class:`~kivy.uix.scrollview.ScrollView`. - - -Simple examples ---------------- - -Kv Lang: - -.. code-block:: python - - ScrollView: - do_scroll_x: False # Important for MD compliance - MDList: - OneLineListItem: - text: "Single-line item" - TwoLineListItem: - text: "Two-line item" - secondary_text: "Secondary text here" - ThreeLineListItem: - text: "Three-line item" - secondary_text: "This is a multi-line label where you can fit more text than usual" - - -Python: - -.. code-block:: python - - # Sets up ScrollView with MDList, as normally used in Android: - sv = ScrollView() - ml = MDList() - sv.add_widget(ml) - - contacts = ["Paula", "John", "Kate", "Vlad"] - for c in contacts: - ml.add_widget( - OneLineListItem( - text=c - ) - ) - -Advanced usage --------------- - -Due to the variety in sizes and controls in the MD spec, this module suffers -from a certain level of complexity to keep the widgets compliant, flexible -and performant. - -For this KivyMD provides ListItems that try to cover the most common usecases, -when those are insufficient, there's a base class called :class:`ListItem` -which you can use to create your own ListItems. This documentation will only -cover the provided ones, for custom implementations please refer to this -module's source code. - -Text only ListItems -------------------- - -- :class:`~OneLineListItem` -- :class:`~TwoLineListItem` -- :class:`~ThreeLineListItem` - -These are the simplest ones. The :attr:`~ListItem.text` attribute changes the -text in the most prominent line, while :attr:`~ListItem.secondary_text` -changes the second and third line. - -If there are only two lines, :attr:`~ListItem.secondary_text` will shorten -the text to fit in case it is too long; if a third line is available, it will -instead wrap the text to make use of it. - -ListItems with widget containers --------------------------------- - -- :class:`~OneLineAvatarListItem` -- :class:`~TwoLineAvatarListItem` -- :class:`~ThreeLineAvatarListItem` -- :class:`~OneLineIconListItem` -- :class:`~TwoLineIconListItem` -- :class:`~ThreeLineIconListItem` -- :class:`~OneLineAvatarIconListItem` -- :class:`~TwoLineAvatarIconListItem` -- :class:`~ThreeLineAvatarIconListItem` - -These widgets will take other widgets that inherit from :class:`~ILeftBody`, -:class:`ILeftBodyTouch`, :class:`~IRightBody` or :class:`~IRightBodyTouch` and -put them in their corresponding container. - -As the name implies, :class:`~ILeftBody` and :class:`~IRightBody` will signal -that the widget goes into the left or right container, respectively. - -:class:`~ILeftBodyTouch` and :class:`~IRightBodyTouch` do the same thing, -except these widgets will also receive touch events that occur within their -surfaces. - -Python example: - -.. code-block:: python - - class ContactPhoto(ILeftBody, AsyncImage): - pass - - class MessageButton(IRightBodyTouch, MDIconButton): - phone_number = StringProperty() - - def on_release(self): - # sample code: - Dialer.send_sms(phone_number, "Hey! What's up?") - pass - - # Sets up ScrollView with MDList, as normally used in Android: - sv = ScrollView() - ml = MDList() - sv.add_widget(ml) - - contacts = [ - ["Annie", "555-24235", "http://myphotos.com/annie.png"], - ["Bob", "555-15423", "http://myphotos.com/bob.png"], - ["Claire", "555-66098", "http://myphotos.com/claire.png"] - ] - - for c in contacts: - item = TwoLineAvatarIconListItem( - text=c[0], - secondary_text=c[1] - ) - item.add_widget(ContactPhoto(source=c[2])) - item.add_widget(MessageButton(phone_number=c[1]) - ml.add_widget(item) - -API ---- -''' - -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.properties import ObjectProperty, StringProperty, NumericProperty, \ - ListProperty, OptionProperty -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.floatlayout import FloatLayout -from kivy.uix.gridlayout import GridLayout -import kivymd.material_resources as m_res -from kivymd.ripplebehavior import RectangularRippleBehavior -from kivymd.theming import ThemableBehavior - -Builder.load_string(''' -#:import m_res kivymd.material_resources - - cols: 1 - size_hint_y: None - height: self._min_list_height - padding: 0, self._list_vertical_padding - - - size_hint_y: None - canvas: - Color: - rgba: self.theme_cls.divider_color - Line: - points: root.x,root.y, root.x+self.width,root.y - BoxLayout: - id: _text_container - orientation: 'vertical' - pos: root.pos - padding: root._txt_left_pad, root._txt_top_pad, root._txt_right_pad, root._txt_bot_pad - MDLabel: - id: _lbl_primary - text: root.text - font_style: root.font_style - theme_text_color: root.theme_text_color - text_color: root.text_color - size_hint_y: None - height: self.texture_size[1] - MDLabel: - id: _lbl_secondary - text: '' if root._num_lines == 1 else root.secondary_text - font_style: root.secondary_font_style - theme_text_color: root.secondary_theme_text_color - text_color: root.secondary_text_color - size_hint_y: None - height: 0 if root._num_lines == 1 else self.texture_size[1] - shorten: True if root._num_lines == 2 else False - - - BoxLayout: - id: _left_container - size_hint: None, None - x: root.x + dp(16) - y: root.y + root.height/2 - self.height/2 - size: dp(40), dp(40) - - - BoxLayout: - id: _left_container - size_hint: None, None - x: root.x + dp(16) - y: root.y + root.height - root._txt_top_pad - self.height - dp(5) - size: dp(40), dp(40) - - - BoxLayout: - id: _left_container - size_hint: None, None - x: root.x + dp(16) - y: root.y + root.height/2 - self.height/2 - size: dp(48), dp(48) - - - BoxLayout: - id: _left_container - size_hint: None, None - x: root.x + dp(16) - y: root.y + root.height - root._txt_top_pad - self.height - dp(5) - size: dp(48), dp(48) - - - BoxLayout: - id: _right_container - size_hint: None, None - x: root.x + root.width - m_res.HORIZ_MARGINS - self.width - y: root.y + root.height/2 - self.height/2 - size: dp(48), dp(48) - - - BoxLayout: - id: _right_container - size_hint: None, None - x: root.x + root.width - m_res.HORIZ_MARGINS - self.width - y: root.y + root.height/2 - self.height/2 - size: dp(48), dp(48) - - - BoxLayout: - id: _right_container - size_hint: None, None - x: root.x + root.width - m_res.HORIZ_MARGINS - self.width - y: root.y + root.height/2 - self.height/2 - size: dp(48), dp(48) - - - BoxLayout: - id: _right_container - size_hint: None, None - x: root.x + root.width - m_res.HORIZ_MARGINS - self.width - y: root.y + root.height/2 - self.height/2 - size: dp(48), dp(48) - - - BoxLayout: - id: _right_container - size_hint: None, None - x: root.x + root.width - m_res.HORIZ_MARGINS - self.width - y: root.y + root.height - root._txt_top_pad - self.height - dp(5) - size: dp(48), dp(48) -''') - - -class MDList(GridLayout): - '''ListItem container. Best used in conjunction with a - :class:`kivy.uix.ScrollView`. - - When adding (or removing) a widget, it will resize itself to fit its - children, plus top and bottom paddings as described by the MD spec. - ''' - selected = ObjectProperty() - _min_list_height = dp(16) - _list_vertical_padding = dp(8) - - icon = StringProperty() - - def add_widget(self, widget, index=0): - super(MDList, self).add_widget(widget, index) - self.height += widget.height - - def remove_widget(self, widget): - super(MDList, self).remove_widget(widget) - self.height -= widget.height - - -class BaseListItem(ThemableBehavior, RectangularRippleBehavior, - ButtonBehavior, FloatLayout): - '''Base class to all ListItems. Not supposed to be instantiated on its own. - ''' - - text = StringProperty() - '''Text shown in the first line. - - :attr:`text` is a :class:`~kivy.properties.StringProperty` and defaults - to "". - ''' - - text_color = ListProperty(None) - ''' Text color used if theme_text_color is set to 'Custom' ''' - - font_style = OptionProperty( - 'Subhead', options=['Body1', 'Body2', 'Caption', 'Subhead', 'Title', - 'Headline', 'Display1', 'Display2', 'Display3', - 'Display4', 'Button', 'Icon']) - - theme_text_color = StringProperty('Primary',allownone=True) - ''' Theme text color for primary text ''' - - secondary_text = StringProperty() - '''Text shown in the second and potentially third line. - - The text will wrap into the third line if the ListItem's type is set to - \'one-line\'. It can be forced into the third line by adding a \\n - escape sequence. - - :attr:`secondary_text` is a :class:`~kivy.properties.StringProperty` and - defaults to "". - ''' - - secondary_text_color = ListProperty(None) - ''' Text color used for secondary text if secondary_theme_text_color - is set to 'Custom' ''' - - secondary_theme_text_color = StringProperty('Secondary',allownone=True) - ''' Theme text color for secondary primary text ''' - - secondary_font_style = OptionProperty( - 'Body1', options=['Body1', 'Body2', 'Caption', 'Subhead', 'Title', - 'Headline', 'Display1', 'Display2', 'Display3', - 'Display4', 'Button', 'Icon']) - - _txt_left_pad = NumericProperty(dp(16)) - _txt_top_pad = NumericProperty() - _txt_bot_pad = NumericProperty() - _txt_right_pad = NumericProperty(m_res.HORIZ_MARGINS) - _num_lines = 2 - - -class ILeftBody: - '''Pseudo-interface for widgets that go in the left container for - ListItems that support it. - - Implements nothing and requires no implementation, for annotation only. - ''' - pass - - -class ILeftBodyTouch: - '''Same as :class:`~ILeftBody`, but allows the widget to receive touch - events instead of triggering the ListItem's ripple effect - ''' - pass - - -class IRightBody: - '''Pseudo-interface for widgets that go in the right container for - ListItems that support it. - - Implements nothing and requires no implementation, for annotation only. - ''' - pass - - -class IRightBodyTouch: - '''Same as :class:`~IRightBody`, but allows the widget to receive touch - events instead of triggering the ListItem's ripple effect - ''' - pass - - -class ContainerSupport: - '''Overrides add_widget in a ListItem to include support for I*Body - widgets when the appropiate containers are present. - ''' - _touchable_widgets = ListProperty() - - def add_widget(self, widget, index=0): - if issubclass(widget.__class__, ILeftBody): - self.ids['_left_container'].add_widget(widget) - elif issubclass(widget.__class__, ILeftBodyTouch): - self.ids['_left_container'].add_widget(widget) - self._touchable_widgets.append(widget) - elif issubclass(widget.__class__, IRightBody): - self.ids['_right_container'].add_widget(widget) - elif issubclass(widget.__class__, IRightBodyTouch): - self.ids['_right_container'].add_widget(widget) - self._touchable_widgets.append(widget) - else: - return super(BaseListItem, self).add_widget(widget,index) - - def remove_widget(self, widget): - super(BaseListItem, self).remove_widget(widget) - if widget in self._touchable_widgets: - self._touchable_widgets.remove(widget) - - def on_touch_down(self, touch): - if self.propagate_touch_to_touchable_widgets(touch, 'down'): - return - super(BaseListItem, self).on_touch_down(touch) - - def on_touch_move(self, touch, *args): - if self.propagate_touch_to_touchable_widgets(touch, 'move', *args): - return - super(BaseListItem, self).on_touch_move(touch, *args) - - def on_touch_up(self, touch): - if self.propagate_touch_to_touchable_widgets(touch, 'up'): - return - super(BaseListItem, self).on_touch_up(touch) - - def propagate_touch_to_touchable_widgets(self, touch, touch_event, *args): - triggered = False - for i in self._touchable_widgets: - if i.collide_point(touch.x, touch.y): - triggered = True - if touch_event == 'down': - i.on_touch_down(touch) - elif touch_event == 'move': - i.on_touch_move(touch, *args) - elif touch_event == 'up': - i.on_touch_up(touch) - return triggered - - -class OneLineListItem(BaseListItem): - _txt_top_pad = NumericProperty(dp(16)) - _txt_bot_pad = NumericProperty(dp(15)) # dp(20) - dp(5) - _num_lines = 1 - - def __init__(self, **kwargs): - super(OneLineListItem, self).__init__(**kwargs) - self.height = dp(48) - - -class TwoLineListItem(BaseListItem): - _txt_top_pad = NumericProperty(dp(20)) - _txt_bot_pad = NumericProperty(dp(15)) # dp(20) - dp(5) - - def __init__(self, **kwargs): - super(TwoLineListItem, self).__init__(**kwargs) - self.height = dp(72) - - -class ThreeLineListItem(BaseListItem): - _txt_top_pad = NumericProperty(dp(16)) - _txt_bot_pad = NumericProperty(dp(15)) # dp(20) - dp(5) - _num_lines = 3 - - def __init__(self, **kwargs): - super(ThreeLineListItem, self).__init__(**kwargs) - self.height = dp(88) - - -class OneLineAvatarListItem(ContainerSupport, BaseListItem): - _txt_left_pad = NumericProperty(dp(72)) - _txt_top_pad = NumericProperty(dp(20)) - _txt_bot_pad = NumericProperty(dp(19)) # dp(24) - dp(5) - _num_lines = 1 - - def __init__(self, **kwargs): - super(OneLineAvatarListItem, self).__init__(**kwargs) - self.height = dp(56) - - -class TwoLineAvatarListItem(OneLineAvatarListItem): - _txt_top_pad = NumericProperty(dp(20)) - _txt_bot_pad = NumericProperty(dp(15)) # dp(20) - dp(5) - _num_lines = 2 - - def __init__(self, **kwargs): - super(BaseListItem, self).__init__(**kwargs) - self.height = dp(72) - - -class ThreeLineAvatarListItem(ContainerSupport, ThreeLineListItem): - _txt_left_pad = NumericProperty(dp(72)) - - -class OneLineIconListItem(ContainerSupport, OneLineListItem): - _txt_left_pad = NumericProperty(dp(72)) - - -class TwoLineIconListItem(OneLineIconListItem): - _txt_top_pad = NumericProperty(dp(20)) - _txt_bot_pad = NumericProperty(dp(15)) # dp(20) - dp(5) - _num_lines = 2 - - def __init__(self, **kwargs): - super(BaseListItem, self).__init__(**kwargs) - self.height = dp(72) - - -class ThreeLineIconListItem(ContainerSupport, ThreeLineListItem): - _txt_left_pad = NumericProperty(dp(72)) - - -class OneLineRightIconListItem(ContainerSupport, OneLineListItem): - # dp(40) = dp(16) + dp(24): - _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS) - - -class TwoLineRightIconListItem(OneLineRightIconListItem): - _txt_top_pad = NumericProperty(dp(20)) - _txt_bot_pad = NumericProperty(dp(15)) # dp(20) - dp(5) - _num_lines = 2 - - def __init__(self, **kwargs): - super(BaseListItem, self).__init__(**kwargs) - self.height = dp(72) - - -class ThreeLineRightIconListitem(ContainerSupport, ThreeLineListItem): - # dp(40) = dp(16) + dp(24): - _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS) - - -class OneLineAvatarIconListItem(OneLineAvatarListItem): - # dp(40) = dp(16) + dp(24): - _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS) - - -class TwoLineAvatarIconListItem(TwoLineAvatarListItem): - # dp(40) = dp(16) + dp(24): - _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS) - - -class ThreeLineAvatarIconListItem(ThreeLineAvatarListItem): - # dp(40) = dp(16) + dp(24): - _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS) diff --git a/src/kivymd/material_resources.py b/src/kivymd/material_resources.py deleted file mode 100644 index 46270e5c..00000000 --- a/src/kivymd/material_resources.py +++ /dev/null @@ -1,50 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy import platform -from kivy.core.window import Window -from kivy.metrics import dp -from kivymd import fonts_path - -# Feel free to override this const if you're designing for a device such as -# a GNU/Linux tablet. -if platform != "android" and platform != "ios": - DEVICE_TYPE = "desktop" -elif Window.width >= dp(600) and Window.height >= dp(600): - DEVICE_TYPE = "tablet" -else: - DEVICE_TYPE = "mobile" - -if DEVICE_TYPE == "mobile": - MAX_NAV_DRAWER_WIDTH = dp(300) - HORIZ_MARGINS = dp(16) - STANDARD_INCREMENT = dp(56) - PORTRAIT_TOOLBAR_HEIGHT = STANDARD_INCREMENT - LANDSCAPE_TOOLBAR_HEIGHT = STANDARD_INCREMENT - dp(8) -else: - MAX_NAV_DRAWER_WIDTH = dp(400) - HORIZ_MARGINS = dp(24) - STANDARD_INCREMENT = dp(64) - PORTRAIT_TOOLBAR_HEIGHT = STANDARD_INCREMENT - LANDSCAPE_TOOLBAR_HEIGHT = STANDARD_INCREMENT - -TOUCH_TARGET_HEIGHT = dp(48) - -FONTS = [ - { - "name": "Roboto", - "fn_regular": fonts_path + 'Roboto-Regular.ttf', - "fn_bold": fonts_path + 'Roboto-Medium.ttf', - "fn_italic": fonts_path + 'Roboto-Italic.ttf', - "fn_bolditalic": fonts_path + 'Roboto-MediumItalic.ttf' - }, - { - "name": "RobotoLight", - "fn_regular": fonts_path + 'Roboto-Thin.ttf', - "fn_bold": fonts_path + 'Roboto-Light.ttf', - "fn_italic": fonts_path + 'Roboto-ThinItalic.ttf', - "fn_bolditalic": fonts_path + 'Roboto-LightItalic.ttf' - }, - { - "name": "Icons", - "fn_regular": fonts_path + 'Material-Design-Iconic-Font.ttf' - } -] diff --git a/src/kivymd/menu.py b/src/kivymd/menu.py deleted file mode 100644 index f4c96ac8..00000000 --- a/src/kivymd/menu.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.animation import Animation -from kivy.clock import Clock -from kivy.core.window import Window -from kivy.lang import Builder -from kivy.garden.recycleview import RecycleView -from kivy.metrics import dp -from kivy.properties import NumericProperty, ListProperty, OptionProperty, \ - StringProperty -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.boxlayout import BoxLayout -import kivymd.material_resources as m_res -from kivymd.theming import ThemableBehavior - -Builder.load_string(''' -#:import STD_INC kivymd.material_resources.STANDARD_INCREMENT - - size_hint_y: None - height: dp(48) - padding: dp(16), 0 - on_release: root.parent.parent.parent.parent.dismiss() # Horrible, but hey it works - MDLabel: - text: root.text - theme_text_color: 'Primary' - - - size_hint: None, None - width: root.width_mult * STD_INC - key_viewclass: 'viewclass' - key_size: 'height' - - - FloatLayout: - id: fl - MDMenu: - id: md_menu - data: root.items - width_mult: root.width_mult - size_hint: None, None - size: 0,0 - canvas.before: - Color: - rgba: root.theme_cls.bg_light - Rectangle: - size: self.size - pos: self.pos -''') - - -class MDMenuItem(ButtonBehavior, BoxLayout): - text = StringProperty() - - -class MDMenu(RecycleView): - width_mult = NumericProperty(1) - - -class MDDropdownMenu(ThemableBehavior, BoxLayout): - items = ListProperty() - '''See :attr:`~kivy.garden.recycleview.RecycleView.data` - ''' - - width_mult = NumericProperty(1) - '''This number multiplied by the standard increment (56dp on mobile, - 64dp on desktop, determines the width of the menu items. - - If the resulting number were to be too big for the application Window, - the multiplier will be adjusted for the biggest possible one. - ''' - - max_height = NumericProperty() - '''The menu will grow no bigger than this number. - - Set to 0 for no limit. Defaults to 0. - ''' - - border_margin = NumericProperty(dp(4)) - '''Margin between Window border and menu - ''' - - ver_growth = OptionProperty(None, allownone=True, - options=['up', 'down']) - '''Where the menu will grow vertically to when opening - - Set to None to let the widget pick for you. Defaults to None. - ''' - - hor_growth = OptionProperty(None, allownone=True, - options=['left', 'right']) - '''Where the menu will grow horizontally to when opening - - Set to None to let the widget pick for you. Defaults to None. - ''' - - def open(self, *largs): - Window.add_widget(self) - Clock.schedule_once(lambda x: self.display_menu(largs[0]), -1) - - def display_menu(self, caller): - # We need to pick a starting point, see how big we need to be, - # and where to grow to. - - c = caller.to_window(caller.center_x, - caller.center_y) # Starting coords - - # ---ESTABLISH INITIAL TARGET SIZE ESTIMATE--- - target_width = self.width_mult * m_res.STANDARD_INCREMENT - # If we're wider than the Window... - if target_width > Window.width: - # ...reduce our multiplier to max allowed. - target_width = int( - Window.width / m_res.STANDARD_INCREMENT) * m_res.STANDARD_INCREMENT - - target_height = sum([dp(48) for i in self.items]) - # If we're over max_height... - if 0 < self.max_height < target_height: - target_height = self.max_height - - # ---ESTABLISH VERTICAL GROWTH DIRECTION--- - if self.ver_growth is not None: - ver_growth = self.ver_growth - else: - # If there's enough space below us: - if target_height <= c[1] - self.border_margin: - ver_growth = 'down' - # if there's enough space above us: - elif target_height < Window.height - c[1] - self.border_margin: - ver_growth = 'up' - # otherwise, let's pick the one with more space and adjust ourselves - else: - # if there's more space below us: - if c[1] >= Window.height - c[1]: - ver_growth = 'down' - target_height = c[1] - self.border_margin - # if there's more space above us: - else: - ver_growth = 'up' - target_height = Window.height - c[1] - self.border_margin - - if self.hor_growth is not None: - hor_growth = self.hor_growth - else: - # If there's enough space to the right: - if target_width <= Window.width - c[0] - self.border_margin: - hor_growth = 'right' - # if there's enough space to the left: - elif target_width < c[0] - self.border_margin: - hor_growth = 'left' - # otherwise, let's pick the one with more space and adjust ourselves - else: - # if there's more space to the right: - if Window.width - c[0] >= c[0]: - hor_growth = 'right' - target_width = Window.width - c[0] - self.border_margin - # if there's more space to the left: - else: - hor_growth = 'left' - target_width = c[0] - self.border_margin - - if ver_growth == 'down': - tar_y = c[1] - target_height - else: # should always be 'up' - tar_y = c[1] - - if hor_growth == 'right': - tar_x = c[0] - else: # should always be 'left' - tar_x = c[0] - target_width - anim = Animation(x=tar_x, y=tar_y, - width=target_width, height=target_height, - duration=.3, transition='out_quint') - menu = self.ids['md_menu'] - menu.pos = c - anim.start(menu) - - def on_touch_down(self, touch): - if not self.ids['md_menu'].collide_point(*touch.pos): - self.dismiss() - return True - super(MDDropdownMenu, self).on_touch_down(touch) - return True - - def on_touch_move(self, touch): - super(MDDropdownMenu, self).on_touch_move(touch) - return True - - def on_touch_up(self, touch): - super(MDDropdownMenu, self).on_touch_up(touch) - return True - - def dismiss(self): - Window.remove_widget(self) diff --git a/src/kivymd/navigationdrawer.py b/src/kivymd/navigationdrawer.py deleted file mode 100644 index 42aa9a62..00000000 --- a/src/kivymd/navigationdrawer.py +++ /dev/null @@ -1,76 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.animation import Animation -from kivy.lang import Builder -from kivy.properties import StringProperty, ObjectProperty -from kivymd.elevationbehavior import ElevationBehavior -from kivymd.icon_definitions import md_icons -from kivymd.label import MDLabel -from kivymd.list import OneLineIconListItem, ILeftBody, BaseListItem -from kivymd.slidingpanel import SlidingPanel -from kivymd.theming import ThemableBehavior - -Builder.load_string(''' - - canvas: - Color: - rgba: root.theme_cls.divider_color - Line: - points: self.x, self.y, self.x+self.width,self.y - - - _list: list - elevation: 0 - canvas: - Color: - rgba: root.theme_cls.bg_light - Rectangle: - size: root.size - pos: root.pos - NavDrawerToolbar: - title: root.title - opposite_colors: False - title_theme_color: 'Secondary' - background_color: root.theme_cls.bg_light - elevation: 0 - ScrollView: - do_scroll_x: False - MDList: - id: ml - id: list - - - NDIconLabel: - id: _icon - font_style: 'Icon' - theme_text_color: 'Secondary' -''') - - -class NavigationDrawer(SlidingPanel, ThemableBehavior, ElevationBehavior): - title = StringProperty() - - _list = ObjectProperty() - - def add_widget(self, widget, index=0): - if issubclass(widget.__class__, BaseListItem): - self._list.add_widget(widget, index) - widget.bind(on_release=lambda x: self.toggle()) - else: - super(NavigationDrawer, self).add_widget(widget, index) - - def _get_main_animation(self, duration, t, x, is_closing): - a = super(NavigationDrawer, self)._get_main_animation(duration, t, x, - is_closing) - a &= Animation(elevation=0 if is_closing else 5, t=t, duration=duration) - return a - - -class NDIconLabel(ILeftBody, MDLabel): - pass - - -class NavigationDrawerIconButton(OneLineIconListItem): - icon = StringProperty() - - def on_icon(self, instance, value): - self.ids['_icon'].text = u"{}".format(md_icons[value]) diff --git a/src/kivymd/progressbar.py b/src/kivymd/progressbar.py deleted file mode 100644 index 6d3a2ca8..00000000 --- a/src/kivymd/progressbar.py +++ /dev/null @@ -1,79 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.properties import ListProperty, OptionProperty, BooleanProperty -from kivy.utils import get_color_from_hex -from kivymd.color_definitions import colors -from kivymd.theming import ThemableBehavior -from kivy.uix.progressbar import ProgressBar - - -Builder.load_string(''' -: - canvas: - Clear - Color: - rgba: self.theme_cls.divider_color - Rectangle: - size: (self.width , dp(4)) if self.orientation == 'horizontal' else (dp(4),self.height) - pos: (self.x, self.center_y - dp(4)) if self.orientation == 'horizontal' \ - else (self.center_x - dp(4),self.y) - - - Color: - rgba: self.theme_cls.primary_color - Rectangle: - size: (self.width*self.value_normalized, sp(4)) if self.orientation == 'horizontal' else (sp(4), \ - self.height*self.value_normalized) - pos: (self.width*(1-self.value_normalized)+self.x if self.reversed else self.x, self.center_y - dp(4)) \ - if self.orientation == 'horizontal' else \ - (self.center_x - dp(4),self.height*(1-self.value_normalized)+self.y if self.reversed else self.y) - -''') - - -class MDProgressBar(ThemableBehavior, ProgressBar): - reversed = BooleanProperty(False) - ''' Reverse the direction the progressbar moves. ''' - - orientation = OptionProperty('horizontal', options=['horizontal', 'vertical']) - ''' Orientation of progressbar''' - - -if __name__ == '__main__': - from kivy.app import App - from kivymd.theming import ThemeManager - - class ProgressBarApp(App): - theme_cls = ThemeManager() - - def build(self): - return Builder.load_string("""#:import MDSlider kivymd.slider.MDSlider -BoxLayout: - orientation:'vertical' - padding: '8dp' - MDSlider: - id:slider - min:0 - max:100 - value: 40 - - MDProgressBar: - value: slider.value - MDProgressBar: - reversed: True - value: slider.value - BoxLayout: - MDProgressBar: - orientation:"vertical" - reversed: True - value: slider.value - - MDProgressBar: - orientation:"vertical" - value: slider.value - -""") - - - ProgressBarApp().run() diff --git a/src/kivymd/ripplebehavior.py b/src/kivymd/ripplebehavior.py deleted file mode 100644 index 21dd3463..00000000 --- a/src/kivymd/ripplebehavior.py +++ /dev/null @@ -1,169 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.properties import ListProperty, NumericProperty, StringProperty, \ - BooleanProperty -from kivy.animation import Animation -from kivy.graphics import Color, Ellipse, StencilPush, StencilPop, \ - StencilUse, StencilUnUse, Rectangle - - -class CommonRipple(object): - ripple_rad = NumericProperty() - ripple_rad_default = NumericProperty(1) - ripple_post = ListProperty() - ripple_color = ListProperty() - ripple_alpha = NumericProperty(.5) - ripple_scale = NumericProperty(None) - ripple_duration_in_fast = NumericProperty(.3) - # FIXME: These speeds should be calculated based on widget size in dp - ripple_duration_in_slow = NumericProperty(2) - ripple_duration_out = NumericProperty(.3) - ripple_func_in = StringProperty('out_quad') - ripple_func_out = StringProperty('out_quad') - - doing_ripple = BooleanProperty(False) - finishing_ripple = BooleanProperty(False) - fading_out = BooleanProperty(False) - - def on_touch_down(self, touch): - if touch.is_mouse_scrolling: - return False - if not self.collide_point(touch.x, touch.y): - return False - - if not self.disabled: - if self.doing_ripple: - Animation.cancel_all(self, 'ripple_rad', 'ripple_color', - 'rect_color') - self.anim_complete() - self.ripple_rad = self.ripple_rad_default - self.ripple_pos = (touch.x, touch.y) - - if self.ripple_color != []: - pass - elif hasattr(self, 'theme_cls'): - self.ripple_color = self.theme_cls.ripple_color - else: - # If no theme, set Grey 300 - self.ripple_color = [0.8784313725490196, 0.8784313725490196, - 0.8784313725490196, self.ripple_alpha] - self.ripple_color[3] = self.ripple_alpha - - self.lay_canvas_instructions() - self.finish_rad = max(self.width, self.height) * self.ripple_scale - self.start_ripple() - return super(CommonRipple, self).on_touch_down(touch) - - def lay_canvas_instructions(self): - raise NotImplementedError - - def on_touch_move(self, touch, *args): - if not self.collide_point(touch.x, touch.y): - if not self.finishing_ripple and self.doing_ripple: - self.finish_ripple() - return super(CommonRipple, self).on_touch_move(touch, *args) - - def on_touch_up(self, touch): - if self.collide_point(touch.x, touch.y) and self.doing_ripple: - self.finish_ripple() - return super(CommonRipple, self).on_touch_up(touch) - - def start_ripple(self): - if not self.doing_ripple: - anim = Animation( - ripple_rad=self.finish_rad, - t='linear', - duration=self.ripple_duration_in_slow) - anim.bind(on_complete=self.fade_out) - self.doing_ripple = True - anim.start(self) - - def _set_ellipse(self, instance, value): - self.ellipse.size = (self.ripple_rad, self.ripple_rad) - - # Adjust ellipse pos here - - def _set_color(self, instance, value): - self.col_instruction.a = value[3] - - def finish_ripple(self): - if self.doing_ripple and not self.finishing_ripple: - Animation.cancel_all(self, 'ripple_rad') - anim = Animation(ripple_rad=self.finish_rad, - t=self.ripple_func_in, - duration=self.ripple_duration_in_fast) - anim.bind(on_complete=self.fade_out) - self.finishing_ripple = True - anim.start(self) - - def fade_out(self, *args): - rc = self.ripple_color - if not self.fading_out: - Animation.cancel_all(self, 'ripple_color') - anim = Animation(ripple_color=[rc[0], rc[1], rc[2], 0.], - t=self.ripple_func_out, - duration=self.ripple_duration_out) - anim.bind(on_complete=self.anim_complete) - self.fading_out = True - anim.start(self) - - def anim_complete(self, *args): - self.doing_ripple = False - self.finishing_ripple = False - self.fading_out = False - self.canvas.after.clear() - - -class RectangularRippleBehavior(CommonRipple): - ripple_scale = NumericProperty(2.75) - - def lay_canvas_instructions(self): - with self.canvas.after: - StencilPush() - Rectangle(pos=self.pos, size=self.size) - StencilUse() - self.col_instruction = Color(rgba=self.ripple_color) - self.ellipse = \ - Ellipse(size=(self.ripple_rad, self.ripple_rad), - pos=(self.ripple_pos[0] - self.ripple_rad / 2., - self.ripple_pos[1] - self.ripple_rad / 2.)) - StencilUnUse() - Rectangle(pos=self.pos, size=self.size) - StencilPop() - self.bind(ripple_color=self._set_color, - ripple_rad=self._set_ellipse) - - def _set_ellipse(self, instance, value): - super(RectangularRippleBehavior, self)._set_ellipse(instance, value) - self.ellipse.pos = (self.ripple_pos[0] - self.ripple_rad / 2., - self.ripple_pos[1] - self.ripple_rad / 2.) - - -class CircularRippleBehavior(CommonRipple): - ripple_scale = NumericProperty(1) - - def lay_canvas_instructions(self): - with self.canvas.after: - StencilPush() - self.stencil = Ellipse(size=(self.width * self.ripple_scale, - self.height * self.ripple_scale), - pos=(self.center_x - ( - self.width * self.ripple_scale) / 2, - self.center_y - ( - self.height * self.ripple_scale) / 2)) - StencilUse() - self.col_instruction = Color(rgba=self.ripple_color) - self.ellipse = Ellipse(size=(self.ripple_rad, self.ripple_rad), - pos=(self.center_x - self.ripple_rad / 2., - self.center_y - self.ripple_rad / 2.)) - StencilUnUse() - Ellipse(pos=self.pos, size=self.size) - StencilPop() - self.bind(ripple_color=self._set_color, - ripple_rad=self._set_ellipse) - - def _set_ellipse(self, instance, value): - super(CircularRippleBehavior, self)._set_ellipse(instance, value) - if self.ellipse.size[0] > self.width * .6 and not self.fading_out: - self.fade_out() - self.ellipse.pos = (self.center_x - self.ripple_rad / 2., - self.center_y - self.ripple_rad / 2.) diff --git a/src/kivymd/selectioncontrols.py b/src/kivymd/selectioncontrols.py deleted file mode 100644 index b918428a..00000000 --- a/src/kivymd/selectioncontrols.py +++ /dev/null @@ -1,240 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.properties import StringProperty, ListProperty, NumericProperty -from kivy.uix.behaviors import ToggleButtonBehavior -from kivy.uix.label import Label -from kivy.uix.floatlayout import FloatLayout -from kivy.properties import AliasProperty, BooleanProperty -from kivy.metrics import dp, sp -from kivy.animation import Animation -from kivy.utils import get_color_from_hex -from kivymd.color_definitions import colors -from kivymd.icon_definitions import md_icons -from kivymd.theming import ThemableBehavior -from kivymd.elevationbehavior import RoundElevationBehavior -from kivymd.ripplebehavior import CircularRippleBehavior -from kivy.uix.behaviors import ButtonBehavior -from kivy.uix.widget import Widget - -Builder.load_string(''' -: - canvas: - Clear - Color: - rgba: self.color - Rectangle: - texture: self.texture - size: self.texture_size - pos: int(self.center_x - self.texture_size[0] / 2.), int(self.center_y - self.texture_size[1] / 2.) - - text: self._radio_icon if self.group else self._checkbox_icon - font_name: 'Icons' - font_size: sp(24) - color: self.theme_cls.primary_color if self.active else self.theme_cls.secondary_text_color - halign: 'center' - valign: 'middle' - -: - color: 1, 1, 1, 1 - canvas: - Color: - rgba: self.color - Ellipse: - size: self.size - pos: self.pos - -: - canvas.before: - Color: - rgba: self._track_color_disabled if self.disabled else \ - (self._track_color_active if self.active else self._track_color_normal) - Ellipse: - size: dp(16), dp(16) - pos: self.x, self.center_y - dp(8) - angle_start: 180 - angle_end: 360 - Rectangle: - size: self.width - dp(16), dp(16) - pos: self.x + dp(8), self.center_y - dp(8) - Ellipse: - size: dp(16), dp(16) - pos: self.right - dp(16), self.center_y - dp(8) - angle_start: 0 - angle_end: 180 - on_release: thumb.trigger_action() - - Thumb: - id: thumb - size_hint: None, None - size: dp(24), dp(24) - pos: root._thumb_pos - color: root.thumb_color_disabled if root.disabled else \ - (root.thumb_color_down if root.active else root.thumb_color) - elevation: 4 if root.active else 2 - on_release: setattr(root, 'active', not root.active) -''') - - -class MDCheckbox(ThemableBehavior, CircularRippleBehavior, - ToggleButtonBehavior, Label): - active = BooleanProperty(False) - - _checkbox_icon = StringProperty( - u"{}".format(md_icons['square-o'])) - _radio_icon = StringProperty(u"{}".format(md_icons['circle-o'])) - _icon_active = StringProperty(u"{}".format(md_icons['check-square'])) - - def __init__(self, **kwargs): - super(MDCheckbox, self).__init__(**kwargs) - self.register_event_type('on_active') - self.check_anim_out = Animation(font_size=0, duration=.1, t='out_quad') - self.check_anim_in = Animation(font_size=sp(24), duration=.1, - t='out_quad') - self.check_anim_out.bind( - on_complete=lambda *x: self.check_anim_in.start(self)) - - def on_state(self, *args): - if self.state == 'down': - self.check_anim_in.cancel(self) - self.check_anim_out.start(self) - self._radio_icon = u"{}".format(md_icons['dot-circle']) - self._checkbox_icon = u"{}".format(md_icons['check-square']) - self.active = True - else: - self.check_anim_in.cancel(self) - self.check_anim_out.start(self) - self._radio_icon = u"{}".format(md_icons['circle-o']) - self._checkbox_icon = u"{}".format( - md_icons['square-o']) - self.active = False - - def on_active(self, instance, value): - self.state = 'down' if value else 'normal' - - -class Thumb(RoundElevationBehavior, CircularRippleBehavior, ButtonBehavior, - Widget): - ripple_scale = NumericProperty(2) - - def _set_ellipse(self, instance, value): - self.ellipse.size = (self.ripple_rad, self.ripple_rad) - if self.ellipse.size[0] > self.width * 1.5 and not self.fading_out: - self.fade_out() - self.ellipse.pos = (self.center_x - self.ripple_rad / 2., - self.center_y - self.ripple_rad / 2.) - self.stencil.pos = ( - self.center_x - (self.width * self.ripple_scale) / 2, - self.center_y - (self.height * self.ripple_scale) / 2) - - -class MDSwitch(ThemableBehavior, ButtonBehavior, FloatLayout): - active = BooleanProperty(False) - - _thumb_color = ListProperty(get_color_from_hex(colors['Grey']['50'])) - - def _get_thumb_color(self): - return self._thumb_color - - def _set_thumb_color(self, color, alpha=None): - if len(color) == 2: - self._thumb_color = get_color_from_hex(colors[color[0]][color[1]]) - if alpha: - self._thumb_color[3] = alpha - elif len(color) == 4: - self._thumb_color = color - - thumb_color = AliasProperty(_get_thumb_color, _set_thumb_color, - bind=['_thumb_color']) - - _thumb_color_down = ListProperty([1, 1, 1, 1]) - - def _get_thumb_color_down(self): - return self._thumb_color_down - - def _set_thumb_color_down(self, color, alpha=None): - if len(color) == 2: - self._thumb_color_down = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._thumb_color_down[3] = alpha - else: - self._thumb_color_down[3] = 1 - elif len(color) == 4: - self._thumb_color_down = color - - thumb_color_down = AliasProperty(_get_thumb_color_down, - _set_thumb_color_down, - bind=['_thumb_color_down']) - - _thumb_color_disabled = ListProperty( - get_color_from_hex(colors['Grey']['400'])) - - def _get_thumb_color_disabled(self): - return self._thumb_color_disabled - - def _set_thumb_color_disabled(self, color, alpha=None): - if len(color) == 2: - self._thumb_color_disabled = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._thumb_color_disabled[3] = alpha - elif len(color) == 4: - self._thumb_color_disabled = color - - thumb_color_down = AliasProperty(_get_thumb_color_disabled, - _set_thumb_color_disabled, - bind=['_thumb_color_disabled']) - - _track_color_active = ListProperty() - _track_color_normal = ListProperty() - _track_color_disabled = ListProperty() - _thumb_pos = ListProperty([0, 0]) - - def __init__(self, **kwargs): - super(MDSwitch, self).__init__(**kwargs) - self.theme_cls.bind(theme_style=self._set_colors, - primary_color=self._set_colors, - primary_palette=self._set_colors) - self._set_colors() - - def _set_colors(self, *args): - self._track_color_normal = self.theme_cls.disabled_hint_text_color - if self.theme_cls.theme_style == 'Dark': - self._track_color_active = self.theme_cls.primary_color - self._track_color_active[3] = .5 - self._track_color_disabled = get_color_from_hex('FFFFFF') - self._track_color_disabled[3] = .1 - self.thumb_color = get_color_from_hex(colors['Grey']['400']) - self.thumb_color_down = get_color_from_hex( - colors[self.theme_cls.primary_palette]['200']) - self.thumb_color_disabled = get_color_from_hex( - colors['Grey']['800']) - else: - self._track_color_active = get_color_from_hex( - colors[self.theme_cls.primary_palette]['200']) - self._track_color_active[3] = .5 - self._track_color_disabled = self.theme_cls.disabled_hint_text_color - self.thumb_color_down = self.theme_cls.primary_color - - def on_pos(self, *args): - if self.active: - self._thumb_pos = (self.right - dp(12), self.center_y - dp(12)) - else: - self._thumb_pos = (self.x - dp(12), self.center_y - dp(12)) - self.bind(active=self._update_thumb) - - def _update_thumb(self, *args): - if self.active: - Animation.cancel_all(self, '_thumb_pos') - anim = Animation( - _thumb_pos=(self.right - dp(12), self.center_y - dp(12)), - duration=.2, - t='out_quad') - else: - Animation.cancel_all(self, '_thumb_pos') - anim = Animation( - _thumb_pos=(self.x - dp(12), self.center_y - dp(12)), - duration=.2, - t='out_quad') - anim.start(self) diff --git a/src/kivymd/slider.py b/src/kivymd/slider.py deleted file mode 100644 index 1166bea7..00000000 --- a/src/kivymd/slider.py +++ /dev/null @@ -1,247 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.properties import StringProperty, ListProperty, NumericProperty,AliasProperty, BooleanProperty -from kivy.utils import get_color_from_hex -from kivy.metrics import dp, sp -from kivymd.color_definitions import colors -from kivymd.theming import ThemableBehavior -from kivy.uix.slider import Slider - - -Builder.load_string(''' -#:import Thumb kivymd.selectioncontrols.Thumb - -: - id: slider - canvas: - Clear - Color: - rgba: self._track_color_disabled if self.disabled else (self._track_color_active if self.active \ - else self._track_color_normal) - Rectangle: - size: (self.width - self.padding*2 - self._offset[0], dp(4)) if self.orientation == 'horizontal' \ - else (dp(4),self.height - self.padding*2 - self._offset[1]) - pos: (self.x + self.padding + self._offset[0], self.center_y - dp(4)) \ - if self.orientation == 'horizontal' else (self.center_x - dp(4),self.y + self.padding + self._offset[1]) - - # If 0 draw circle - Color: - rgba: [0,0,0,0] if not self._is_off else (self._track_color_disabled if self.disabled \ - else (self._track_color_active if self.active else self._track_color_normal)) - Line: - width: 2 - circle: (self.x+self.padding+dp(3),self.center_y-dp(2),8 if self.active else 6 ) \ - if self.orientation == 'horizontal' else (self.center_x-dp(2),self.y+self.padding+dp(3),8 \ - if self.active else 6) - - Color: - rgba: [0,0,0,0] if self._is_off \ - else (self.thumb_color_down if not self.disabled else self._track_color_disabled) - Rectangle: - size: ((self.width-self.padding*2)*self.value_normalized, sp(4)) \ - if slider.orientation == 'horizontal' else (sp(4), (self.height-self.padding*2)*self.value_normalized) - pos: (self.x + self.padding, self.center_y - dp(4)) if self.orientation == 'horizontal' \ - else (self.center_x - dp(4),self.y + self.padding) - Thumb: - id: thumb - size_hint: None, None - size: (dp(12), dp(12)) if root.disabled else ((dp(24), dp(24)) if root.active else (dp(16),dp(16))) - pos: (slider.value_pos[0] - dp(8), slider.center_y - thumb.height/2 - dp(2)) \ - if slider.orientation == 'horizontal' \ - else (slider.center_x - thumb.width/2 - dp(2), slider.value_pos[1]-dp(8)) - color: [0,0,0,0] if slider._is_off else (root._track_color_disabled if root.disabled \ - else root.thumb_color_down) - elevation: 0 if slider._is_off else (4 if root.active else 2) - -''') - - -class MDSlider(ThemableBehavior, Slider): - # If the slider is clicked - active = BooleanProperty(False) - - # Show the "off" ring when set to minimum value - show_off = BooleanProperty(True) - - # Internal state of ring - _is_off = BooleanProperty(False) - - # Internal adjustment to reposition sliders for ring - _offset = ListProperty((0, 0)) - - _thumb_color = ListProperty(get_color_from_hex(colors['Grey']['50'])) - - def _get_thumb_color(self): - return self._thumb_color - - def _set_thumb_color(self, color, alpha=None): - if len(color) == 2: - self._thumb_color = get_color_from_hex(colors[color[0]][color[1]]) - if alpha: - self._thumb_color[3] = alpha - elif len(color) == 4: - self._thumb_color = color - - thumb_color = AliasProperty(_get_thumb_color, _set_thumb_color, - bind=['_thumb_color']) - - _thumb_color_down = ListProperty([1, 1, 1, 1]) - - def _get_thumb_color_down(self): - return self._thumb_color_down - - def _set_thumb_color_down(self, color, alpha=None): - if len(color) == 2: - self._thumb_color_down = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._thumb_color_down[3] = alpha - else: - self._thumb_color_down[3] = 1 - elif len(color) == 4: - self._thumb_color_down = color - - thumb_color_down = AliasProperty(_get_thumb_color_down, - _set_thumb_color_down, - bind=['_thumb_color_down']) - - _thumb_color_disabled = ListProperty( - get_color_from_hex(colors['Grey']['400'])) - - def _get_thumb_color_disabled(self): - return self._thumb_color_disabled - - def _set_thumb_color_disabled(self, color, alpha=None): - if len(color) == 2: - self._thumb_color_disabled = get_color_from_hex( - colors[color[0]][color[1]]) - if alpha: - self._thumb_color_disabled[3] = alpha - elif len(color) == 4: - self._thumb_color_disabled = color - - thumb_color_down = AliasProperty(_get_thumb_color_disabled, - _set_thumb_color_disabled, - bind=['_thumb_color_disabled']) - - _track_color_active = ListProperty() - _track_color_normal = ListProperty() - _track_color_disabled = ListProperty() - _thumb_pos = ListProperty([0, 0]) - - def __init__(self, **kwargs): - super(MDSlider, self).__init__(**kwargs) - self.theme_cls.bind(theme_style=self._set_colors, - primary_color=self._set_colors, - primary_palette=self._set_colors) - self._set_colors() - - def _set_colors(self, *args): - if self.theme_cls.theme_style == 'Dark': - self._track_color_normal = get_color_from_hex('FFFFFF') - self._track_color_normal[3] = .3 - self._track_color_active = self._track_color_normal - self._track_color_disabled = self._track_color_normal - self.thumb_color = get_color_from_hex(colors['Grey']['400']) - self.thumb_color_down = get_color_from_hex( - colors[self.theme_cls.primary_palette]['200']) - self.thumb_color_disabled = get_color_from_hex( - colors['Grey']['800']) - else: - self._track_color_normal = get_color_from_hex('000000') - self._track_color_normal[3] = 0.26 - self._track_color_active = get_color_from_hex('000000') - self._track_color_active[3] = 0.38 - self._track_color_disabled = get_color_from_hex('000000') - self._track_color_disabled[3] = 0.26 - self.thumb_color_down = self.theme_cls.primary_color - - def on_value_normalized(self, *args): - """ When the value == min set it to "off" state and make slider a ring """ - self._update_is_off() - - def on_show_off(self, *args): - self._update_is_off() - - def _update_is_off(self): - self._is_off = self.show_off and (self.value_normalized == 0) - - def on__is_off(self, *args): - self._update_offset() - - def on_active(self, *args): - self._update_offset() - - def _update_offset(self): - """ Offset is used to shift the sliders so the background color - shows through the off circle. - """ - d = 2 if self.active else 0 - self._offset = (dp(11+d), dp(11+d)) if self._is_off else (0, 0) - - def on_touch_down(self, touch): - if super(MDSlider, self).on_touch_down(touch): - self.active = True - - def on_touch_up(self,touch): - if super(MDSlider, self).on_touch_up(touch): - self.active = False -# thumb = self.ids['thumb'] -# if thumb.collide_point(*touch.pos): -# thumb.on_touch_down(touch) -# thumb.on_touch_up(touch) - -if __name__ == '__main__': - from kivy.app import App - from kivymd.theming import ThemeManager - - class SliderApp(App): - theme_cls = ThemeManager() - - def build(self): - return Builder.load_string(""" -BoxLayout: - orientation:'vertical' - BoxLayout: - size_hint_y:None - height: '48dp' - Label: - text:"Toggle disabled" - color: [0,0,0,1] - CheckBox: - on_press: slider.disabled = not slider.disabled - BoxLayout: - size_hint_y:None - height: '48dp' - Label: - text:"Toggle active" - color: [0,0,0,1] - CheckBox: - on_press: slider.active = not slider.active - BoxLayout: - size_hint_y:None - height: '48dp' - Label: - text:"Toggle show off" - color: [0,0,0,1] - CheckBox: - on_press: slider.show_off = not slider.show_off - - MDSlider: - id:slider - min:0 - max:100 - value: 40 - - MDSlider: - id:slider2 - orientation:"vertical" - min:0 - max:100 - value: 40 - -""") - - - SliderApp().run() diff --git a/src/kivymd/slidingpanel.py b/src/kivymd/slidingpanel.py deleted file mode 100644 index b818505a..00000000 --- a/src/kivymd/slidingpanel.py +++ /dev/null @@ -1,92 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.animation import Animation -from kivy.clock import Clock -from kivy.core.window import Window -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.properties import OptionProperty, NumericProperty, StringProperty, \ - BooleanProperty, ListProperty -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.relativelayout import RelativeLayout - -Builder.load_string(""" -#: import Window kivy.core.window.Window - - orientation: 'vertical' - size_hint_x: None - width: dp(320) - x: -1 * self.width if self.side == 'left' else Window.width - - - canvas: - Color: - rgba: root.color - Rectangle: - size: root.size -""") - - -class PanelShadow(BoxLayout): - color = ListProperty([0, 0, 0, 0]) - - -class SlidingPanel(BoxLayout): - anim_length_close = NumericProperty(0.3) - anim_length_open = NumericProperty(0.3) - animation_t_open = StringProperty('out_sine') - animation_t_close = StringProperty('out_sine') - side = OptionProperty('left', options=['left', 'right']) - - _open = False - - def __init__(self, **kwargs): - super(SlidingPanel, self).__init__(**kwargs) - self.shadow = PanelShadow() - Clock.schedule_once(lambda x: Window.add_widget(self.shadow,89), 0) - Clock.schedule_once(lambda x: Window.add_widget(self,90), 0) - - def toggle(self): - Animation.stop_all(self, 'x') - Animation.stop_all(self.shadow, 'color') - if self._open: - if self.side == 'left': - target_x = -1 * self.width - else: - target_x = Window.width - - sh_anim = Animation(duration=self.anim_length_open, - t=self.animation_t_open, - color=[0, 0, 0, 0]) - sh_anim.start(self.shadow) - self._get_main_animation(duration=self.anim_length_close, - t=self.animation_t_close, - x=target_x, - is_closing=True).start(self) - self._open = False - else: - if self.side == 'left': - target_x = 0 - else: - target_x = Window.width - self.width - Animation(duration=self.anim_length_open, t=self.animation_t_open, - color=[0, 0, 0, 0.5]).start(self.shadow) - self._get_main_animation(duration=self.anim_length_open, - t=self.animation_t_open, - x=target_x, - is_closing=False).start(self) - self._open = True - - def _get_main_animation(self, duration, t, x, is_closing): - return Animation(duration=duration, t=t, x=x) - - def on_touch_down(self, touch): - # Prevents touch events from propagating to anything below the widget. - super(SlidingPanel, self).on_touch_down(touch) - if self.collide_point(*touch.pos) or self._open: - return True - - def on_touch_up(self, touch): - if not self.collide_point(touch.x, touch.y) and self._open: - self.toggle() - return True - super(SlidingPanel, self).on_touch_up(touch) diff --git a/src/kivymd/snackbar.py b/src/kivymd/snackbar.py deleted file mode 100644 index e0ac70e8..00000000 --- a/src/kivymd/snackbar.py +++ /dev/null @@ -1,115 +0,0 @@ -# -*- coding: utf-8 -*- -from collections import deque -from kivy.animation import Animation -from kivy.clock import Clock -from kivy.core.window import Window -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.properties import ObjectProperty, StringProperty, NumericProperty -from kivy.uix.relativelayout import RelativeLayout -from kivymd.material_resources import DEVICE_TYPE - -Builder.load_string(''' -#:import Window kivy.core.window.Window -#:import get_color_from_hex kivy.utils.get_color_from_hex -#:import MDFlatButton kivymd.button.MDFlatButton -#:import MDLabel kivymd.label.MDLabel -#:import DEVICE_TYPE kivymd.material_resources.DEVICE_TYPE -<_SnackbarWidget> - canvas: - Color: - rgb: get_color_from_hex('323232') - Rectangle: - size: self.size - size_hint_y: None - size_hint_x: 1 if DEVICE_TYPE == 'mobile' else None - height: dp(48) if _label.texture_size[1] < dp(30) else dp(80) - width: dp(24) + _label.width + _spacer.width + root.padding_right if root.button_text == '' else dp(24) + \ - _label.width + _spacer.width + _button.width + root.padding_right - top: 0 - x: 0 if DEVICE_TYPE == 'mobile' else Window.width/2 - self.width/2 - BoxLayout: - width: Window.width - root.padding_right - _spacer.width - dp(24) if DEVICE_TYPE == 'mobile' and \ - root.button_text == '' else Window.width - root.padding_right - _button.width - _spacer.width - dp(24) \ - if DEVICE_TYPE == 'mobile' else _label.texture_size[0] if (dp(568) - root.padding_right - _button.width - \ - _spacer.width - _label.texture_size[0] - dp(24)) >= 0 else (dp(568) - root.padding_right - _button.width - \ - _spacer.width - dp(24)) - size_hint_x: None - x: dp(24) - MDLabel: - id: _label - text: root.text - size: self.texture_size - BoxLayout: - id: _spacer - size_hint_x: None - x: _label.right - width: 0 - MDFlatButton: - id: _button - text: root.button_text - size_hint_x: None - x: _spacer.right if root.button_text != '' else root.right - center_y: root.height/2 - on_release: root.button_callback() -''') - - -class _SnackbarWidget(RelativeLayout): - text = StringProperty() - button_text = StringProperty() - button_callback = ObjectProperty() - duration = NumericProperty() - padding_right = NumericProperty(dp(24)) - - def __init__(self, text, duration, button_text='', button_callback=None, - **kwargs): - super(_SnackbarWidget, self).__init__(**kwargs) - self.text = text - self.button_text = button_text - self.button_callback = button_callback - self.duration = duration - self.ids['_label'].text_size = (None, None) - - def begin(self): - if self.button_text == '': - self.remove_widget(self.ids['_button']) - else: - self.ids['_spacer'].width = dp(16) if \ - DEVICE_TYPE == "mobile" else dp(40) - self.padding_right = dp(16) - Window.add_widget(self) - anim = Animation(y=0, duration=.3, t='out_quad') - anim.start(self) - Clock.schedule_once(lambda dt: self.die(), self.duration) - - def die(self): - anim = Animation(top=0, duration=.3, t='out_quad') - anim.bind(on_complete=lambda *args: _play_next(self)) - anim.bind(on_complete=lambda *args: Window.remove_widget(self)) - anim.start(self) - - -queue = deque() -playing = False - - -def make(text, button_text=None, button_callback=None, duration=3): - if button_text is not None and button_callback is not None: - queue.append(_SnackbarWidget(text=text, - button_text=button_text, - button_callback=button_callback, - duration=duration)) - else: - queue.append(_SnackbarWidget(text=text, - duration=duration)) - _play_next() - - -def _play_next(dying_widget=None): - global playing - if (dying_widget or not playing) and len(queue) > 0: - playing = True - queue.popleft().begin() - elif len(queue) == 0: - playing = False diff --git a/src/kivymd/spinner.py b/src/kivymd/spinner.py deleted file mode 100644 index 238062db..00000000 --- a/src/kivymd/spinner.py +++ /dev/null @@ -1,149 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.uix.widget import Widget -from kivy.properties import NumericProperty, ListProperty, BooleanProperty -from kivy.animation import Animation -from kivymd.theming import ThemableBehavior -from kivy.clock import Clock - -Builder.load_string(''' -: - canvas.before: - PushMatrix - Rotate: - angle: self._rotation_angle - origin: self.center - canvas: - Color: - rgba: self.color - a: self._alpha - Line: - circle: self.center_x, self.center_y, self.width / 2, \ - self._angle_start, self._angle_end - cap: 'square' - width: dp(2) - canvas.after: - PopMatrix - -''') - - -class MDSpinner(ThemableBehavior, Widget): - """:class:`MDSpinner` is an implementation of the circular progress - indicator in Google's Material Design. - - It can be used either as an indeterminate indicator that loops while - the user waits for something to happen, or as a determinate indicator. - - Set :attr:`determinate` to **True** to activate determinate mode, and - :attr:`determinate_time` to set the duration of the animation. - """ - - determinate = BooleanProperty(False) - """:attr:`determinate` is a :class:`~kivy.properties.BooleanProperty` and - defaults to False - """ - - determinate_time = NumericProperty(2) - """:attr:`determinate_time` is a :class:`~kivy.properties.NumericProperty` - and defaults to 2 - """ - - active = BooleanProperty(True) - """Use :attr:`active` to start or stop the spinner. - - :attr:`active` is a :class:`~kivy.properties.BooleanProperty` and - defaults to True - """ - - color = ListProperty([]) - """:attr:`color` is a :class:`~kivy.properties.ListProperty` and - defaults to 'self.theme_cls.primary_color' - """ - - _alpha = NumericProperty(0) - _rotation_angle = NumericProperty(360) - _angle_start = NumericProperty(0) - _angle_end = NumericProperty(8) - - def __init__(self, **kwargs): - super(MDSpinner, self).__init__(**kwargs) - Clock.schedule_interval(self._update_color, 5) - self.color = self.theme_cls.primary_color - self._alpha_anim_in = Animation(_alpha=1, duration=.8, t='out_quad') - self._alpha_anim_out = Animation(_alpha=0, duration=.3, t='out_quad') - self._alpha_anim_out.bind(on_complete=self._reset) - - if self.determinate: - self._start_determinate() - else: - self._start_loop() - - def _update_color(self, *args): - self.color = self.theme_cls.primary_color - - def _start_determinate(self, *args): - self._alpha_anim_in.start(self) - - _rot_anim = Animation(_rotation_angle=0, - duration=self.determinate_time * .7, - t='out_quad') - _rot_anim.start(self) - - _angle_start_anim = Animation(_angle_end=360, - duration=self.determinate_time, - t='in_out_quad') - _angle_start_anim.bind(on_complete=lambda *x: \ - self._alpha_anim_out.start(self)) - - _angle_start_anim.start(self) - - def _start_loop(self, *args): - if self._alpha == 0: - _rot_anim = Animation(_rotation_angle=0, - duration=2, - t='linear') - _rot_anim.start(self) - - self._alpha = 1 - self._alpha_anim_in.start(self) - _angle_start_anim = Animation(_angle_end=self._angle_end + 270, - duration=.6, - t='in_out_cubic') - _angle_start_anim.bind(on_complete=self._anim_back) - _angle_start_anim.start(self) - - def _anim_back(self, *args): - _angle_back_anim = Animation(_angle_start=self._angle_end - 8, - duration=.6, - t='in_out_cubic') - _angle_back_anim.bind(on_complete=self._start_loop) - - _angle_back_anim.start(self) - - def on__rotation_angle(self, *args): - if self._rotation_angle == 0: - self._rotation_angle = 360 - if not self.determinate: - _rot_anim = Animation(_rotation_angle=0, - duration=2) - _rot_anim.start(self) - - def _reset(self, *args): - Animation.cancel_all(self, '_angle_start', '_rotation_angle', - '_angle_end', '_alpha') - self._angle_start = 0 - self._angle_end = 8 - self._rotation_angle = 360 - self._alpha = 0 - self.active = False - - def on_active(self, *args): - if not self.active: - self._reset() - else: - if self.determinate: - self._start_determinate() - else: - self._start_loop() diff --git a/src/kivymd/tabs.py b/src/kivymd/tabs.py deleted file mode 100644 index c09f21c2..00000000 --- a/src/kivymd/tabs.py +++ /dev/null @@ -1,303 +0,0 @@ -# Created on Jul 8, 2016 -# -# The default kivy tab implementation seems like a stupid design to me. The -# ScreenManager is much better. -# -# @author: jrm - -from kivy.properties import StringProperty, DictProperty, ListProperty, \ - ObjectProperty, OptionProperty, BoundedNumericProperty -from kivy.uix.screenmanager import Screen -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.uix.boxlayout import BoxLayout -from kivymd.theming import ThemableBehavior -from kivymd.backgroundcolorbehavior import BackgroundColorBehavior -from kivymd.button import MDFlatButton - -Builder.load_string(""" -: - id: panel - orientation: 'vertical' if panel.tab_orientation in ['top','bottom'] else 'horizontal' - ScrollView: - id: scroll_view - size_hint_y: None - height: panel._tab_display_height[panel.tab_display_mode] - MDTabBar: - id: tab_bar - size_hint_y: None - height: panel._tab_display_height[panel.tab_display_mode] - background_color: panel.tab_color or panel.theme_cls.primary_color - canvas: - # Draw bottom border - Color: - rgba: (panel.tab_border_color or panel.tab_color or panel.theme_cls.primary_dark) - Rectangle: - size: (self.width,dp(2)) - ScreenManager: - id: tab_manager - current: root.current - screens: root.tabs - - -: - canvas: - Color: - rgba: self.panel.tab_color or self.panel.theme_cls.primary_color - Rectangle: - size: self.size - pos: self.pos - - # Draw indicator - Color: - rgba: (self.panel.tab_indicator_color or self.panel.theme_cls.accent_color) if self.tab \ - and self.tab.manager and self.tab.manager.current==self.tab.name else (self.panel.tab_border_color \ - or self.panel.tab_color or self.panel.theme_cls.primary_dark) - Rectangle: - size: (self.width,dp(2)) - pos: self.pos - - size_hint: (None,None) #(1, None) if self.panel.tab_width_mode=='fixed' else (None,None) - width: (_label.texture_size[0] + dp(16)) - padding: (dp(12), 0) - theme_text_color: 'Custom' - text_color: (self.panel.tab_text_color_active or app.theme_cls.bg_light if app.theme_cls.theme_style == "Light" \ - else app.theme_cls.opposite_bg_light) if self.tab and self.tab.manager \ - and self.tab.manager.current==self.tab.name else (self.panel.tab_text_color \ - or self.panel.theme_cls.primary_light) - on_press: - self.tab.dispatch('on_tab_press') - # self.tab.manager.current = self.tab.name - on_release: self.tab.dispatch('on_tab_release') - on_touch_down: self.tab.dispatch('on_tab_touch_down',*args) - on_touch_move: self.tab.dispatch('on_tab_touch_move',*args) - on_touch_up: self.tab.dispatch('on_tab_touch_up',*args) - - - MDLabel: - id: _label - text: root.tab.text if root.panel.tab_display_mode == 'text' else u"{}".format(md_icons[root.tab.icon]) - font_style: 'Button' if root.panel.tab_display_mode == 'text' else 'Icon' - size_hint_x: None# if root.panel.tab_width_mode=='fixed' else 1 - text_size: (None, root.height) - height: self.texture_size[1] - theme_text_color: root.theme_text_color - text_color: root.text_color - valign: 'middle' - halign: 'center' - opposite_colors: root.opposite_colors -""") - - -class MDTabBar(ThemableBehavior, BackgroundColorBehavior, BoxLayout): - pass - - -class MDTabHeader(MDFlatButton): - """ Internal widget for headers based on MDFlatButton""" - - width = BoundedNumericProperty(dp(None), min=dp(72), max=dp(264), errorhandler=lambda x: dp(72)) - tab = ObjectProperty(None) - panel = ObjectProperty(None) - - -class MDTab(Screen): - """ A tab is simply a screen with meta information - that defines the content that goes in the tab header. - """ - __events__ = ('on_tab_touch_down', 'on_tab_touch_move', 'on_tab_touch_up', 'on_tab_press', 'on_tab_release') - - # Tab header text - text = StringProperty("") - - # Tab header icon - icon = StringProperty("circle") - - # Tab dropdown menu items - menu_items = ListProperty() - - # Tab dropdown menu (if you want to customize it) - menu = ObjectProperty(None) - - def __init__(self, **kwargs): - super(MDTab, self).__init__(**kwargs) - self.index = 0 - self.parent_widget = None - self.register_event_type('on_tab_touch_down') - self.register_event_type('on_tab_touch_move') - self.register_event_type('on_tab_touch_up') - self.register_event_type('on_tab_press') - self.register_event_type('on_tab_release') - - def on_leave(self, *args): - self.parent_widget.ids.tab_manager.transition.direction = self.parent_widget.prev_dir - - def on_tab_touch_down(self, *args): - pass - - def on_tab_touch_move(self, *args): - pass - - def on_tab_touch_up(self, *args): - pass - - def on_tab_press(self, *args): - par = self.parent_widget - if par.previous_tab is not self: - par.prev_dir = str(par.ids.tab_manager.transition.direction) - if par.previous_tab.index > self.index: - par.ids.tab_manager.transition.direction = "right" - elif par.previous_tab.index < self.index: - par.ids.tab_manager.transition.direction = "left" - par.ids.tab_manager.current = self.name - par.previous_tab = self - - def on_tab_release(self, *args): - pass - - def __repr__(self): - return "".format(self.name, self.text) - - -class MDTabbedPanel(ThemableBehavior, BackgroundColorBehavior, BoxLayout): - """ A tab panel that is implemented by delegating all tabs - to a ScreenManager. - """ - # If tabs should fill space - tab_width_mode = OptionProperty('stacked', options=['stacked', 'fixed']) - - # Where the tabs go - tab_orientation = OptionProperty('top', options=['top']) # ,'left','bottom','right']) - - # How tabs are displayed - tab_display_mode = OptionProperty('text', options=['text', 'icons']) # ,'both']) - _tab_display_height = DictProperty({'text': dp(46), 'icons': dp(46), 'both': dp(72)}) - - # Tab background color (leave empty for theme color) - tab_color = ListProperty([]) - - # Tab text color in normal state (leave empty for theme color) - tab_text_color = ListProperty([]) - - # Tab text color in active state (leave empty for theme color) - tab_text_color_active = ListProperty([]) - - # Tab indicator color (leave empty for theme color) - tab_indicator_color = ListProperty([]) - - # Tab bar bottom border color (leave empty for theme color) - tab_border_color = ListProperty([]) - - # List of all the tabs so you can dynamically change them - tabs = ListProperty([]) - - # Current tab name - current = StringProperty(None) - - def __init__(self, **kwargs): - super(MDTabbedPanel, self).__init__(**kwargs) - self.previous_tab = None - self.prev_dir = None - self.index = 0 - self._refresh_tabs() - - def on_tab_width_mode(self, *args): - self._refresh_tabs() - - def on_tab_display_mode(self, *args): - self._refresh_tabs() - - def _refresh_tabs(self): - """ Refresh all tabs """ - # if fixed width, use a box layout - if not self.ids: - return - tab_bar = self.ids.tab_bar - tab_bar.clear_widgets() - tab_manager = self.ids.tab_manager - for tab in tab_manager.screens: - tab_header = MDTabHeader(tab=tab, - panel=self, - height=tab_bar.height, - ) - tab_bar.add_widget(tab_header) - - def add_widget(self, widget, **kwargs): - """ Add tabs to the screen or the layout. - :param widget: The widget to add. - """ - d = {} - if isinstance(widget, MDTab): - self.index += 1 - if self.index == 1: - self.previous_tab = widget - widget.index = self.index - widget.parent_widget = self - self.ids.tab_manager.add_widget(widget) - self._refresh_tabs() - else: - super(MDTabbedPanel, self).add_widget(widget) - - def remove_widget(self, widget): - """ Remove tabs from the screen or the layout. - :param widget: The widget to remove. - """ - self.index -= 1 - if isinstance(widget, MDTab): - self.ids.tab_manager.remove_widget(widget) - self._refresh_tabs() - else: - super(MDTabbedPanel, self).remove_widget(widget) - - -if __name__ == '__main__': - from kivy.app import App - from kivymd.theming import ThemeManager - - class TabsApp(App): - theme_cls = ThemeManager() - - def build(self): - from kivy.core.window import Window - Window.size = (540, 720) - # self.theme_cls.theme_style = 'Dark' - - return Builder.load_string(""" -#:import Toolbar kivymd.toolbar.Toolbar -BoxLayout: - orientation:'vertical' - Toolbar: - id: toolbar - title: 'Page title' - background_color: app.theme_cls.primary_color - left_action_items: [['menu', lambda x: '']] - right_action_items: [['search', lambda x: ''],['more-vert',lambda x:'']] - MDTabbedPanel: - id: tab_mgr - tab_display_mode:'icons' - - MDTab: - name: 'music' - text: "Music" # Why are these not set!!! - icon: "playlist-audio" - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Here is my music list :)" - halign: 'center' - MDTab: - name: 'movies' - text: 'Movies' - icon: "movie" - - MDLabel: - font_style: 'Body1' - theme_text_color: 'Primary' - text: "Show movies here :)" - halign: 'center' - - -""") - - - TabsApp().run() diff --git a/src/kivymd/textfields.py b/src/kivymd/textfields.py deleted file mode 100644 index 18de10e6..00000000 --- a/src/kivymd/textfields.py +++ /dev/null @@ -1,215 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.uix.textinput import TextInput -from kivy.properties import ObjectProperty, NumericProperty, StringProperty, \ - ListProperty, BooleanProperty -from kivy.metrics import sp, dp -from kivy.animation import Animation -from kivymd.label import MDLabel -from kivymd.theming import ThemableBehavior -from kivy.clock import Clock - -Builder.load_string(''' -: - canvas.before: - Clear - Color: - rgba: self.line_color_normal - Line: - id: "the_line" - points: self.x, self.y + dp(8), self.x + self.width, self.y + dp(8) - width: 1 - dash_length: dp(3) - dash_offset: 2 if self.disabled else 0 - Color: - rgba: self._current_line_color - Rectangle: - size: self._line_width, dp(2) - pos: self.center_x - (self._line_width / 2), self.y + dp(8) - Color: - rgba: self._current_error_color - Rectangle: - texture: self._msg_lbl.texture - size: self._msg_lbl.texture_size - pos: self.x, self.y - dp(8) - Color: - rgba: (self._current_line_color if self.focus and not self.cursor_blink \ - else (0, 0, 0, 0)) - Rectangle: - pos: [int(x) for x in self.cursor_pos] - size: 1, -self.line_height - Color: - #rgba: self._hint_txt_color if not self.text and not self.focus\ - #else (self.line_color_focus if not self.text or self.focus\ - #else self.line_color_normal) - rgba: self._current_hint_text_color - Rectangle: - texture: self._hint_lbl.texture - size: self._hint_lbl.texture_size - pos: self.x, self.y + self._hint_y - Color: - rgba: self.disabled_foreground_color if self.disabled else \ - (self.hint_text_color if not self.text and not self.focus else \ - self.foreground_color) - - font_name: 'Roboto' - foreground_color: app.theme_cls.text_color - font_size: sp(16) - bold: False - padding: 0, dp(16), 0, dp(10) - multiline: False - size_hint_y: None - height: dp(48) -''') - - -class SingleLineTextField(ThemableBehavior, TextInput): - line_color_normal = ListProperty() - line_color_focus = ListProperty() - error_color = ListProperty() - error = BooleanProperty(False) - message = StringProperty("") - message_mode = StringProperty("none") - mode = message_mode - - _hint_txt_color = ListProperty() - _hint_lbl = ObjectProperty() - _hint_lbl_font_size = NumericProperty(sp(16)) - _hint_y = NumericProperty(dp(10)) - _error_label = ObjectProperty() - _line_width = NumericProperty(0) - _hint_txt = StringProperty('') - _current_line_color = line_color_focus - _current_error_color = ListProperty([0.0, 0.0, 0.0, 0.0]) - _current_hint_text_color = _hint_txt_color - - def __init__(self, **kwargs): - Clock.schedule_interval(self._update_color, 5) - self._msg_lbl = MDLabel(font_style='Caption', - theme_text_color='Error', - halign='left', - valign='middle', - text=self.message) - - self._hint_lbl = MDLabel(font_style='Subhead', - halign='left', - valign='middle') - super(SingleLineTextField, self).__init__(**kwargs) - self.line_color_normal = self.theme_cls.divider_color - self.line_color_focus = list(self.theme_cls.primary_color) - self.base_line_color_focus = list(self.theme_cls.primary_color) - self.error_color = self.theme_cls.error_color - - self._hint_txt_color = self.theme_cls.disabled_hint_text_color - self.hint_text_color = (1, 1, 1, 0) - self.cursor_color = self.theme_cls.primary_color - self.bind(message=self._set_msg, - hint_text=self._set_hint, - _hint_lbl_font_size=self._hint_lbl.setter('font_size'), - message_mode=self._set_mode) - self.hint_anim_in = Animation(_hint_y=dp(34), - _hint_lbl_font_size=sp(12), duration=.2, - t='out_quad') - - self.hint_anim_out = Animation(_hint_y=dp(10), - _hint_lbl_font_size=sp(16), duration=.2, - t='out_quad') - - def _update_color(self, *args): - self.line_color_normal = self.theme_cls.divider_color - self.base_line_color_focus = list(self.theme_cls.primary_color) - if not self.focus and not self.error: - self.line_color_focus = self.theme_cls.primary_color - Animation(duration=.2, _current_hint_text_color=self.theme_cls.disabled_hint_text_color).start(self) - if self.mode == "persistent": - Animation(duration=.1, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - if self.focus and not self.error: - self.cursor_color = self.theme_cls.primary_color - - def on_hint_text_color(self, instance, color): - self._hint_txt_color = self.theme_cls.disabled_hint_text_color - self.hint_text_color = (1, 1, 1, 0) - - def on_width(self, instance, width): - if self.focus and instance is not None or self.error and instance is not None: - self._line_width = width - self.anim = Animation(_line_width=width, duration=.2, t='out_quad') - self._msg_lbl.width = self.width - self._hint_lbl.width = self.width - - def on_pos(self, *args): - self.hint_anim_in = Animation(_hint_y=dp(34), - _hint_lbl_font_size=sp(12), duration=.2, - t='out_quad') - self.hint_anim_out = Animation(_hint_y=dp(10), - _hint_lbl_font_size=sp(16), duration=.2, - t='out_quad') - - def on_focus(self, *args): - if self.focus: - Animation.cancel_all(self, '_line_width', '_hint_y', - '_hint_lbl_font_size') - if len(self.text) == 0: - self.hint_anim_in.start(self) - if self.error: - Animation(duration=.2, _current_hint_text_color=self.error_color).start(self) - if self.mode == "on_error": - Animation(duration=.2, _current_error_color=self.error_color).start(self) - elif self.mode == "persistent": - Animation(duration=.2, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - elif self.mode == "on_focus": - Animation(duration=.2, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - else: - pass - elif not self.error: - self.on_width(None, self.width) - self.anim.start(self) - Animation(duration=.2, _current_hint_text_color=self.line_color_focus).start(self) - if self.mode == "on_error": - Animation(duration=.2, _current_error_color=(0, 0, 0, 0)).start(self) - if self.mode == "persistent": - Animation(duration=.2, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - elif self.mode == "on_focus": - Animation(duration=.2, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - else: - pass - else: - Animation.cancel_all(self, '_line_width', '_hint_y', - '_hint_lbl_font_size') - if len(self.text) == 0: - self.hint_anim_out.start(self) - if not self.error: - self.line_color_focus = self.base_line_color_focus - Animation(duration=.2, _current_line_color=self.line_color_focus, - _current_hint_text_color=self.theme_cls.disabled_hint_text_color).start(self) - if self.mode == "on_error": - Animation(duration=.2, _current_error_color=(0, 0, 0, 0)).start(self) - elif self.mode == "persistent": - Animation(duration=.2, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - elif self.mode == "on_focus": - Animation(duration=.2, _current_error_color=(0, 0, 0, 0)).start(self) - - self.on_width(None, 0) - self.anim.start(self) - elif self.error: - Animation(duration=.2, _current_line_color=self.error_color, - _current_hint_text_color=self.error_color).start(self) - if self.mode == "on_error": - Animation(duration=.2, _current_error_color=self.error_color).start(self) - elif self.mode == "persistent": - Animation(duration=.2, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) - elif self.mode == "on_focus": - Animation(duration=.2, _current_error_color=(0, 0, 0, 0)).start(self) - - def _set_hint(self, instance, text): - self._hint_lbl.text = text - - def _set_msg(self, instance, text): - self._msg_lbl.text = text - self.message = text - - def _set_mode(self, instance, text): - self.mode = text - if self.mode == "persistent": - Animation(duration=.1, _current_error_color=self.theme_cls.disabled_hint_text_color).start(self) diff --git a/src/kivymd/theme_picker.py b/src/kivymd/theme_picker.py deleted file mode 100644 index e5104ce6..00000000 --- a/src/kivymd/theme_picker.py +++ /dev/null @@ -1,422 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.uix.modalview import ModalView -from kivy.uix.floatlayout import FloatLayout -from kivy.uix.boxlayout import BoxLayout -from kivymd.button import MDFlatButton, MDIconButton -from kivymd.theming import ThemableBehavior -from kivymd.elevationbehavior import ElevationBehavior -from kivy.properties import ObjectProperty, ListProperty -from kivymd.label import MDLabel -from kivy.metrics import dp -from kivy.utils import get_color_from_hex -from kivymd.color_definitions import colors - -Builder.load_string(""" -#:import SingleLineTextField kivymd.textfields.SingleLineTextField -#:import MDTabbedPanel kivymd.tabs.MDTabbedPanel -#:import MDTab kivymd.tabs.MDTab -: - size_hint: (None, None) - size: dp(260), dp(120)+dp(290) - pos_hint: {'center_x': .5, 'center_y': .5} - canvas: - Color: - rgb: app.theme_cls.primary_color - Rectangle: - size: dp(260), dp(120) - pos: root.pos[0], root.pos[1] + root.height-dp(120) - Color: - rgb: app.theme_cls.bg_normal - Rectangle: - size: dp(260), dp(290) - pos: root.pos[0], root.pos[1] + root.height-(dp(120)+dp(290)) - - MDFlatButton: - pos: root.pos[0]+root.size[0]-dp(72), root.pos[1] + dp(10) - text: "Close" - on_release: root.dismiss() - MDLabel: - font_style: "Headline" - text: "Change theme" - size_hint: (None, None) - size: dp(160), dp(50) - pos_hint: {'center_x': 0.5, 'center_y': 0.9} - MDTabbedPanel: - size_hint: (None, None) - size: dp(260), root.height-dp(135) - pos_hint: {'center_x': 0.5, 'center_y': 0.475} - id: tab_panel - tab_display_mode:'text' - - MDTab: - name: 'color' - text: "Theme Color" - BoxLayout: - spacing: dp(4) - size_hint: (None, None) - size: dp(270), root.height # -dp(120) - pos_hint: {'center_x': 0.532, 'center_y': 0.89} - orientation: 'vertical' - BoxLayout: - size_hint: (None, None) - pos_hint: {'center_x': 0.5, 'center_y': 0.5} - size: dp(230), dp(40) - pos: self.pos - halign: 'center' - orientation: 'horizontal' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Red') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Red' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Pink') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Pink' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Purple') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Purple' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('DeepPurple') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'DeepPurple' - BoxLayout: - size_hint: (None, None) - pos_hint: {'center_x': .5, 'center_y': 0.5} - size: dp(230), dp(40) - pos: self.pos - halign: 'center' - orientation: 'horizontal' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Indigo') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Indigo' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Blue') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Blue' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('LightBlue') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'LightBlue' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Cyan') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Cyan' - BoxLayout: - size_hint: (None, None) - pos_hint: {'center_x': .5, 'center_y': 0.5} - size: dp(230), dp(40) - pos: self.pos - halign: 'center' - orientation: 'horizontal' - padding: 0, 0, 0, dp(1) - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Teal') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Teal' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Green') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Green' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('LightGreen') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'LightGreen' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Lime') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Lime' - BoxLayout: - size_hint: (None, None) - pos_hint: {'center_x': .5, 'center_y': 0.5} - size: dp(230), dp(40) - pos: self.pos - orientation: 'horizontal' - halign: 'center' - padding: 0, 0, 0, dp(1) - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Yellow') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Yellow' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Amber') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Amber' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Orange') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Orange' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('DeepOrange') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'DeepOrange' - BoxLayout: - size_hint: (None, None) - pos_hint: {'center_x': .5, 'center_y': 0.5} - size: dp(230), dp(40) - #pos: self.pos - orientation: 'horizontal' - padding: 0, 0, 0, dp(1) - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Brown') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Brown' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('Grey') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'Grey' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - #pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: root.rgb_hex('BlueGrey') - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.primary_palette = 'BlueGrey' - BoxLayout: - MDIconButton: - size: dp(40), dp(40) - size_hint: (None, None) - canvas: - Color: - rgba: app.theme_cls.bg_normal - Ellipse: - size: self.size - pos: self.pos - disabled: True - - MDTab: - name: 'style' - text: "Theme Style" - BoxLayout: - size_hint: (None, None) - pos_hint: {'center_x': .3, 'center_y': 0.5} - size: self.size - pos: self.pos - halign: 'center' - spacing: dp(10) - BoxLayout: - halign: 'center' - size_hint: (None, None) - size: dp(100), dp(100) - pos: self.pos - pos_hint: {'center_x': .3, 'center_y': 0.5} - MDIconButton: - size: dp(100), dp(100) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: 1, 1, 1, 1 - Ellipse: - size: self.size - pos: self.pos - Color: - rgba: 0, 0, 0, 1 - Line: - width: 1. - circle: (self.center_x, self.center_y, 50) - on_release: app.theme_cls.theme_style = 'Light' - BoxLayout: - halign: 'center' - size_hint: (None, None) - size: dp(100), dp(100) - MDIconButton: - size: dp(100), dp(100) - pos: self.pos - size_hint: (None, None) - canvas: - Color: - rgba: 0, 0, 0, 1 - Ellipse: - size: self.size - pos: self.pos - on_release: app.theme_cls.theme_style = 'Dark' -""") - - -class MDThemePicker(ThemableBehavior, FloatLayout, ModalView, ElevationBehavior): - # background_color = ListProperty([0, 0, 0, 0]) - time = ObjectProperty() - - def __init__(self, **kwargs): - super(MDThemePicker, self).__init__(**kwargs) - - def rgb_hex(self, col): - return get_color_from_hex(colors[col][self.theme_cls.accent_hue]) - - -if __name__ == "__main__": - from kivy.app import App - from kivymd.theming import ThemeManager - - class ThemePickerApp(App): - theme_cls = ThemeManager() - - def build(self): - main_widget = Builder.load_string(""" -#:import MDRaisedButton kivymd.button.MDRaisedButton -#:import MDThemePicker kivymd.theme_picker.MDThemePicker -FloatLayout: - MDRaisedButton: - size_hint: None, None - pos_hint: {'center_x': .5, 'center_y': .5} - size: 3 * dp(48), dp(48) - center_x: self.parent.center_x - text: 'Open theme picker' - on_release: MDThemePicker().open() - opposite_colors: True -""") - return main_widget - - ThemePickerApp().run() diff --git a/src/kivymd/theming.py b/src/kivymd/theming.py deleted file mode 100644 index 3172ee58..00000000 --- a/src/kivymd/theming.py +++ /dev/null @@ -1,350 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.app import App -from kivy.core.text import LabelBase -from kivy.core.window import Window -from kivy.clock import Clock -from kivy.metrics import dp -from kivy.properties import OptionProperty, AliasProperty, ObjectProperty, \ - StringProperty, ListProperty, BooleanProperty -from kivy.uix.widget import Widget -from kivy.utils import get_color_from_hex -from kivy.atlas import Atlas -from kivymd.color_definitions import colors -from kivymd.material_resources import FONTS, DEVICE_TYPE -from kivymd import images_path - -for font in FONTS: - LabelBase.register(**font) - - -class ThemeManager(Widget): - primary_palette = OptionProperty( - 'Blue', - options=['Pink', 'Blue', 'Indigo', 'BlueGrey', 'Brown', - 'LightBlue', - 'Purple', 'Grey', 'Yellow', 'LightGreen', 'DeepOrange', - 'Green', 'Red', 'Teal', 'Orange', 'Cyan', 'Amber', - 'DeepPurple', 'Lime']) - - primary_hue = OptionProperty( - '500', - options=['50', '100', '200', '300', '400', '500', '600', '700', - '800', - '900', 'A100', 'A200', 'A400', 'A700']) - - primary_light_hue = OptionProperty( - '200', - options=['50', '100', '200', '300', '400', '500', '600', '700', - '800', - '900', 'A100', 'A200', 'A400', 'A700']) - - primary_dark_hue = OptionProperty( - '700', - options=['50', '100', '200', '300', '400', '500', '600', '700', - '800', - '900', 'A100', 'A200', 'A400', 'A700']) - - def _get_primary_color(self): - return get_color_from_hex( - colors[self.primary_palette][self.primary_hue]) - - primary_color = AliasProperty(_get_primary_color, - bind=('primary_palette', 'primary_hue')) - - def _get_primary_light(self): - return get_color_from_hex( - colors[self.primary_palette][self.primary_light_hue]) - - primary_light = AliasProperty( - _get_primary_light, bind=('primary_palette', 'primary_light_hue')) - - def _get_primary_dark(self): - return get_color_from_hex( - colors[self.primary_palette][self.primary_dark_hue]) - - primary_dark = AliasProperty(_get_primary_dark, - bind=('primary_palette', 'primary_dark_hue')) - - accent_palette = OptionProperty( - 'Amber', - options=['Pink', 'Blue', 'Indigo', 'BlueGrey', 'Brown', - 'LightBlue', - 'Purple', 'Grey', 'Yellow', 'LightGreen', 'DeepOrange', - 'Green', 'Red', 'Teal', 'Orange', 'Cyan', 'Amber', - 'DeepPurple', 'Lime']) - - accent_hue = OptionProperty( - '500', - options=['50', '100', '200', '300', '400', '500', '600', '700', - '800', - '900', 'A100', 'A200', 'A400', 'A700']) - - accent_light_hue = OptionProperty( - '200', - options=['50', '100', '200', '300', '400', '500', '600', '700', - '800', - '900', 'A100', 'A200', 'A400', 'A700']) - - accent_dark_hue = OptionProperty( - '700', - options=['50', '100', '200', '300', '400', '500', '600', '700', - '800', - '900', 'A100', 'A200', 'A400', 'A700']) - - def _get_accent_color(self): - return get_color_from_hex( - colors[self.accent_palette][self.accent_hue]) - - accent_color = AliasProperty(_get_accent_color, - bind=['accent_palette', 'accent_hue']) - - def _get_accent_light(self): - return get_color_from_hex( - colors[self.accent_palette][self.accent_light_hue]) - - accent_light = AliasProperty(_get_accent_light, - bind=['accent_palette', 'accent_light_hue']) - - def _get_accent_dark(self): - return get_color_from_hex( - colors[self.accent_palette][self.accent_dark_hue]) - - accent_dark = AliasProperty(_get_accent_dark, - bind=['accent_palette', 'accent_dark_hue']) - - theme_style = OptionProperty('Light', options=['Light', 'Dark']) - - def _get_theme_style(self, opposite): - if opposite: - return 'Light' if self.theme_style == 'Dark' else 'Dark' - else: - return self.theme_style - - def _get_bg_darkest(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - return get_color_from_hex(colors['Light']['StatusBar']) - elif theme_style == 'Dark': - return get_color_from_hex(colors['Dark']['StatusBar']) - - bg_darkest = AliasProperty(_get_bg_darkest, bind=['theme_style']) - - def _get_op_bg_darkest(self): - return self._get_bg_darkest(True) - - opposite_bg_darkest = AliasProperty(_get_op_bg_darkest, - bind=['theme_style']) - - def _get_bg_dark(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - return get_color_from_hex(colors['Light']['AppBar']) - elif theme_style == 'Dark': - return get_color_from_hex(colors['Dark']['AppBar']) - - bg_dark = AliasProperty(_get_bg_dark, bind=['theme_style']) - - def _get_op_bg_dark(self): - return self._get_bg_dark(True) - - opposite_bg_dark = AliasProperty(_get_op_bg_dark, bind=['theme_style']) - - def _get_bg_normal(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - return get_color_from_hex(colors['Light']['Background']) - elif theme_style == 'Dark': - return get_color_from_hex(colors['Dark']['Background']) - - bg_normal = AliasProperty(_get_bg_normal, bind=['theme_style']) - - def _get_op_bg_normal(self): - return self._get_bg_normal(True) - - opposite_bg_normal = AliasProperty(_get_op_bg_normal, bind=['theme_style']) - - def _get_bg_light(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - return get_color_from_hex(colors['Light']['CardsDialogs']) - elif theme_style == 'Dark': - return get_color_from_hex(colors['Dark']['CardsDialogs']) - - bg_light = AliasProperty(_get_bg_light, bind=['theme_style']) - - def _get_op_bg_light(self): - return self._get_bg_light(True) - - opposite_bg_light = AliasProperty(_get_op_bg_light, bind=['theme_style']) - - def _get_divider_color(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - color = get_color_from_hex('000000') - elif theme_style == 'Dark': - color = get_color_from_hex('FFFFFF') - color[3] = .12 - return color - - divider_color = AliasProperty(_get_divider_color, bind=['theme_style']) - - def _get_op_divider_color(self): - return self._get_divider_color(True) - - opposite_divider_color = AliasProperty(_get_op_divider_color, - bind=['theme_style']) - - def _get_text_color(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - color = get_color_from_hex('000000') - color[3] = .87 - elif theme_style == 'Dark': - color = get_color_from_hex('FFFFFF') - return color - - text_color = AliasProperty(_get_text_color, bind=['theme_style']) - - def _get_op_text_color(self): - return self._get_text_color(True) - - opposite_text_color = AliasProperty(_get_op_text_color, - bind=['theme_style']) - - def _get_secondary_text_color(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - color = get_color_from_hex('000000') - color[3] = .54 - elif theme_style == 'Dark': - color = get_color_from_hex('FFFFFF') - color[3] = .70 - return color - - secondary_text_color = AliasProperty(_get_secondary_text_color, - bind=['theme_style']) - - def _get_op_secondary_text_color(self): - return self._get_secondary_text_color(True) - - opposite_secondary_text_color = AliasProperty(_get_op_secondary_text_color, - bind=['theme_style']) - - def _get_icon_color(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - color = get_color_from_hex('000000') - color[3] = .54 - elif theme_style == 'Dark': - color = get_color_from_hex('FFFFFF') - return color - - icon_color = AliasProperty(_get_icon_color, - bind=['theme_style']) - - def _get_op_icon_color(self): - return self._get_icon_color(True) - - opposite_icon_color = AliasProperty(_get_op_icon_color, - bind=['theme_style']) - - def _get_disabled_hint_text_color(self, opposite=False): - theme_style = self._get_theme_style(opposite) - if theme_style == 'Light': - color = get_color_from_hex('000000') - color[3] = .26 - elif theme_style == 'Dark': - color = get_color_from_hex('FFFFFF') - color[3] = .30 - return color - - disabled_hint_text_color = AliasProperty(_get_disabled_hint_text_color, - bind=['theme_style']) - - def _get_op_disabled_hint_text_color(self): - return self._get_disabled_hint_text_color(True) - - opposite_disabled_hint_text_color = AliasProperty( - _get_op_disabled_hint_text_color, bind=['theme_style']) - - # Hardcoded because muh standard - def _get_error_color(self): - return get_color_from_hex(colors['Red']['A700']) - - error_color = AliasProperty(_get_error_color) - - def _get_ripple_color(self): - return self._ripple_color - - def _set_ripple_color(self, value): - self._ripple_color = value - - _ripple_color = ListProperty(get_color_from_hex(colors['Grey']['400'])) - ripple_color = AliasProperty(_get_ripple_color, - _set_ripple_color, - bind=['_ripple_color']) - - def _determine_device_orientation(self, _, window_size): - if window_size[0] > window_size[1]: - self.device_orientation = 'landscape' - elif window_size[1] >= window_size[0]: - self.device_orientation = 'portrait' - - device_orientation = StringProperty('') - - def _get_standard_increment(self): - if DEVICE_TYPE == 'mobile': - if self.device_orientation == 'landscape': - return dp(48) - else: - return dp(56) - else: - return dp(64) - - standard_increment = AliasProperty(_get_standard_increment, - bind=['device_orientation']) - - def _get_horizontal_margins(self): - if DEVICE_TYPE == 'mobile': - return dp(16) - else: - return dp(24) - - horizontal_margins = AliasProperty(_get_horizontal_margins) - - def on_theme_style(self, instance, value): - if hasattr(App.get_running_app(), 'theme_cls') and \ - App.get_running_app().theme_cls == self: - self.set_clearcolor_by_theme_style(value) - - def set_clearcolor_by_theme_style(self, theme_style): - if theme_style == 'Light': - Window.clearcolor = get_color_from_hex( - colors['Light']['Background']) - elif theme_style == 'Dark': - Window.clearcolor = get_color_from_hex( - colors['Dark']['Background']) - - def __init__(self, **kwargs): - super(ThemeManager, self).__init__(**kwargs) - self.rec_shadow = Atlas('{}rec_shadow.atlas'.format(images_path)) - self.rec_st_shadow = Atlas('{}rec_st_shadow.atlas'.format(images_path)) - self.quad_shadow = Atlas('{}quad_shadow.atlas'.format(images_path)) - self.round_shadow = Atlas('{}round_shadow.atlas'.format(images_path)) - Clock.schedule_once(lambda x: self.on_theme_style(0, self.theme_style)) - self._determine_device_orientation(None, Window.size) - Window.bind(size=self._determine_device_orientation) - - -class ThemableBehavior(object): - theme_cls = ObjectProperty(None) - opposite_colors = BooleanProperty(False) - - def __init__(self, **kwargs): - if self.theme_cls is not None: - pass - elif hasattr(App.get_running_app(), 'theme_cls'): - self.theme_cls = App.get_running_app().theme_cls - else: - self.theme_cls = ThemeManager() - super(ThemableBehavior, self).__init__(**kwargs) diff --git a/src/kivymd/time_picker.py b/src/kivymd/time_picker.py deleted file mode 100644 index 6de6fc20..00000000 --- a/src/kivymd/time_picker.py +++ /dev/null @@ -1,84 +0,0 @@ -# -*- coding: utf-8 -*- - -from kivy.lang import Builder -from kivy.uix.modalview import ModalView -from kivy.uix.floatlayout import FloatLayout -from kivymd.theming import ThemableBehavior -from kivymd.elevationbehavior import ElevationBehavior -from kivy.properties import ObjectProperty, ListProperty - -Builder.load_string(""" -#:import MDFlatButton kivymd.button.MDFlatButton -#:import CircularTimePicker kivymd.vendor.circularTimePicker.CircularTimePicker -#:import dp kivy.metrics.dp -: - size_hint: (None, None) - size: [dp(270), dp(335)+dp(95)] - #if root.theme_cls.device_orientation == 'portrait' else [dp(520), dp(325)] - pos_hint: {'center_x': .5, 'center_y': .5} - canvas: - Color: - rgba: self.theme_cls.bg_light - Rectangle: - size: [dp(270), dp(335)] - #if root.theme_cls.device_orientation == 'portrait' else [dp(250), root.height] - pos: [root.pos[0], root.pos[1] + root.height - dp(335) - dp(95)] - #if root.theme_cls.device_orientation == 'portrait' else [root.pos[0]+dp(270), root.pos[1]] - Color: - rgba: self.theme_cls.primary_color - Rectangle: - size: [dp(270), dp(95)] - #if root.theme_cls.device_orientation == 'portrait' else [dp(270), root.height] - pos: [root.pos[0], root.pos[1] + root.height - dp(95)] - #if root.theme_cls.device_orientation == 'portrait' else [root.pos[0], root.pos[1]] - Color: - rgba: self.theme_cls.bg_dark - Ellipse: - size: [dp(220), dp(220)] - #if root.theme_cls.device_orientation == 'portrait' else [dp(195), dp(195)] - pos: root.pos[0]+dp(270)/2-dp(220)/2, root.pos[1] + root.height - (dp(335)/2+dp(95)) - dp(220)/2 + dp(35) - #Color: - #rgba: (1, 0, 0, 1) - #Line: - #width: 4 - #points: dp(270)/2, root.height, dp(270)/2, 0 - CircularTimePicker: - id: time_picker - pos: (dp(270)/2)-(self.width/2), root.height-self.height - size_hint: [.8, .8] - #if root.theme_cls.device_orientation == 'portrait' else [0.35, 0.9] - pos_hint: {'center_x': 0.5, 'center_y': 0.585} - #if root.theme_cls.device_orientation == 'portrait' else {'center_x': 0.75, 'center_y': 0.7} - MDFlatButton: - pos: root.pos[0]+root.size[0]-dp(72)*2, root.pos[1] + dp(10) - text: "Cancel" - on_release: root.close_cancel() - MDFlatButton: - pos: root.pos[0]+root.size[0]-dp(72), root.pos[1] + dp(10) - text: "OK" - on_release: root.close_ok() -""") - - -class MDTimePicker(ThemableBehavior, FloatLayout, ModalView, ElevationBehavior): - # background_color = ListProperty((0, 0, 0, 0)) - time = ObjectProperty() - - def __init__(self, **kwargs): - super(MDTimePicker, self).__init__(**kwargs) - self.current_time = self.ids.time_picker.time - - def set_time(self, time): - try: - self.ids.time_picker.set_time(time) - except AttributeError: - raise TypeError("MDTimePicker._set_time must receive a datetime object, not a \"" + - type(time).__name__ + "\"") - - def close_cancel(self): - self.dismiss() - - def close_ok(self): - self.current_time = self.ids.time_picker.time - self.time = self.current_time - self.dismiss() diff --git a/src/kivymd/toolbar.py b/src/kivymd/toolbar.py deleted file mode 100644 index fc7b146c..00000000 --- a/src/kivymd/toolbar.py +++ /dev/null @@ -1,98 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.clock import Clock -from kivy.lang import Builder -from kivy.metrics import dp -from kivy.properties import ListProperty, StringProperty, OptionProperty -from kivy.uix.boxlayout import BoxLayout -from kivymd.backgroundcolorbehavior import BackgroundColorBehavior -from kivymd.button import MDIconButton -from kivymd.theming import ThemableBehavior -from kivymd.elevationbehavior import ElevationBehavior - -Builder.load_string(''' -#:import m_res kivymd.material_resources - - size_hint_y: None - height: root.theme_cls.standard_increment - background_color: root.background_color - padding: [root.theme_cls.horizontal_margins - dp(12), 0] - opposite_colors: True - elevation: 6 - BoxLayout: - id: left_actions - orientation: 'horizontal' - size_hint_x: None - padding: [0, (self.height - dp(48))/2] - BoxLayout: - padding: dp(12), 0 - MDLabel: - font_style: 'Title' - opposite_colors: root.opposite_colors - theme_text_color: root.title_theme_color - text_color: root.title_color - text: root.title - shorten: True - shorten_from: 'right' - BoxLayout: - id: right_actions - orientation: 'horizontal' - size_hint_x: None - padding: [0, (self.height - dp(48))/2] -''') - - -class Toolbar(ThemableBehavior, ElevationBehavior, BackgroundColorBehavior, - BoxLayout): - left_action_items = ListProperty() - """The icons on the left of the Toolbar. - - To add one, append a list like the following: - - ['icon_name', callback] - - where 'icon_name' is a string that corresponds to an icon definition and - callback is the function called on a touch release event. - """ - - right_action_items = ListProperty() - """The icons on the left of the Toolbar. - - Works the same way as :attr:`left_action_items` - """ - - title = StringProperty() - """The text displayed on the Toolbar.""" - - title_theme_color = OptionProperty(None, allownone=True, - options=['Primary', 'Secondary', 'Hint', - 'Error', 'Custom']) - - title_color = ListProperty(None, allownone=True) - - background_color = ListProperty([0, 0, 0, 1]) - - def __init__(self, **kwargs): - super(Toolbar, self).__init__(**kwargs) - Clock.schedule_once( - lambda x: self.on_left_action_items(0, self.left_action_items)) - Clock.schedule_once( - lambda x: self.on_right_action_items(0, - self.right_action_items)) - - def on_left_action_items(self, instance, value): - self.update_action_bar(self.ids['left_actions'], value) - - def on_right_action_items(self, instance, value): - self.update_action_bar(self.ids['right_actions'], value) - - def update_action_bar(self, action_bar, action_bar_items): - action_bar.clear_widgets() - new_width = 0 - for item in action_bar_items: - new_width += dp(48) - action_bar.add_widget(MDIconButton(icon=item[0], - on_release=item[1], - opposite_colors=True, - text_color=self.title_color, - theme_text_color=self.title_theme_color)) - action_bar.width = new_width diff --git a/src/kivymd/vendor/__init__.py b/src/kivymd/vendor/__init__.py deleted file mode 100644 index 9bad5790..00000000 --- a/src/kivymd/vendor/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# coding=utf-8 diff --git a/src/kivymd/vendor/circleLayout/LICENSE b/src/kivymd/vendor/circleLayout/LICENSE deleted file mode 100644 index 9d6e5b59..00000000 --- a/src/kivymd/vendor/circleLayout/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Davide Depau - -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. - diff --git a/src/kivymd/vendor/circleLayout/README.md b/src/kivymd/vendor/circleLayout/README.md deleted file mode 100644 index 6cf54bbe..00000000 --- a/src/kivymd/vendor/circleLayout/README.md +++ /dev/null @@ -1,21 +0,0 @@ -CircularLayout -============== - -CircularLayout is a special layout that places widgets around a circle. - -See the widget's documentation and the example for more information. - -![Screenshot](screenshot.png) - -size_hint ---------- - -size_hint_x is used as an angle-quota hint (widget with higher -size_hint_x will be farther from each other, and viceversa), while -size_hint_y is used as a widget size hint (widgets with a higher size -hint will be bigger).size_hint_x cannot be None. - -Widgets are all squares, unless you set size_hint_y to None (in that -case you'll be able to specify your own size), and their size is the -difference between the outer and the inner circle's radii. To make the -widgets bigger you can just decrease inner_radius_hint. \ No newline at end of file diff --git a/src/kivymd/vendor/circleLayout/__init__.py b/src/kivymd/vendor/circleLayout/__init__.py deleted file mode 100644 index 9d62c99c..00000000 --- a/src/kivymd/vendor/circleLayout/__init__.py +++ /dev/null @@ -1,196 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -""" -CircularLayout -============== - -CircularLayout is a special layout that places widgets around a circle. - -size_hint ---------- - -size_hint_x is used as an angle-quota hint (widget with higher -size_hint_x will be farther from each other, and vice versa), while -size_hint_y is used as a widget size hint (widgets with a higher size -hint will be bigger).size_hint_x cannot be None. - -Widgets are all squares, unless you set size_hint_y to None (in that -case you'll be able to specify your own size), and their size is the -difference between the outer and the inner circle's radii. To make the -widgets bigger you can just decrease inner_radius_hint. -""" - -from kivy.uix.layout import Layout -from kivy.properties import NumericProperty, ReferenceListProperty, OptionProperty, \ - BoundedNumericProperty, VariableListProperty, AliasProperty -from math import sin, cos, pi, radians - -__all__ = ('CircularLayout') - -try: - xrange(1, 2) -except NameError: - def xrange(first, second, third=None): - if third: - return range(first, second, third) - else: - return range(first, second) - - -class CircularLayout(Layout): - ''' - Circular layout class. See module documentation for more information. - ''' - - padding = VariableListProperty([0, 0, 0, 0]) - '''Padding between the layout box and it's children: [padding_left, - padding_top, padding_right, padding_bottom]. - - padding also accepts a two argument form [padding_horizontal, - padding_vertical] and a one argument form [padding]. - - .. version changed:: 1.7.0 - Replaced NumericProperty with VariableListProperty. - - :attr:`padding` is a :class:`~kivy.properties.VariableListProperty` and - defaults to [0, 0, 0, 0]. - ''' - - start_angle = NumericProperty(0) - '''Angle (in degrees) at which the first widget will be placed. - Start counting angles from the X axis, going counterclockwise. - - :attr:`start_angle` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0 (start from the right). - ''' - - circle_quota = BoundedNumericProperty(360, min=0, max=360) - '''Size (in degrees) of the part of the circumference that will actually - be used to place widgets. - - :attr:`circle_quota` is a :class:`~kivy.properties.BoundedNumericProperty` - and defaults to 360 (all the circumference). - ''' - - direction = OptionProperty("ccw", options=("cw", "ccw")) - '''Direction of widgets in the circle. - - :attr:`direction` is an :class:`~kivy.properties.OptionProperty` and - defaults to 'ccw'. Can be 'ccw' (counterclockwise) or 'cw' (clockwise). - ''' - - outer_radius_hint = NumericProperty(1) - '''Sets the size of the outer circle. A number greater than 1 will make the - widgets larger than the actual widget, a number smaller than 1 will leave - a gap. - - :attr:`outer_radius_hint` is a :class:`~kivy.properties.NumericProperty` and - defaults to 1. - ''' - - inner_radius_hint = NumericProperty(.6) - '''Sets the size of the inner circle. A number greater than - :attr:`outer_radius_hint` will cause glitches. The closest it is to - :attr:`outer_radius_hint`, the smallest will be the widget in the layout. - - :attr:`outer_radius_hint` is a :class:`~kivy.properties.NumericProperty` and - defaults to 1. - ''' - - radius_hint = ReferenceListProperty(inner_radius_hint, outer_radius_hint) - '''Combined :attr:`outer_radius_hint` and :attr:`inner_radius_hint` in a list - for convenience. See their documentation for more details. - - :attr:`radius_hint` is a :class:`~kivy.properties.ReferenceListProperty`. - ''' - - def _get_delta_radii(self): - radius = min(self.width-self.padding[0]-self.padding[2], self.height-self.padding[1]-self.padding[3]) / 2. - outer_r = radius * self.outer_radius_hint - inner_r = radius * self.inner_radius_hint - return outer_r - inner_r - delta_radii = AliasProperty(_get_delta_radii, None, bind=("radius_hint", "padding", "size")) - - def __init__(self, **kwargs): - super(CircularLayout, self).__init__(**kwargs) - - self.bind( - start_angle=self._trigger_layout, - parent=self._trigger_layout, - # padding=self._trigger_layout, - children=self._trigger_layout, - size=self._trigger_layout, - radius_hint=self._trigger_layout, - pos=self._trigger_layout) - - def do_layout(self, *largs): - # optimize layout by preventing looking at the same attribute in a loop - len_children = len(self.children) - if len_children == 0: - return - selfcx = self.center_x - selfcy = self.center_y - direction = self.direction - cquota = radians(self.circle_quota) - start_angle_r = radians(self.start_angle) - padding_left = self.padding[0] - padding_top = self.padding[1] - padding_right = self.padding[2] - padding_bottom = self.padding[3] - padding_x = padding_left + padding_right - padding_y = padding_top + padding_bottom - - radius = min(self.width-padding_x, self.height-padding_y) / 2. - outer_r = radius * self.outer_radius_hint - inner_r = radius * self.inner_radius_hint - middle_r = radius * sum(self.radius_hint) / 2. - delta_r = outer_r - inner_r - - stretch_weight_angle = 0. - for w in self.children: - sha = w.size_hint_x - if sha is None: - raise ValueError("size_hint_x cannot be None in a CircularLayout") - else: - stretch_weight_angle += sha - - sign = +1. - angle_offset = start_angle_r - if direction == 'cw': - angle_offset = 2 * pi - start_angle_r - sign = -1. - - for c in reversed(self.children): - sha = c.size_hint_x - shs = c.size_hint_y - - angle_quota = cquota / stretch_weight_angle * sha - angle = angle_offset + (sign * angle_quota / 2) - angle_offset += sign * angle_quota - - # kived: looking it up, yes. x = cos(angle) * radius + centerx; y = sin(angle) * radius + centery - ccx = cos(angle) * middle_r + selfcx + padding_left - padding_right - ccy = sin(angle) * middle_r + selfcy + padding_bottom - padding_top - - c.center_x = ccx - c.center_y = ccy - if shs: - s = delta_r * shs - c.width = s - c.height = s - -if __name__ == "__main__": - from kivy.app import App - from kivy.uix.button import Button - - class CircLayoutApp(App): - def build(self): - cly = CircularLayout(direction="cw", start_angle=-75, inner_radius_hint=.7, padding="20dp") - - for i in xrange(1, 13): - cly.add_widget(Button(text=str(i), font_size="30dp")) - - return cly - - CircLayoutApp().run() diff --git a/src/kivymd/vendor/circularTimePicker/LICENSE b/src/kivymd/vendor/circularTimePicker/LICENSE deleted file mode 100644 index 9d6e5b59..00000000 --- a/src/kivymd/vendor/circularTimePicker/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2015 Davide Depau - -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. - diff --git a/src/kivymd/vendor/circularTimePicker/README.md b/src/kivymd/vendor/circularTimePicker/README.md deleted file mode 100644 index 20ac2de9..00000000 --- a/src/kivymd/vendor/circularTimePicker/README.md +++ /dev/null @@ -1,43 +0,0 @@ -Circular Date & Time Picker for Kivy -==================================== - -(currently only time, date coming soon) - -Based on [CircularLayout](https://github.com/kivy-garden/garden.circularlayout). -The main aim is to provide a date and time selector similar to the -one found in Android KitKat+. - -![Screenshot](screenshot.png) - -Simple usage ------------- - -Import the widget with - -```python -from kivy.garden.circulardatetimepicker import CircularTimePicker -``` - -then use it! That's it! - -```python -c = CircularTimePicker() -c.bind(time=self.set_time) -root.add_widget(c) -``` - -in Kv language: - -``` -: - BoxLayout: - orientation: "vertical" - - CircularTimePicker - - Button: - text: "Dismiss" - size_hint_y: None - height: "40dp" - on_release: root.dismiss() -``` \ No newline at end of file diff --git a/src/kivymd/vendor/circularTimePicker/__init__.py b/src/kivymd/vendor/circularTimePicker/__init__.py deleted file mode 100644 index fbc73954..00000000 --- a/src/kivymd/vendor/circularTimePicker/__init__.py +++ /dev/null @@ -1,770 +0,0 @@ -# -*- coding: utf-8 -*- - -""" -Circular Date & Time Picker for Kivy -==================================== - -(currently only time, date coming soon) - -Based on [CircularLayout](https://github.com/kivy-garden/garden.circularlayout). -The main aim is to provide a date and time selector similar to the -one found in Android KitKat+. - -Simple usage ------------- - -Import the widget with - -```python -from kivy.garden.circulardatetimepicker import CircularTimePicker -``` - -then use it! That's it! - -```python -c = CircularTimePicker() -c.bind(time=self.set_time) -root.add_widget(c) -``` - -in Kv language: - -``` -: - BoxLayout: - orientation: "vertical" - - CircularTimePicker - - Button: - text: "Dismiss" - size_hint_y: None - height: "40dp" - on_release: root.dismiss() -``` -""" - -from kivy.animation import Animation -from kivy.clock import Clock -from kivymd.vendor.circleLayout import CircularLayout -from kivy.graphics import Line, Color, Ellipse -from kivy.lang import Builder -from kivy.properties import NumericProperty, BoundedNumericProperty, \ - ObjectProperty, StringProperty, DictProperty, \ - ListProperty, OptionProperty, BooleanProperty, \ - ReferenceListProperty, AliasProperty -from kivy.uix.boxlayout import BoxLayout -from kivy.uix.label import Label -from kivy.metrics import dp -from kivymd.theming import ThemableBehavior -from math import atan, pi, radians, sin, cos -import sys -import datetime -if sys.version_info[0] > 2: - def xrange(first=None, second=None, third=None): - if third: - return range(first, second, third) - else: - return range(first, second) - - -def map_number(x, in_min, in_max, out_min, out_max): - return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min - - -def rgb_to_hex(*color): - tor = "#" - for col in color: - tor += "{:>02}".format(hex(int(col * 255))[2:]) - return tor - - -Builder.load_string(""" - -: - text_size: self.size - valign: "middle" - halign: "center" - font_size: self.height * self.size_factor - -: - canvas.before: - PushMatrix - Scale: - origin: self.center_x + self.padding[0] - self.padding[2], self.center_y + self.padding[3] - self.padding[1] - x: self.scale - y: self.scale - - canvas.after: - PopMatrix - -: - orientation: "vertical" - spacing: "20dp" - - FloatLayout: - anchor_x: "center" - anchor_y: "center" - size_hint_y: 1./3 - size_hint_x: 1 - size: root.size - pos: root.pos - - GridLayout: - cols: 2 - spacing: "10dp" - size_hint_x: None - width: self.minimum_width - pos_hint: {'center_x': .5, 'center_y': .5} - - Label: - id: timelabel - text: root.time_text - markup: True - halign: "right" - valign: "middle" - # text_size: self.size - size_hint_x: None #.6 - width: self.texture_size[0] - font_size: self.height * .75 - - Label: - id: ampmlabel - text: root.ampm_text - markup: True - halign: "left" - valign: "middle" - # text_size: self.size - size_hint_x: None #.4 - width: self.texture_size[0] - font_size: self.height * .3 - - FloatLayout: - id: picker_container - #size_hint_y: 2./3 - _bound: {} -""") - - -class Number(Label): - """The class used to show the numbers in the selector. - """ - - size_factor = NumericProperty(.5) - """Font size scale. - - :attr:`size_factor` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0.5. - """ - - -class CircularNumberPicker(CircularLayout): - """A circular number picker based on CircularLayout. A selector will - help you pick a number. You can also set :attr:`multiples_of` to make - it show only some numbers and use the space in between for the other - numbers. - """ - - min = NumericProperty(0) - """The first value of the range. - - :attr:`min` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0. - """ - - max = NumericProperty(0) - """The last value of the range. Note that it behaves like xrange, so - the actual last displayed value will be :attr:`max` - 1. - - :attr:`max` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0. - """ - - range = ReferenceListProperty(min, max) - """Packs :attr:`min` and :attr:`max` into a list for convenience. See - their documentation for further information. - - :attr:`range` is a :class:`~kivy.properties.ReferenceListProperty`. - """ - - multiples_of = NumericProperty(1) - """Only show numbers that are multiples of this number. The other numbers - will be selectable, but won't have their own label. - - :attr:`multiples_of` is a :class:`~kivy.properties.NumericProperty` and - defaults to 1. - """ - - # selector_color = ListProperty([.337, .439, .490]) - selector_color = ListProperty([1, 1, 1]) - """Color of the number selector. RGB. - - :attr:`selector_color` is a :class:`~kivy.properties.ListProperty` and - defaults to [.337, .439, .490] (material green). - """ - - color = ListProperty([0, 0, 0]) - """Color of the number labels and of the center dot. RGB. - - :attr:`color` is a :class:`~kivy.properties.ListProperty` and - defaults to [1, 1, 1] (white). - """ - - selector_alpha = BoundedNumericProperty(.3, min=0, max=1) - """Alpha value for the transparent parts of the selector. - - :attr:`selector_alpha` is a :class:`~kivy.properties.BoundedNumericProperty` and - defaults to 0.3 (min=0, max=1). - """ - - selected = NumericProperty(None) - """Currently selected number. - - :attr:`selected` is a :class:`~kivy.properties.NumericProperty` and - defaults to :attr:`min`. - """ - - number_size_factor = NumericProperty(.5) - """Font size scale factor fot the :class:`Number`s. - - :attr:`number_size_factor` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0.5. - """ - - number_format_string = StringProperty("{}") - """String that will be formatted with the selected number as the first argument. - Can be anything supported by :meth:`str.format` (es. "{:02d}"). - - :attr:`number_format_string` is a :class:`~kivy.properties.StringProperty` and - defaults to "{}". - """ - - scale = NumericProperty(1) - """Canvas scale factor. Used in :class:`CircularTimePicker` transitions. - - :attr:`scale` is a :class:`~kivy.properties.NumericProperty` and - defaults to 1. - """ - - _selection_circle = ObjectProperty(None) - _selection_line = ObjectProperty(None) - _selection_dot = ObjectProperty(None) - _selection_dot_color = ObjectProperty(None) - _selection_color = ObjectProperty(None) - _center_dot = ObjectProperty(None) - _center_color = ObjectProperty(None) - - def _get_items(self): - return self.max - self.min - - items = AliasProperty(_get_items, None) - - def _get_shown_items(self): - sh = 0 - for i in xrange(*self.range): - if i % self.multiples_of == 0: - sh += 1 - return sh - - shown_items = AliasProperty(_get_shown_items, None) - - def __init__(self, **kw): - self._trigger_genitems = Clock.create_trigger(self._genitems, -1) - self.bind(min=self._trigger_genitems, - max=self._trigger_genitems, - multiples_of=self._trigger_genitems) - super(CircularNumberPicker, self).__init__(**kw) - self.selected = self.min - self.bind(selected=self.on_selected, - pos=self.on_selected, - size=self.on_selected) - - cx = self.center_x + self.padding[0] - self.padding[2] - cy = self.center_y + self.padding[3] - self.padding[1] - sx, sy = self.pos_for_number(self.selected) - epos = [i - (self.delta_radii * self.number_size_factor) for i in (sx, sy)] - esize = [self.delta_radii * self.number_size_factor * 2] * 2 - dsize = [i * .3 for i in esize] - dpos = [i + esize[0] / 2. - dsize[0] / 2. for i in epos] - csize = [i * .05 for i in esize] - cpos = [i - csize[0] / 2. for i in (cx, cy)] - dot_alpha = 0 if self.selected % self.multiples_of == 0 else 1 - color = list(self.selector_color) - - with self.canvas: - self._selection_color = Color(*(color + [self.selector_alpha])) - self._selection_circle = Ellipse(pos=epos, size=esize) - self._selection_line = Line(points=[cx, cy, sx, sy], width=dp(1.25)) - self._selection_dot_color = Color(*(color + [dot_alpha])) - self._selection_dot = Ellipse(pos=dpos, size=dsize) - self._center_color = Color(*self.color) - self._center_dot = Ellipse(pos=cpos, size=csize) - - self.bind(selector_color=lambda ign, u: setattr(self._selection_color, "rgba", u + [self.selector_alpha])) - self.bind(selector_color=lambda ign, u: setattr(self._selection_dot_color, "rgb", u)) - self.bind(selector_color=lambda ign, u: self.dot_is_none()) - self.bind(color=lambda ign, u: setattr(self._center_color, "rgb", u)) - Clock.schedule_once(self._genitems) - Clock.schedule_once(self.on_selected) # Just to make sure pos/size are set - - def dot_is_none(self, *args): - dot_alpha = 0 if self.selected % self.multiples_of == 0 else 1 - if self._selection_dot_color: - self._selection_dot_color.a = dot_alpha - - def _genitems(self, *a): - self.clear_widgets() - for i in xrange(*self.range): - if i % self.multiples_of != 0: - continue - n = Number(text=self.number_format_string.format(i), size_factor=self.number_size_factor, color=self.color) - self.bind(color=n.setter("color")) - self.add_widget(n) - - def on_touch_down(self, touch): - if not self.collide_point(*touch.pos): - return - touch.grab(self) - self.selected = self.number_at_pos(*touch.pos) - if self.selected == 60: - self.selected = 0 - - def on_touch_move(self, touch): - if touch.grab_current is not self: - return super(CircularNumberPicker, self).on_touch_move(touch) - self.selected = self.number_at_pos(*touch.pos) - if self.selected == 60: - self.selected = 0 - - def on_touch_up(self, touch): - if touch.grab_current is not self: - return super(CircularNumberPicker, self).on_touch_up(touch) - touch.ungrab(self) - - def on_selected(self, *a): - cx = self.center_x + self.padding[0] - self.padding[2] - cy = self.center_y + self.padding[3] - self.padding[1] - sx, sy = self.pos_for_number(self.selected) - epos = [i - (self.delta_radii * self.number_size_factor) for i in (sx, sy)] - esize = [self.delta_radii * self.number_size_factor * 2] * 2 - dsize = [i * .3 for i in esize] - dpos = [i + esize[0] / 2. - dsize[0] / 2. for i in epos] - csize = [i * .05 for i in esize] - cpos = [i - csize[0] / 2. for i in (cx, cy)] - dot_alpha = 0 if self.selected % self.multiples_of == 0 else 1 - - if self._selection_circle: - self._selection_circle.pos = epos - self._selection_circle.size = esize - if self._selection_line: - self._selection_line.points = [cx, cy, sx, sy] - if self._selection_dot: - self._selection_dot.pos = dpos - self._selection_dot.size = dsize - if self._selection_dot_color: - self._selection_dot_color.a = dot_alpha - if self._center_dot: - self._center_dot.pos = cpos - self._center_dot.size = csize - - def pos_for_number(self, n): - """Returns the center x, y coordinates for a given number. - """ - - if self.items == 0: - return 0, 0 - radius = min(self.width - self.padding[0] - self.padding[2], - self.height - self.padding[1] - self.padding[3]) / 2. - middle_r = radius * sum(self.radius_hint) / 2. - cx = self.center_x + self.padding[0] - self.padding[2] - cy = self.center_y + self.padding[3] - self.padding[1] - sign = +1. - angle_offset = radians(self.start_angle) - if self.direction == 'cw': - angle_offset = 2 * pi - angle_offset - sign = -1. - quota = 2 * pi / self.items - mult_quota = 2 * pi / self.shown_items - angle = angle_offset + n * sign * quota - - if self.items == self.shown_items: - angle += quota / 2 - else: - angle -= mult_quota / 2 - - # kived: looking it up, yes. x = cos(angle) * radius + centerx; y = sin(angle) * radius + centery - x = cos(angle) * middle_r + cx - y = sin(angle) * middle_r + cy - - return x, y - - def number_at_pos(self, x, y): - """Returns the number at a given x, y position. The number is found - using the widget's center as a starting point for angle calculations. - - Not thoroughly tested, may yield wrong results. - """ - if self.items == 0: - return self.min - cx = self.center_x + self.padding[0] - self.padding[2] - cy = self.center_y + self.padding[3] - self.padding[1] - lx = x - cx - ly = y - cy - quota = 2 * pi / self.items - mult_quota = 2 * pi / self.shown_items - if lx == 0 and ly > 0: - angle = pi / 2 - elif lx == 0 and ly < 0: - angle = 3 * pi / 2 - else: - angle = atan(ly / lx) - if lx < 0 < ly: - angle += pi - if lx > 0 > ly: - angle += 2 * pi - if lx < 0 and ly < 0: - angle += pi - angle += radians(self.start_angle) - if self.direction == "cw": - angle = 2 * pi - angle - if mult_quota != quota: - angle -= mult_quota / 2 - if angle < 0: - angle += 2 * pi - elif angle > 2 * pi: - angle -= 2 * pi - - return int(angle / quota) + self.min - - -class CircularMinutePicker(CircularNumberPicker): - """:class:`CircularNumberPicker` implementation for minutes. - """ - - def __init__(self, **kw): - super(CircularMinutePicker, self).__init__(**kw) - self.min = 0 - self.max = 60 - self.multiples_of = 5 - self.number_format_string = "{:02d}" - self.direction = "cw" - self.bind(shown_items=self._update_start_angle) - Clock.schedule_once(self._update_start_angle) - Clock.schedule_once(self.on_selected) - - def _update_start_angle(self, *a): - self.start_angle = -(360. / self.shown_items / 2) - 90 - - -class CircularHourPicker(CircularNumberPicker): - """:class:`CircularNumberPicker` implementation for hours. - """ - - # military = BooleanProperty(False) - - def __init__(self, **kw): - super(CircularHourPicker, self).__init__(**kw) - self.min = 1 - self.max = 13 - # 25 if self.military else 13 - # self.inner_radius_hint = .8 if self.military else .6 - self.multiples_of = 1 - self.number_format_string = "{}" - self.direction = "cw" - self.bind(shown_items=self._update_start_angle) - # self.bind(military=lambda v: setattr(self, "max", 25 if v else 13)) - # self.bind(military=lambda v: setattr(self, "inner_radius_hint", .8 if self.military else .6)) - # Clock.schedule_once(self._genitems) - Clock.schedule_once(self._update_start_angle) - Clock.schedule_once(self.on_selected) - - def _update_start_angle(self, *a): - self.start_angle = (360. / self.shown_items / 2) - 90 - - -class CircularTimePicker(BoxLayout, ThemableBehavior): - """Widget that makes use of :class:`CircularHourPicker` and - :class:`CircularMinutePicker` to create a user-friendly, animated - time picker like the one seen on Android. - - See module documentation for more details. - """ - - primary_dark = ListProperty([1, 1, 1]) - - hours = NumericProperty(0) - """The hours, in military format (0-23). - - :attr:`hours` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0 (12am). - """ - - minutes = NumericProperty(0) - """The minutes. - - :attr:`minutes` is a :class:`~kivy.properties.NumericProperty` and - defaults to 0. - """ - - time_list = ReferenceListProperty(hours, minutes) - """Packs :attr:`hours` and :attr:`minutes` in a list for convenience. - - :attr:`time_list` is a :class:`~kivy.properties.ReferenceListProperty`. - """ - - # military = BooleanProperty(False) - time_format = StringProperty( - "[color={hours_color}][ref=hours]{hours}[/ref][/color][color={primary_dark}][ref=colon]:[/ref][/color]\ -[color={minutes_color}][ref=minutes]{minutes:02d}[/ref][/color]") - """String that will be formatted with the time and shown in the time label. - Can be anything supported by :meth:`str.format`. Make sure you don't - remove the refs. See the default for the arguments passed to format. - :attr:`time_format` is a :class:`~kivy.properties.StringProperty` and - defaults to "[color={hours_color}][ref=hours]{hours}[/ref][/color]:[color={minutes_color}][ref=minutes]\ - {minutes:02d}[/ref][/color]". - """ - - ampm_format = StringProperty( - "[color={am_color}][ref=am]AM[/ref][/color]\n[color={pm_color}][ref=pm]PM[/ref][/color]") - """String that will be formatted and shown in the AM/PM label. - Can be anything supported by :meth:`str.format`. Make sure you don't - remove the refs. See the default for the arguments passed to format. - - :attr:`ampm_format` is a :class:`~kivy.properties.StringProperty` and - defaults to "[color={am_color}][ref=am]AM[/ref][/color]\n[color={pm_color}][ref=pm]PM[/ref][/color]". - """ - - picker = OptionProperty("hours", options=("minutes", "hours")) - """Currently shown time picker. Can be one of "minutes", "hours". - - :attr:`picker` is a :class:`~kivy.properties.OptionProperty` and - defaults to "hours". - """ - - # selector_color = ListProperty([.337, .439, .490]) - selector_color = ListProperty([0, 0, 0]) - """Color of the number selector and of the highlighted text. RGB. - - :attr:`selector_color` is a :class:`~kivy.properties.ListProperty` and - defaults to [.337, .439, .490] (material green). - """ - - color = ListProperty([1, 1, 1]) - """Color of the number labels and of the center dot. RGB. - - :attr:`color` is a :class:`~kivy.properties.ListProperty` and - defaults to [1, 1, 1] (white). - """ - - selector_alpha = BoundedNumericProperty(.3, min=0, max=1) - """Alpha value for the transparent parts of the selector. - - :attr:`selector_alpha` is a :class:`~kivy.properties.BoundedNumericProperty` and - defaults to 0.3 (min=0, max=1). - """ - - _am = BooleanProperty(True) - _h_picker = ObjectProperty(None) - _m_picker = ObjectProperty(None) - _bound = DictProperty({}) - - def _get_time(self): - try: - return datetime.time(*self.time_list) - except ValueError: - self.time_list = [self.hours, 0] - return datetime.time(*self.time_list) - - def set_time(self, dt): - if dt.hour >= 12: - dt.strftime("%I:%M") - self._am = False - self.time_list = [dt.hour, dt.minute] - - time = AliasProperty(_get_time, set_time, bind=("time_list",)) - """Selected time as a datetime.time object. - - :attr:`time` is an :class:`~kivy.properties.AliasProperty`. - """ - - def _get_picker(self): - if self.picker == "hours": - return self._h_picker - return self._m_picker - - _picker = AliasProperty(_get_picker, None) - - def _get_time_text(self): - hc = rgb_to_hex(0, 0, 0) if self.picker == "hours" else rgb_to_hex(*self.primary_dark) - mc = rgb_to_hex(0, 0, 0) if self.picker == "minutes" else rgb_to_hex(*self.primary_dark) - h = self.hours == 0 and 12 or self.hours <= 12 and self.hours or self.hours - 12 - m = self.minutes - primary_dark = rgb_to_hex(*self.primary_dark) - return self.time_format.format(hours_color=hc, - minutes_color=mc, - hours=h, - minutes=m, - primary_dark=primary_dark) - time_text = AliasProperty(_get_time_text, None, bind=("hours", "minutes", "time_format", "picker")) - - def _get_ampm_text(self, *args): - amc = rgb_to_hex(0, 0, 0) if self._am else rgb_to_hex(*self.primary_dark) - pmc = rgb_to_hex(0, 0, 0) if not self._am else rgb_to_hex(*self.primary_dark) - return self.ampm_format.format(am_color=amc, - pm_color=pmc) - - ampm_text = AliasProperty(_get_ampm_text, None, bind=("hours", "ampm_format", "_am")) - - def __init__(self, **kw): - super(CircularTimePicker, self).__init__(**kw) - self.selector_color = self.theme_cls.primary_color[0], self.theme_cls.primary_color[1], \ - self.theme_cls.primary_color[2] - self.color = self.theme_cls.text_color - self.primary_dark = self.theme_cls.primary_dark[0] / 2, self.theme_cls.primary_dark[1] / 2, \ - self.theme_cls.primary_dark[2] / 2 - self.on_ampm() - if self.hours >= 12: - self._am = False - self.bind(time_list=self.on_time_list, - picker=self._switch_picker, - _am=self.on_ampm, - primary_dark=self._get_ampm_text) - self._h_picker = CircularHourPicker() - self.h_picker_touch = False - self._m_picker = CircularMinutePicker() - self.animating = False - Clock.schedule_once(self.on_selected) - Clock.schedule_once(self.on_time_list) - Clock.schedule_once(self._init_later) - Clock.schedule_once(lambda *a: self._switch_picker(noanim=True)) - - def _init_later(self, *args): - self.ids.timelabel.bind(on_ref_press=self.on_ref_press) - self.ids.ampmlabel.bind(on_ref_press=self.on_ref_press) - - def on_ref_press(self, ign, ref): - if not self.animating: - if ref == "hours": - self.picker = "hours" - elif ref == "minutes": - self.picker = "minutes" - if ref == "am": - self._am = True - elif ref == "pm": - self._am = False - - def on_selected(self, *a): - if not self._picker: - return - if self.picker == "hours": - hours = self._picker.selected if self._am else self._picker.selected + 12 - if hours == 24 and not self._am: - hours = 12 - elif hours == 12 and self._am: - hours = 0 - self.hours = hours - elif self.picker == "minutes": - self.minutes = self._picker.selected - - def on_time_list(self, *a): - if not self._picker: - return - self._h_picker.selected = self.hours == 0 and 12 or self._am and self.hours or self.hours - 12 - self._m_picker.selected = self.minutes - self.on_selected() - - def on_ampm(self, *a): - if self._am: - self.hours = self.hours if self.hours < 12 else self.hours - 12 - else: - self.hours = self.hours if self.hours >= 12 else self.hours + 12 - - def is_animating(self, *args): - self.animating = True - - def is_not_animating(self, *args): - self.animating = False - - def on_touch_down(self, touch): - if not self._h_picker.collide_point(*touch.pos): - self.h_picker_touch = False - else: - self.h_picker_touch = True - super(CircularTimePicker, self).on_touch_down(touch) - - def on_touch_up(self, touch): - try: - if not self.h_picker_touch: - return - if not self.animating: - if touch.grab_current is not self: - if self.picker == "hours": - self.picker = "minutes" - except AttributeError: - pass - super(CircularTimePicker, self).on_touch_up(touch) - - def _switch_picker(self, *a, **kw): - noanim = "noanim" in kw - if noanim: - noanim = kw["noanim"] - - try: - container = self.ids.picker_container - except (AttributeError, NameError): - Clock.schedule_once(lambda *a: self._switch_picker(noanim=noanim)) - - if self.picker == "hours": - picker = self._h_picker - prevpicker = self._m_picker - elif self.picker == "minutes": - picker = self._m_picker - prevpicker = self._h_picker - - if len(self._bound) > 0: - prevpicker.unbind(selected=self.on_selected) - self.unbind(**self._bound) - picker.bind(selected=self.on_selected) - self._bound = {"selector_color": picker.setter("selector_color"), - "color": picker.setter("color"), - "selector_alpha": picker.setter("selector_alpha")} - self.bind(**self._bound) - - if len(container._bound) > 0: - container.unbind(**container._bound) - container._bound = {"size": picker.setter("size"), - "pos": picker.setter("pos")} - container.bind(**container._bound) - - picker.pos = container.pos - picker.size = container.size - picker.selector_color = self.selector_color - picker.color = self.color - picker.selector_alpha = self.selector_alpha - if noanim: - if prevpicker in container.children: - container.remove_widget(prevpicker) - if picker.parent: - picker.parent.remove_widget(picker) - container.add_widget(picker) - else: - self.is_animating() - if prevpicker in container.children: - anim = Animation(scale=1.5, d=.5, t="in_back") & Animation(opacity=0, d=.5, t="in_cubic") - anim.start(prevpicker) - Clock.schedule_once(lambda *y: container.remove_widget(prevpicker), .5) # .31) - picker.scale = 1.5 - picker.opacity = 0 - if picker.parent: - picker.parent.remove_widget(picker) - container.add_widget(picker) - anim = Animation(scale=1, d=.5, t="out_back") & Animation(opacity=1, d=.5, t="out_cubic") - anim.bind(on_complete=self.is_not_animating) - Clock.schedule_once(lambda *y: anim.start(picker), .3) - - -if __name__ == "__main__": - from kivy.base import runTouchApp - - c = CircularTimePicker() - runTouchApp(c) diff --git a/src/main.py b/src/main.py index 71a4cb50..e1644436 100644 --- a/src/main.py +++ b/src/main.py @@ -1,6 +1,11 @@ """This module is for thread start.""" import state +import sys from bitmessagemain import main +from termcolor import colored +print(colored('kivy is not supported at the moment for this version..', 'red')) +sys.exit() + if __name__ == '__main__': state.kivy = True diff --git a/src/navigationdrawer/__init__.py b/src/navigationdrawer/__init__.py deleted file mode 100644 index a8fa5ce7..00000000 --- a/src/navigationdrawer/__init__.py +++ /dev/null @@ -1,82 +0,0 @@ -# -*- coding: utf-8 -*- -from kivy.animation import Animation -from kivy.lang import Builder -from kivy.properties import StringProperty, ObjectProperty -from kivymd.elevationbehavior import ElevationBehavior -from kivymd.icon_definitions import md_icons -from kivymd.label import MDLabel -from kivymd.list import OneLineIconListItem, ILeftBody, BaseListItem -from kivymd.slidingpanel import SlidingPanel -from kivymd.theming import ThemableBehavior - -Builder.load_string(''' - - canvas: - Color: - rgba: root.parent.parent.theme_cls.divider_color - Line: - points: self.x, self.y, self.x+self.width,self.y - - - widget_list: widget_list - elevation: 0 - canvas: - Color: - rgba: root.theme_cls.bg_light - Rectangle: - size: root.size - pos: root.pos - BoxLayout: - size_hint: (1, .4) - NavDrawerToolbar: - padding: 10, 10 - canvas.after: - Color: - rgba: (1, 1, 1, 1) - RoundedRectangle: - size: (self.size[1]-dp(14), self.size[1]-dp(14)) - pos: (self.pos[0]+(self.size[0]-self.size[1])/2, self.pos[1]+dp(7)) - source: root.image_source - radius: [self.size[1]-(self.size[1]/2)] - - ScrollView: - do_scroll_x: False - MDList: - id: ml - id: widget_list - - - NDIconLabel: - id: _icon - font_style: 'Icon' - theme_text_color: 'Secondary' -''') - - -class NavigationDrawer(SlidingPanel, ThemableBehavior, ElevationBehavior): - image_source = StringProperty() - widget_list = ObjectProperty() - - def add_widget(self, widget, index=0): - if issubclass(widget.__class__, BaseListItem): - self.widget_list.add_widget(widget, index) - widget.bind(on_release=lambda x: self.toggle()) - else: - super(NavigationDrawer, self).add_widget(widget, index) - - def _get_main_animation(self, duration, t, x, is_closing): - a = super(NavigationDrawer, self)._get_main_animation(duration, t, x, - is_closing) - a &= Animation(elevation=0 if is_closing else 5, t=t, duration=duration) - return a - - -class NDIconLabel(ILeftBody, MDLabel): - pass - - -class NavigationDrawerIconButton(OneLineIconListItem): - icon = StringProperty() - - def on_icon(self, instance, value): - self.ids['_icon'].text = u"{}".format(md_icons[value])