Added Navigation Drawer UI with create feature
parent
3b4d73d291
commit
bb8d4c5a1f
@ -1,167 +1,173 @@
|
||||
#:import FadeTransition kivy.uix.screenmanager.FadeTransition
|
||||
|
||||
<Display>:
|
||||
BoxLayout:
|
||||
orientation: "vertical"
|
||||
BoxLayout:
|
||||
size_hint: 1, None
|
||||
<Navigator>:
|
||||
id: nav_drawer
|
||||
NavigationDrawerIconButton:
|
||||
Button:
|
||||
id: btn
|
||||
background_color:app.theme_cls.primary_dark
|
||||
text: 'BM-2cSvewtJw8o8eqcFzmLeXHza4BVsRsirKk'
|
||||
on_release: dropdown.open(self)
|
||||
pos_hint: {'x': 0, 'y': 0.3}
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
Button:
|
||||
text: 'messages'
|
||||
on_release: sm.current = 'screen_one'
|
||||
background_color: (0,0,0,0)
|
||||
color: 0,0,0,1
|
||||
Button:
|
||||
text: 'send'
|
||||
on_release: sm.current = 'screen_two'
|
||||
background_color: (0,0,0,0)
|
||||
color: 0,0,0,1
|
||||
Button:
|
||||
text: 'subscription'
|
||||
on_release: sm.current = 'screen_three'
|
||||
background_color: (0,0,0,0)
|
||||
color: 0,0,0,1
|
||||
Button:
|
||||
text: 'four'
|
||||
on_release: sm.current = 'screen_four'
|
||||
background_color: (0,0,0,0)
|
||||
color: 0,0,0,1
|
||||
|
||||
Button:
|
||||
text: 'chans'
|
||||
on_release: sm.current = 'screen_five'
|
||||
background_color: (0,0,0,0)
|
||||
color: 0,0,0,1
|
||||
Button:
|
||||
text: 'blacklist'
|
||||
on_release: sm.current = 'screen_six'
|
||||
background_color: (0,0,0,0)
|
||||
color: 0,0,0,1
|
||||
DropDown:
|
||||
|
||||
ScreenManager:
|
||||
id: sm
|
||||
transition: FadeTransition()
|
||||
Screen_One:
|
||||
Screen_Two:
|
||||
Screen_three:
|
||||
Screen_four:
|
||||
Screen_five:
|
||||
Screen_six:
|
||||
EmailScreen:
|
||||
id: dropdown
|
||||
on_parent: self.dismiss()
|
||||
on_select: btn.text = '{}'.format(args[1])
|
||||
Button:
|
||||
background_color:app.theme_cls.primary_dark
|
||||
text: 'BM-2cSvewtJw8o8eqcFzmLeXHza4BVsRsirKk'
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
on_release: dropdown.select('BM-2cSvewtJw8o8eqcFzmLeXHza4BVsRsirKk')
|
||||
on_release: app.root.ids.scr_mngr.current = 'dialog'
|
||||
|
||||
<Screen_One>:
|
||||
name: 'screen_one'
|
||||
BoxLayout:
|
||||
padding: 10,10,10,300
|
||||
orientation: "vertical"
|
||||
Button:
|
||||
text: "create"
|
||||
size_hint_y: 0.3
|
||||
size_hint_x: 0.1
|
||||
color: 0,0,0,1
|
||||
background_color: (0,0,0,0)
|
||||
Button:
|
||||
text: "inbox"
|
||||
background_color: (0,0,0,0)
|
||||
size_hint_y: 0.3
|
||||
size_hint_x: 0.1
|
||||
color: 0,0,0,1
|
||||
Button:
|
||||
background_color:app.theme_cls.primary_dark
|
||||
text: 'BM-2cSvewtJw8o8eqcFzmLeXHza4BVsRsirKk'
|
||||
size_hint_y: None
|
||||
height: '48dp'
|
||||
on_release: dropdown.select('BM-2cSvewtJw8o8eqcFzmLeXHza4BVsRsirKk')
|
||||
on_release: app.root.ids.scr_mngr.current = 'button'
|
||||
|
||||
NavigationDrawerIconButton:
|
||||
icon: 'email'
|
||||
text: "inbox"
|
||||
on_release: app.root.ids.scr_mngr.current = 'inbox'
|
||||
NavigationDrawerIconButton:
|
||||
icon: 'email'
|
||||
text: "sent"
|
||||
on_release: app.root.ids.scr_mngr.current = 'sent'
|
||||
NavigationDrawerIconButton:
|
||||
icon: 'email'
|
||||
text: "trash"
|
||||
on_release: app.root.ids.scr_mngr.current = 'trash'
|
||||
NavigationDrawerIconButton:
|
||||
icon: 'email'
|
||||
text: "dialog"
|
||||
on_release: app.root.ids.scr_mngr.current = 'dialog'
|
||||
NavigationDrawerIconButton:
|
||||
icon: 'email'
|
||||
text: "test"
|
||||
on_release: app.root.ids.scr_mngr.current = 'test'
|
||||
|
||||
|
||||
|
||||
BoxLayout:
|
||||
orientation: 'vertical'
|
||||
Toolbar:
|
||||
id: toolbar
|
||||
title: 'PyBitmessage'
|
||||
background_color: app.theme_cls.primary_dark
|
||||
left_action_items: [['menu', lambda x: app.nav_drawer.toggle()]]
|
||||
Button:
|
||||
text: "new"
|
||||
background_color: (0,0,0,0)
|
||||
size_hint_y: 0.3
|
||||
size_hint_x: 0.1
|
||||
text:"EXIT"
|
||||
color: 0,0,0,1
|
||||
on_press:
|
||||
root.manager.current = 'email'
|
||||
Button:
|
||||
text: "sents"
|
||||
background_color: (0,0,0,0)
|
||||
size_hint_y: 0.3
|
||||
size_hint_y: 0.1
|
||||
size_hint_x: 0.1
|
||||
color: 0,0,0,1
|
||||
|
||||
<Screen_Two>:
|
||||
name: 'screen_two'
|
||||
Label:
|
||||
text: "Two"
|
||||
|
||||
<Screen_three>:
|
||||
name: 'screen_three'
|
||||
Label:
|
||||
text: "Three"
|
||||
|
||||
<Screen_four>:
|
||||
name: 'screen_four'
|
||||
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
|
||||
|
||||
Button:
|
||||
height:100
|
||||
size_hint_y: 0.1
|
||||
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
|
||||
x: self.parent.x + self.parent.width - 50
|
||||
size: 70, 70
|
||||
<Inbox>:
|
||||
name: 'inbox'
|
||||
|
||||
<Sent>:
|
||||
name: 'sent'
|
||||
|
||||
<Trash>:
|
||||
name: 'trash'
|
||||
Label:
|
||||
text: "four"
|
||||
|
||||
<Screen_five>:
|
||||
name: 'screen_five'
|
||||
text:"I am in card"
|
||||
color: 0,0,0,1
|
||||
<Dialog>:
|
||||
name: 'dialog'
|
||||
Label:
|
||||
text: "Two"
|
||||
|
||||
<Screen_six>:
|
||||
name: 'screen_six'
|
||||
text:"I have a good dialox box"
|
||||
color: 0,0,0,1
|
||||
<Test>:
|
||||
name: 'test'
|
||||
Label:
|
||||
text: "Two"
|
||||
|
||||
<EmailScreen>:
|
||||
name: 'email'
|
||||
BoxLayout:
|
||||
padding: 100,10,100,100
|
||||
id: login_layout
|
||||
orientation: "vertical"
|
||||
GridLayout:
|
||||
rows: 2
|
||||
orientation: 'vertical'
|
||||
spacing: 10
|
||||
text:"a rapid data env"
|
||||
color: 0,0,0,1
|
||||
|
||||
<Create>:
|
||||
name: 'create'
|
||||
GridLayout:
|
||||
rows: 5
|
||||
cols: 1
|
||||
padding: 100,100,100,100
|
||||
spacing: 50
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
height: '32dp'
|
||||
Label:
|
||||
text: 'From: '
|
||||
background_color: (0,0,0,0)
|
||||
text: 'FROM'
|
||||
color: 0,0,0,1
|
||||
font_size: 18
|
||||
pos_hint: {"x":.15,"y":1}
|
||||
text_size: root.width-20, 20
|
||||
|
||||
TextInput:
|
||||
multiline:False
|
||||
size_hint: 1,.4
|
||||
hint_text: 'email'
|
||||
|
||||
GridLayout:
|
||||
rows: 2
|
||||
orientation: 'vertical'
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
height: '32dp'
|
||||
Label:
|
||||
text: 'To: '
|
||||
background_color: (0,0,0,0)
|
||||
text: 'TO'
|
||||
color: 0,0,0,1
|
||||
font_size: 18
|
||||
pos_hint: {"x":.15,"y":.5}
|
||||
text_size: root.width-20, 20
|
||||
|
||||
TextInput:
|
||||
multiline:False
|
||||
size_hint: 1,.4
|
||||
pos_hint: {"x":.2,"y":.5}
|
||||
hint_text: 'email'
|
||||
|
||||
GridLayout:
|
||||
rows: 2
|
||||
orientation: 'vertical'
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
height: '32dp'
|
||||
Label:
|
||||
text: 'Message'
|
||||
background_color: (0,0,0,0)
|
||||
text: 'SUBJECT'
|
||||
color: 0,0,0,1
|
||||
pos_hint: {"x":.15,"y":.5}
|
||||
font_size: 18
|
||||
text_size: root.width-20, 20
|
||||
TextInput:
|
||||
hint_text: 'subject'
|
||||
|
||||
BoxLayout:
|
||||
size_hint_y: None
|
||||
height: '32dp'
|
||||
Label:
|
||||
text: 'BODY'
|
||||
color: 0,0,0,1
|
||||
TextInput:
|
||||
id: msg
|
||||
multiline:True
|
||||
size_hint: 1,2
|
||||
|
||||
Button:
|
||||
text: "SEND"
|
||||
size_hint_y: 0.1
|
||||
size_hint_x: 0.2
|
||||
pos_hint: {"x":.15,"y":1}
|
||||
Button:
|
||||
text: 'SEND'
|
||||
size_hint_y: 0.1
|
||||
size_hint_x: 0.3
|
||||
height: '32dp'
|
||||
pos_hint: {'x': .5, 'y': 0.1}
|
@ -1,97 +1,79 @@
|
||||
import time
|
||||
|
||||
import os
|
||||
from kivy.app import App
|
||||
from kivy.core.window import Window
|
||||
from kivy.lang import Builder
|
||||
from kivy.uix.screenmanager import Screen
|
||||
from kivy.properties import ObjectProperty, StringProperty
|
||||
from kivymd.theming import ThemeManager
|
||||
from kivy.uix.widget import Widget
|
||||
from navigationdrawer import NavigationDrawer
|
||||
from kivymd.toolbar import Toolbar
|
||||
from kivy.uix.dropdown import DropDown
|
||||
from kivy.uix.button import Button
|
||||
from kivy.uix.gridlayout import GridLayout
|
||||
from kivy.uix.label import Label
|
||||
from kivy.uix.textinput import TextInput
|
||||
from kivy.clock import Clock
|
||||
from kivy.uix.boxlayout import BoxLayout
|
||||
# from kivy.uix.gridlayout import GridLayout
|
||||
|
||||
from debug import logger
|
||||
from kivy.core.window import Window
|
||||
from os import environ
|
||||
import shutdown
|
||||
|
||||
from addresses import addBMIfNotPresent, decodeAddress
|
||||
class NavigateApp(App):
|
||||
theme_cls = ThemeManager()
|
||||
nav_drawer = ObjectProperty()
|
||||
|
||||
from bmconfigparser import BMConfigParser
|
||||
def build(self):
|
||||
main_widget = Builder.load_file(os.path.join(os.path.dirname(__file__), 'main.kv'))
|
||||
self.nav_drawer = Navigator()
|
||||
return main_widget
|
||||
|
||||
from helper_ackPayload import genAckPayload
|
||||
def say_exit(self):
|
||||
print ("**************************EXITING FROM APPLICATION*****************************")
|
||||
App.get_running_app().stop()
|
||||
shutdown.doCleanShutdown()
|
||||
Window.close()
|
||||
|
||||
from helper_sql import sqlExecute
|
||||
class Navigator(NavigationDrawer):
|
||||
image_source = StringProperty('images/me.jpg')
|
||||
title = StringProperty('Navigation')
|
||||
|
||||
import queues
|
||||
|
||||
import shutdown
|
||||
statusIconColor = 'red'
|
||||
class Inbox(Screen):
|
||||
def __init__ (self,**kwargs):
|
||||
super (Inbox, self).__init__(**kwargs)
|
||||
val_y = .1
|
||||
val_z = 0
|
||||
my_box1 = BoxLayout(orientation='vertical')
|
||||
for i in range(1, 5):
|
||||
my_box1.add_widget(Label(text="I am in inbox", size_hint = (.3,.1), pos_hint = {'x': val_z,'top': val_y},color = (0,0,0,1), background_color = (0,0,0,0)))
|
||||
val_y+=.1
|
||||
self.add_widget(my_box1)
|
||||
|
||||
class Sent(Screen):
|
||||
def __init__ (self,**kwargs):
|
||||
super (Sent, self).__init__(**kwargs)
|
||||
val_y = .1
|
||||
val_z = 0
|
||||
my_box1 = BoxLayout(orientation='vertical')
|
||||
for i in range(1, 5):
|
||||
my_box1.add_widget(Label(text="I am in sent", size_hint = (.3,.1), pos_hint = {'x': val_z,'top': val_y},color = (0,0,0,1), background_color = (0,0,0,0)))
|
||||
val_y+=.1
|
||||
self.add_widget(my_box1)
|
||||
|
||||
class LoginScreen(BoxLayout):
|
||||
"""This will use for sending message to recipents from mobile client."""
|
||||
class Trash(Screen):
|
||||
pass
|
||||
|
||||
def send(self):
|
||||
"""It is used for sending message with subject and body."""
|
||||
queues.apiAddressGeneratorReturnQueue.queue.clear()
|
||||
streamNumberForAddress = 1
|
||||
label = "CisDevelper"
|
||||
eighteenByteRipe = False
|
||||
nonceTrialsPerByte = 1000
|
||||
payloadLengthExtraBytes = 1000
|
||||
queues.addressGeneratorQueue.put((
|
||||
'createRandomAddress', 4,
|
||||
streamNumberForAddress, label, 1,
|
||||
"", eighteenByteRipe, nonceTrialsPerByte,
|
||||
payloadLengthExtraBytes
|
||||
))
|
||||
fromAddress = queues.apiAddressGeneratorReturnQueue.get()
|
||||
toAddress = "BM-2cWyUfBdY2FbgyuCb7abFZ49JYxSzUhNFe"
|
||||
message = self.ids.user_input.text
|
||||
subject = 'Test'
|
||||
encoding = 3
|
||||
sendMessageToPeople = True
|
||||
if sendMessageToPeople:
|
||||
if toAddress != '':
|
||||
status, addressVersionNumber, streamNumber, ripe = decodeAddress(
|
||||
toAddress)
|
||||
if status == 'success':
|
||||
toAddress = addBMIfNotPresent(toAddress)
|
||||
|
||||
if addressVersionNumber > 4 or addressVersionNumber <= 1:
|
||||
logger.info("addressVersionNumber > 4 or addressVersionNumber <= 1")
|
||||
if streamNumber > 1 or streamNumber == 0:
|
||||
logger.info("streamNumber > 1 or streamNumber == 0")
|
||||
if statusIconColor == 'red':
|
||||
logger.info("shared.statusIconColor == 'red'")
|
||||
stealthLevel = BMConfigParser().safeGetInt(
|
||||
'bitmessagesettings', 'ackstealthlevel')
|
||||
ackdata = genAckPayload(streamNumber, stealthLevel)
|
||||
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'))
|
||||
queues.workerQueue.put(('sendmessage', toAddress))
|
||||
return None
|
||||
class Dialog(Screen):
|
||||
pass
|
||||
|
||||
def sayexit(self):
|
||||
"""Method will exit the application screen."""
|
||||
shutdown.doCleanShutdown()
|
||||
Window.close()
|
||||
|
||||
class Test(Screen):
|
||||
pass
|
||||
|
||||
class MainApp(App):
|
||||
"""The App class is the base for creating Kivy applications
|
||||
Think of it as your main entry point into the Kivy run loop."""
|
||||
|
||||
def build(self):
|
||||
"""To initialize an app with a widget tree, we need to override the build().
|
||||
method in our app class and return the widget tree which we have constructed..
|
||||
"""
|
||||
return LoginScreen()
|
||||
class Create(Screen):
|
||||
pass
|
||||
|
||||
if __name__ == '__main__':
|
||||
NavigateApp().run()
|
Binary file not shown.
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
@ -0,0 +1,21 @@
|
||||
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.
|
@ -0,0 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import os
|
||||
|
||||
path = os.path.dirname(__file__)
|
||||
fonts_path = os.path.join(path, "fonts/")
|
||||
images_path = os.path.join(path, 'images/')
|
@ -0,0 +1,254 @@
|
||||
# -*- 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
|
||||
|
||||
|
||||
<MDAccordionItem>:
|
||||
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()
|
@ -0,0 +1,23 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from kivy.lang import Builder
|
||||
from kivy.properties import BoundedNumericProperty, ReferenceListProperty
|
||||
from kivy.uix.widget import Widget
|
||||
|
||||
Builder.load_string('''
|
||||
<BackgroundColorBehavior>
|
||||
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)
|
@ -0,0 +1,211 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Bottom Sheets
|
||||
=============
|
||||
|
||||
`Material Design spec Bottom Sheets page <http://www.google.com/design/spec/components/bottom-sheets.html>`_
|
||||
|
||||
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('''
|
||||
<MDBottomSheet>
|
||||
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
|
||||
<ListBSIconLeft>
|
||||
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('''
|
||||
<GridBSItem>
|
||||
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)
|
@ -0,0 +1,453 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
Buttons
|
||||
=======
|
||||
|
||||
`Material Design spec, Buttons page <https://www.google.com/design/spec/components/buttons.html>`_
|
||||
|
||||
`Material Design spec, Buttons: Floating Action Button page <https://www.google.com/design/spec/components/buttons-floating-action-button.html>`_
|
||||
|
||||
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
|
||||
<MDIconButton>
|
||||
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'
|
||||
|
||||
<MDFlatButton>
|
||||
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
|
||||
|
||||
<MDRaisedButton>:
|
||||
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'
|
||||
|
||||
<MDFloatingActionButton>:
|
||||
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< |