from kivy.app import App
from kivy.uix.widget import Widgetfrom kivy.uix.boxlayout import BoxLayoutfrom kivy.uix.floatlayout import FloatLayoutfrom kivy.uix.anchorlayout import AnchorLayoutfrom kivy.uix.screenmanager import ScreenManager, Screen, CardTransitionfrom kivy.uix.button import Buttonfrom kivy.uix.behaviors import ButtonBehaviorfrom kivy.uix.image import Imagefrom kivy.uix.label import Label
from kivy.uix.actionbar import ActionBar, ActionItemfrom kivy.uix.textinput import TextInputfrom kivy.properties import NumericProperty, StringPropertyfrom kivy.uix.dropdown import DropDownfrom kivy.uix.popup import Popupfrom calendar_ui import DatePicker, CalendarWidget
class CustomTextInput(TextInput): # Numeric property defined for use in both Python and Kivy (binding) max_characters = NumericProperty(0) # Override the default behaviour of the insert_text method def insert_text(self, substring, from_undo=False): if len(self.text)==self.max_characters and self.max_characters>0: substring="" TextInput.insert_text(self, substring, from_undo)
class ImageButton(ButtonBehavior, Image): pass
class CustomActionButton(ImageButton, ActionItem): pass
class ImageLabel(BoxLayout): source = StringProperty('atlas://data/images/defaulttheme/audio-volume-high') text = StringProperty('default text')
class ImageLabelButton(ButtonBehavior, ImageLabel): pass
class ImageLabelButtonTop(ButtonBehavior, ImageLabel): pass
class SivaLoginScreen(Screen): def t_authentication(self):
App.get_running_app().root.current='verify_screen' App.get_running_app().root.transition.direction='left'
def l_authentication(self): App.get_running_app().root.current='verify_screen' App.get_running_app().root.transition.direction='left'
class SivaVerifyScreen(Screen): def back_to_login(self): App.get_running_app().root.current='login_screen' App.get_running_app().root.transition.direction='right'
def code_verification(self): App.get_running_app().root.current='status_screen' App.get_running_app().root.transition.direction='left'
class SivaStatusScreen(Screen): def to_statusscreen(self): App.get_running_app().root.current='status_screen' App.get_running_app().root.transition.direction='left'
def to_accountsscreen(self): App.get_running_app().root.current='accounts_screen' App.get_running_app().root.transition.direction='left'
def to_botscreen(self): App.get_running_app().root.current='bot_screen' App.get_running_app().root.transition.direction='left'
def to_logout(self): App.get_running_app().root.current='login_screen' App.get_running_app().root.transition.direction='right' def new_status_entry(self): App.get_running_app().root.current='newstatus_screen' App.get_running_app().root.transition.direction='left'
class SivaAccountsScreen(Screen): def to_statusscreen(self): App.get_running_app().root.current='status_screen' App.get_running_app().root.transition.direction='right'
def to_accountsscreen(self): App.get_running_app().root.current='accounts_screen' App.get_running_app().root.transition.direction='left'
def to_botscreen(self): App.get_running_app().root.current='bot_screen' App.get_running_app().root.transition.direction='left'
def to_logout(self): App.get_running_app().root.current='login_screen' App.get_running_app().root.transition.direction='right'
class SivaBotScreen(Screen): def to_statusscreen(self): App.get_running_app().root.current='status_screen' App.get_running_app().root.transition.direction='right'
def to_accountsscreen(self): App.get_running_app().root.current='accounts_screen' App.get_running_app().root.transition.direction='right'
def to_botscreen(self): App.get_running_app().root.current='bot_screen' App.get_running_app().root.transition.direction='left'
def to_logout(self): App.get_running_app().root.current='login_screen' App.get_running_app().root.transition.direction='right'
class SivaTermsScreen(Screen): pass
class NewStatusScreen(Screen): def back_to_status(self): App.get_running_app().root.current='status_screen' App.get_running_app().root.transition.direction='right'
class SivaScreenManager(ScreenManager): pass
class SivaApp(App): def build(self): # Initialize root widget # Screen Manager Instance ssm=SivaScreenManager(transition=CardTransition()) # Login Screen Instance sls=SivaLoginScreen() # Verify Screen Instance svs=SivaVerifyScreen() # Status Screen Instance sss=SivaStatusScreen() # Accounts Screen Instance sas=SivaAccountsScreen() # Bot Screen Instance sbs=SivaBotScreen() # New Status Screen Instance nss=NewStatusScreen() # Create widget tree. Screen Manager is the root widget. ssm.add_widget(sls) ssm.add_widget(svs) ssm.add_widget(sss) ssm.add_widget(sas) ssm.add_widget(sbs) ssm.add_widget(nss) return ssm
if __name__ == '__main__': # Run application SivaApp().run()
<Label>: -font_name: 'roboto/Roboto-Regular.ttf'
<ImageButton>: keep_ratio: True
<CustomTextInput>: use_bubble: True use_handles: True
<CustomActionButton>: size_hint_x: 0.05 size_hint_min_x: 48
<SivaLoginScreen>: name: 'login_screen' canvas.before: Color: rgba: 195/255, 60/255, 35/255, 1 Rectangle: pos: self.pos size: self.size BoxLayout: id: login_layout orientation: 'vertical' size_hint: 0.4, 0.8 pos_hint: {'center_x':0.5, 'center_y':0.5} Image: id: login_logo_siva source: 'images/sivalogo1.png' keep_ratio: True BoxLayout: id: login_slogan_box orientation: 'vertical' Label: id: login_label_space1 Label: id: login_label_siva markup: True font_name: 'roboto/Roboto-Medium.ttf' text: '[color=#FDFD98]S[/color][color=#B29DD9]I[/color][color=#77DD77]V[/color][color=#779ECB]A[/color]' font_size: '40sp' Label: id: login_label_space2 Label: id: login_label_slogan1 markup: True font_name: 'roboto/Roboto-Regular.ttf' text: '[color=#FDFD98]ABCD EFGH[/color]' font_size: '13sp' Label: id: login_label_slogan2 markup: True font_name: 'roboto/Roboto-Regular.ttf' text: '[color=#FDFD98]IJKL MNOP[/color]' font_size: '13sp' BoxLayout: id: login_button_layout orientation: 'horizontal' spacing: 1 ImageButton: id: t_button source: {'normal': 'images/t-circled-96.png', 'down': 'images/t-96.png'} [self.state] on_release: root.t_authentication() ImageButton: id: l_button source: {'normal': 'images/l-circled-96.png', 'down': 'images/l-2-96.png'} [self.state] on_release: root.l_authentication()
<SivaVerifyScreen>: name: 'verify_screen' canvas.before: Color: rgba: 195/255, 60/255, 35/255, 1 Rectangle: pos: self.pos size: self.size AnchorLayout: id: verify_backbtn_layout anchor_x: 'left' anchor_y: 'top' ImageButton: id: verify_back_button size_hint: 0.1, 0.1 source: {'normal': 'images/chevron-left-96.png', 'down': 'images/chevron-left-96.png'} [self.state] on_release: root.back_to_login() BoxLayout: id: verify_layout orientation: 'vertical' size_hint: 0.6, 0.6 pos_hint: {'center_x':0.5, 'center_y':0.5} Label: id: verify_label markup: True font_name: 'roboto/Roboto-Regular.ttf' text: 'Verification Code' font_size: '16sp' BoxLayout: id: verify_textinput orientation: 'vertical' CustomTextInput: id: verify_inputbox multiline: False focus: True hint_text: '1234567' font_size: '30sp' max_characters: 10 input_filter: 'int' Label: id: verify_space1 BoxLayout: id: verify_btn_layout orientation: 'horizontal' Label: id: placeholder_label1 ImageButton: id: verify_button source: {'normal': 'images/lock-96.png', 'down': 'images/privacy-96.png'} [self.state] on_release: root.code_verification() Label: id: placeholder_label2
<SivaStatusScreen>: name: 'status_screen' canvas.before: Color: rgba: 255/255, 255/255, 255/255, 1 Rectangle: pos: self.pos size: self.size AnchorLayout: id: status_add anchor_x: 'right' anchor_y: 'bottom' ImageButton: id: status_addbtn source: {'normal': 'images/plus-96.png', 'down': 'images/plusblue-96.png'} [self.state] size_hint: 0.2, 0.2 on_release: root.new_status_entry() BoxLayout: id: status_layout orientation: 'vertical' BoxLayout: id: actionbar_layout size_hint_y: None height: 48 ActionBar: id: status_actionbar pos_hint: {'top': 1} background_image: '' background_color: 195/255, 60/255, 35/255, 1 ActionView: use_separator: True ActionPrevious: title: 'SIVA' with_previous: False ActionOverflow: CustomActionButton: id: status-button important: True source: {'normal': 'images/communicationgreen-48.png', 'down': 'images/communication-48.png'} [self.state] on_release: root.to_statusscreen() CustomActionButton: id: accounts-button important: True source: {'normal': 'images/key-48.png', 'down': 'images/keygreen-48.png'} [self.state] on_release: root.to_accountsscreen() CustomActionButton: id: bot-button important: True source: {'normal': 'images/bot-48.png', 'down': 'images/botgreen-48.png'} [self.state] on_release: root.to_botscreen() CustomActionButton: id: logout-button important: True source: {'normal': 'images/shutdown-48.png', 'down': 'images/shutdowngreen-48.png'} [self.state] on_release: root.to_logout() BoxLayout: id: status_display orientation: 'vertical' BoxLayout: id: status_label size_hint_y: None height: 40 BoxLayout: orientation: 'horizontal' BoxLayout: orientation: 'horizontal' Image: keep_ratio: True source: 'images/communication-48.png' Label: text: 'Status' markup: True color: 0, 0, 0, 1 ImageLabelButtonTop: # conflict in the on_release defined for ImageLabelButton and this instance. id: parent_button source: 'images/expand-arrow-48.png' text: 'User' on_release: # root.add_dd_values() dropdown.open(self) on_parent: dropdown.dismiss() size_hint_y: None height: '40dp' DropDown: id: dropdown on_select: # args is a reserved keyword which returns only two values: object alias (0) and data (1). parent_button.text = args[1][0] parent_button.source = args[1][1] # Invoked inside dropdown # root - Screen, self - DropDown object ImageLabelButton: source: 'images/t-circled-48.png' text: 'Test' ImageLabelButton: source: 'images/l-circled-48.png' text: 'Load' BoxLayout: id: status_content
<SivaAccountsScreen>: name: 'accounts_screen' canvas.before: Color: rgba: 255/255, 255/255, 255/255, 1 Rectangle: pos: self.pos size: self.size AnchorLayout: id: accounts_add anchor_x: 'right' anchor_y: 'bottom' ImageButton: id: accounts_addbtn source: {'normal': 'images/plus-96.png', 'down': 'images/plusblue-96.png'} [self.state] size_hint: 0.2, 0.2 BoxLayout: id: accounts_layout orientation: 'vertical' BoxLayout: id: actionbar_layout2 size_hint_y: None height: 48 ActionBar: id: accounts_actionbar pos_hint: {'top': 1} background_image: '' background_color: 195/255, 60/255, 35/255, 1 ActionView: use_separator: True ActionPrevious: title: 'S.I.V.A' with_previous: False ActionOverflow: CustomActionButton: id: status-button2 important: True source: {'normal': 'images/communication-48.png', 'down': 'images/communicationgreen-48.png'} [self.state] on_release: root.to_statusscreen() CustomActionButton: id: accounts-button2 important: True source: {'normal': 'images/keygreen-48.png', 'down': 'images/key-48.png'} [self.state] on_release: root.to_accountsscreen() CustomActionButton: id: bot-button2 important: True source: {'normal': 'images/bot-48.png', 'down': 'images/botgreen-48.png'} [self.state] on_release: root.to_botscreen() CustomActionButton: id: logout-button2 important: True source: {'normal': 'images/shutdown-48.png', 'down': 'images/shutdowngreen-48.png'} [self.state] on_release: root.to_logout() BoxLayout: id: accounts_display
<SivaBotScreen>: name: 'bot_screen' canvas.before: Color: rgba: 255/255, 255/255, 255/255, 1 Rectangle: pos: self.pos size: self.size AnchorLayout: id: bot_add anchor_x: 'right' anchor_y: 'bottom' ImageButton: id: bot_addbtn source: {'normal': 'images/plus-96.png', 'down': 'images/plusblue-96.png'} [self.state] size_hint: 0.2, 0.2 BoxLayout: id: bot_layout orientation: 'vertical' BoxLayout: id: actionbar_layout3 size_hint_y: None height: 48 ActionBar: id: bot_actionbar pos_hint: {'top': 1} background_image: '' background_color: 195/255, 60/255, 35/255, 1 ActionView: use_separator: True ActionPrevious: title: 'SIVA' with_previous: False ActionOverflow: CustomActionButton: id: status-button3 important: True source: {'normal': 'images/communication-48.png', 'down': 'images/communicationgreen-48.png'} [self.state] on_release: root.to_statusscreen() CustomActionButton: id: accounts-button3 important: True source: {'normal': 'images/key-48.png', 'down': 'images/keygreen-48.png'} [self.state] on_release: root.to_accountsscreen() CustomActionButton: id: bot-button3 important: True source: {'normal': 'images/botgreen-48.png', 'down': 'images/bot-48.png'} [self.state] on_release: root.to_botscreen() CustomActionButton: id: logout-button3 important: True source: {'normal': 'images/shutdown-48.png', 'down': 'images/shutdowngreen-48.png'} [self.state] on_release: root.to_logout() BoxLayout: id: bot_display
<NewStatusScreen>: name: 'newstatus_screen' canvas.before: Color: rgba: 255/255, 255/255, 255/255, 1 Rectangle: pos: self.pos size: self.size AnchorLayout: id: newstatus_backbtn_layout anchor_x: 'left' anchor_y: 'top' ImageButton: id: newstatus_back_button size_hint: 0.1, 0.1 source: {'normal': 'images/back-96.png', 'down': 'images/back-96.png'} [self.state] on_release: root.back_to_status() BoxLayout: id: newstatus_layout orientation: 'vertical' size_hint: 0.8, 0.9 pos_hint: {'center_x':0.5, 'center_y':0.5} spacing: 2 BoxLayout: orientation: 'vertical' CustomTextInput: id: status_text size_hint_y: 0.8 multiline: True focus: True hint_text: 'Enter your new status message' font_size: '20sp' max_characters: 280 Label: id: chars_left size_hint_y: 0.2 markup: True text: str(len(status_text.text))+"/280" color: 0/255, 0/255, 0/255, 1 text_size: self.size halign: 'right' valign: 'top' BoxLayout: spacing: 2 orientation: 'horizontal' Button: text: 'Button1' Button: text: 'Button2' BoxLayout: orientation: 'horizontal' spacing: 5 DatePicker: pHint: 0.9,0.8 BoxLayout: spacing: 5 orientation: 'vertical' canvas.after: Color: rgba: 128/255, 128/255, 128/255, 1 Line: width: dp(1) rectangle: (*self.pos, self.width, self.height) Label: id: time_label text: 'TIME' font_size: '11sp' font_name: 'roboto/Roboto-Medium.ttf' markup: True color: 0, 0, 0, 1 Slider: id: hrs_slider min: 0 max: 23 step: 1 cursor_size: 25, 25 value: 18 value_track: True value_track_color: 254/255, 107/255, 100/255, 1 orientation: 'horizontal' Label: text:'HH: '+str(int(hrs_slider.value)) markup: True font_size: '11sp' font_name: 'roboto/Roboto-Medium.ttf' color: 0, 0, 0, 1 halign: 'center' valign: 'middle' Slider: id: mins_slider min: 0 max: 59 step: 1 cursor_size: 25, 25 value: 30 value_track: True value_track_color: 254/255, 107/255, 100/255, 1 orientation: 'horizontal' Label: text:'MM: '+str(int(mins_slider.value)) markup: True font_size: '11sp' font_name: 'roboto/Roboto-Medium.ttf' color: 0, 0, 0, 1 halign: 'center' valign: 'middle' BoxLayout: orientation: 'horizontal' ImageButton: source: {'normal': 'images/picture-96.png', 'down': 'images/picture-green-96.png'} [self.state] ImageButton: source: {'normal': 'images/save-96.png', 'down': 'images/save-close-96.png'} [self.state]
<ImageLabel>: orientation: 'horizontal' size_hint_y: None height: '40dp' spacing: 1 Image: size_hint_x: 0.3 keep_ratio: True source: root.source # root - ImageLabel Label: size_hint_x: 0.7 markup: True text: root.text # root - ImageLabel color: 0, 0, 0, 1
<ImageLabelButton>: on_release: # Tuple returned in dropdown.select() method to pass two values bundled as one. app.root.get_screen('status_screen').ids.dropdown.select((self.text, self.source)) # Invoked inside ImageLabelButton rule # app.root - Screen, root - ImageLabelButton object, self - ImageLabelButton object
dropdown.open(self)
Warning
This module is highly experimental, use it with care.