Example #1
0
	def __init__(self, json_device, *args, **kwargs):
		super(DeviceBox, self).__init__(*args, **kwargs)
		
		self.app = App.get_running_app()
		
		print 'building device box'
		print json_device
		print '\n'
		
		self.maj_id = json_device['id']
		self.model = json_device['device_key']
		self.name = json_device['name']
		
		self.orientation = 'vertical'
		self.add_widget(Label(text = self.name,
							  text_size = (self.width-dp(10), 35)))
		
		if self.model in self.nexa_controllers:
			self.switches = []
			for switch in json_device['switches']:
				if switch['state'] != None:	state = switch['state']
				else: state = False
				new_switch = Switch(id = switch['id'], active = state, disabled = True) 
				self.switches.append(new_switch)
				self.add_widget(new_switch)
		elif self.model in self.nexa_sensors:
			self.last_activated = Label(text = json_device['last_activated'],
									    size_hint = (None, 1),
									    text_size = (self.width-dp(10), 100),
									    pos_hint = {'center_x': 0.5})
			self.add_widget(self.last_activated)
		elif self.model in self.nexa_devices:
			self.switch = Switch(id = json_device['id'])
			self.switch.bind(active = self.user_action)
			self.add_widget(self.switch)
Example #2
0
    def _create_popup(self, instance):
        # create the popup
        content = BoxLayout(orientation='vertical', spacing='5dp')
        popup_width = min(0.95 * Window.width, dp(500))
        self.popup = popup = Popup(
            content=content, title=self.title, size_hint=(None, None),
            size=(popup_width, '400dp'))
        popup.height = len(self.options) * dp(55) + dp(150)

        # add all the options
        content.add_widget(Widget(size_hint_y=None, height=1))
        uid = str(self.uid)
        for option in self.options:
            state = 'down' if option == self.value else 'normal'
            btn = ToggleButton(text=option, state=state, group=uid)
            btn.bind(on_release=self._set_option)
            content.add_widget(btn)

        # finally, add a cancel button to return on the previous panel
        content.add_widget(SettingSpacer())
        btn = Button(text='Cancel', size_hint_y=None, height=dp(50))
        btn.bind(on_release=popup.dismiss)
        content.add_widget(btn)

        # and open the popup !
        popup.open()
Example #3
0
	def on_touch_down(self, touch):
		
		#when touch count = 2, the canvas is cleared, getting rid of the lines and angle
		if self.touch_down_count == 2:
			self.canvas.clear()
			return
						
		#when touch count is greater than 2, we reset the count to zero to allow for new lines to be drawn and measured
		if self.touch_down_count > 2:
			self.touch_down_count = 0
		
		#Record the touch coordinates in x and y as variables	
		x1 = touch.x
		y1 = touch.y
		#create a label on touch and store it in the user dictionary to be accessed later by an update function
		touch.ud['label'] = Label(size_hint=(None, None))
		
		#when the touch count is 0 or 1, we will record the touch coordinates and draw a crosshair at the touch location
		if self.touch_down_count <= 1:
			#add a label widget
			self.add_widget(touch.ud['label'])
			
			with self.canvas:
				#save the touch points to the user dictionary
				touch.ud['x1'] = x1
				touch.ud['y1'] = y1
				#set parameters for crosshair display
				Color(1, 0, 0)
				l = dp(40)
				w = dp(3)
				#draw crosshair
				Rectangle(pos=(touch.ud['x1'] - w / 2, touch.ud['y1'] - l / 2), size=(w, l))
				Rectangle(pos=(touch.ud['x1'] - l / 2, touch.ud['y1'] - w / 2), size=(l, w))
 def __init__(self, **kwargs):
     # The starting vertical scroll position
     self._start_y = None
     super(ScrollContainer, self).__init__(**kwargs)
     self.scroll_type = ['bars', 'content']
     self.scroll_wheel_distance = dp(114)
     self.bar_width = dp(20)
Example #5
0
 def on_touch_down(self, touch):
     #Record the touch coordinates in x and y as variables	
     x1 = touch.x
     y1 = touch.y
     
     #when the touch count is 0 or 1, we will record the touch coordinates and draw a crosshair at the touch location
     if self.touch_down_count > 1:
         return
     with self.canvas:
         touch.ud['label'] = TextInput()
         self.initiate_touch_label(touch.ud['label'], touch)
         self.add_widget(touch.ud['label'])
         #save the touch points to the user dictionary
         touch.ud['x1'] = x1
         touch.ud['y1'] = y1
         #set parameters for crosshair display
         Color(1, 0, 0)
         l = dp(25)
         w = dp(1)
         #draw crosshair
         Rectangle(pos=(touch.ud['x1'] - w / 2, touch.ud['y1'] - l / 2), size=(w, l))
         Rectangle(pos=(touch.ud['x1'] - l / 2, touch.ud['y1'] - w / 2), size=(l, w))
     #Initialize the vector v1
     if self.touch_down_count == 0:
         #Record the touch coordinates to variables
         x2 = touch.x
         y2 = touch.y
         #Save touch coordinates to the user dictionary
         touch.ud['x2'] = x2
         touch.ud['y2'] = y2
         #When the touch count is zero (first touch), we define a vector v1 based on the touch positions in ud
         v1 = (touch.ud['x2'] - touch.ud['x1'], touch.ud['y2'] - touch.ud['y1'])
         self.v1 = v1
    def on_volts(self, mapBin, instance):
        value = instance.text.strip()
        if value == '' or value == "." or value == "-":
            value = 0
            instance.text = str(value)
        try:
            value = float(value)
            if self.scaling_map:
                self.scaling_map.setVolts(mapBin, value)
                self.dispatch('on_map_updated')
                self.regen_plot()
        except ScalingMapException as e:
            warn = CenteredBubble()
            warn.add_widget(WarnLabel(text=str(e)))
            warn.auto_dismiss_timeout(WARN_DISMISS_TIMEOUT)
            warn.background_color = (1, 0, 0, 1.0)
            warn.size = (dp(200), dp(50))
            warn.size_hint = (None,None)
            self.get_root_window().add_widget(warn)
            warn.center_on(instance)
            original_value = self.scaling_map.getVolts(mapBin)
            self.set_volts_cell(instance, original_value)
            Clock.schedule_once(lambda dt: self._refocus(instance))
        except Exception as e:

            alertPopup('Scaling Map', str(e))
            original_value = self.scaling_map.getVolts(mapBin)
            self.set_volts_cell(instance, original_value)
Example #7
0
    def Start(self,uTitle,aOptions,fktCallBack):
        ''' starts selection '''
        self.fktCallBack=fktCallBack
        # create the popup
        content         = GridLayout(cols=1, spacing='5dp')
        scrollview      = ScrollView( do_scroll_x=False, bar_width='10dp',scroll_type=['bars'] )
        scrollcontent   = GridLayout(cols=1,  spacing='5dp', size_hint=(None, None))
        scrollcontent.bind(minimum_height=scrollcontent.setter('height'))
        self.oPopup   = popup = Popup(content=content, title=ReplaceVars(uTitle), size_hint=(0.5, 0.9),  auto_dismiss=False)

        #we need to open the popup first to get the metrics
        popup.open()
        #Add some space on top
        content.add_widget(Widget(size_hint_y=None, height=dp(2)))
        # add all the options
        for option in aOptions:
            if hasattr(option,"Name"):
                name=option.Name
            else:
                name=option.Type
            btn = Button(text=name, size=(popup.width, dp(30)), size_hint=(None, None))
            btn.bind(on_release=self.On_Value)
            btn.oDBRef=option
            scrollcontent.add_widget(btn)

        # finally, add a cancel button
        scrollview.add_widget(scrollcontent)
        content.add_widget(scrollview)
        content.add_widget(SettingSpacer())
        btn = Button(text=ReplaceVars('$lvar(5009)'), size=(popup.width, dp(50)),size_hint=(0.9, None))
        btn.bind(on_release=popup.dismiss)
        content.add_widget(btn)
 def on_edit(self):
     channel = self.channel
     popup = Popup(title='Edit System Channel' if channel.systemChannel else 'Edit Channel',
                   content=ChannelEditor(channel=channel),
                   size_hint=(None, None), size=(dp(500), dp(180)))
     popup.open()
     popup.bind(on_dismiss=self.on_edited)
Example #9
0
def card(content, title=None, background_color=None, size=(.7, .5)):
    '''Вывод диалоговых окон с кастомным контентом.'''

    if not background_color:
        background_color = [1.0, 1.0, 1.0, 1]

    card = MDCard(size_hint=(1, 1), padding=5) #, background_color=background_color)

    if title:
        box = BoxLayout(orientation='vertical', padding=dp(8))
        box.add_widget(
            MDLabel(
                text=title, theme_text_color='Secondary', font_style="Title",
                size_hint_y=None, height=dp(36)
            )
        )
        box.add_widget(MDSeparator(height=dp(1)))
        box.add_widget(content)
        card.add_widget(box)
    else:
        card.add_widget(content)

    dialog = ModalView(size_hint=size, background_color=[0, 0, 0, .2])
    dialog.add_widget(card)
    #dialog.open()

    return dialog
Example #10
0
 def on_touch_up(self, touch):
     if touch == self.current_touch:
         self.current_touch = None
         if self.app.editor.delete.collide_point(
                 *self.to_window(*touch.pos)):
             for f in [frog for frog in self.parent.children
                       if type(frog) == FrogPH]:
                 if f.place == self.id:
                     self.app.editor.level.remove_widget(f)
             self.app.editor.level.remove_widget(self)
             return True
         x = int(round(self.center_x / dp(100), 0))
         y = int(round(self.y / dp(100), 0))
         x = x if x > 0 else 1
         y = y if y > 0 else 1
         center_x = dp(100) * x
         y = dp(100) * y
         # Loop until a free place was found
         loop = True
         while loop:
             for child in self.parent.children:
                 if child.center_x == center_x and\
                    y == child.y and child != self:
                     x += 1
                     center_x = dp(100) * x
                     break
             else:
                 loop = False
         self.center_x = center_x
         self.y = y
         self.app.editor.select.center = self.to_window(
             *self.center)
         return True
     return super(PHScatter, self).on_touch_up(touch)
Example #11
0
 def export_level(self, path):
     out = "level boats={} flys={} energy={} ".format(
         self.sidebar.level_settings.boats_count.text,
         self.sidebar.level_settings.flys_count.text,
         self.sidebar.level_settings.energy_count.text)
     # get level size
     max_x = 0
     max_y = 0
     children = self.level.children
     for c in children:
         x = int(round(c.center_x / dp(100), 0))
         if x > max_x:
             max_x = x
         y = int(round(c.y / dp(100), 0))
         if y > max_y:
             max_y = y
     out += "size={},{}\n".format(max_x + 1, max_y + 1)
     # add the objects
     for c in self.level.children:
         extra_opts = " "
         if type(c) == WaterLilyPH:
             tp = "waterlily"
         elif type(c) == StoneLilyPH:
             tp = "stonelily"
         elif type(c) == SwitchLilyPH:
             if c.options.controlled:
                 tp = "switchlily"
                 extra_opts += "controlled={}".format(
                     c.options.controlled.id)
             else:
                 tp = "stonelily"
         elif type(c) == ExercisePH:
             tp = c.options.tp.lower()
             extra_opts += "count={} orientation={} ".format(
                 c.options.count, c.options.orientation.lower())
         elif type(c) == StartPH:
             tp = "start"
         elif type(c) == EndPH:
             tp = "end"
         else:
             continue
         x = int(round(c.center_x / dp(100), 0))
         y = int(round(c.y / dp(100), 0))
         c_id = c.id
         s = "{} pos={},{} id={}".format(tp, x, y, c_id)
         out += s + extra_opts + "\n"
     # Add the player frog
     out += "frog id=player jump_img={} sit_img={}"\
         .format(
             self.level.start.frog.jump_img,
             self.level.start.frog.sit_img) +\
         " player=True place=start\n"
     # Add the other frogs
     for frog in [c for c in self.level.children
                  if type(c) == FrogPH]:
         out += "frog jump_img={} sit_img={} place={}\n".format(
             frog.jump_img, frog.sit_img, frog.place)
     f = open(path, "w")
     f.write(out)
     f.close()
Example #12
0
    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
Example #13
0
 def on_touch_up(self, touch):
     if touch == self.current_touch:
         self.current_touch = None
         if self.app.editor.delete.collide_point(*touch.pos):
             self.app.editor.level.remove_widget(self)
             return True
         x = int(round(self.center_x / dp(100), 0))
         y = int(round(self.y / dp(100), 0))
         center_x = dp(100) * x
         y = dp(100) * y
         for child in self.parent.children:
             if child.center_x == center_x and\
                y == child.y and child != self and\
                type(child) != FrogPH and\
                type(child) != StartPH:
                 for frog in [c for c in self.parent.children
                              if type(c) == FrogPH]:
                     if frog.place == child.id and frog != self:
                         break
                 else:
                     child.bind(pos=self.on_parent_pos)
                     self.center = child.center
                     self.app.editor.select.center = self.to_window(
                         *self.center)
                     self.place = child.id
                     break
         else:
             self.parent.remove_widget(self)
         return True
     return super(PHScatter, self).on_touch_up(touch)
    def build(self):
        # create root widget
        root_widget = FloatLayout()
        box = BoxLayout(orientation='vertical',
                        size_hint=(None, None),
                        size=(400, 200),
                        spacing=dp(20),
                        padding=dp(20),
                        pos_hint={'center_x': .5, 'center_y':.5})

        # create the labels and the textinputs
        lbl_user =  Label(text='User Name:')
        lbl_password = Label(text='Password')
        ti_user = TextInput()
        ti_password = TextInput(password=True)
        
        # create the containers for the labels and textinputs
        grid_user_pass = GridLayout(rows=2, cols=2, spacing=dp(20))
        # create the ok button
        my_but_is_ok = Button(text='OK')
        my_but_is_ok.bind(on_release=lambda *args: self.check_user(ti_user.text, ti_password.text))

        # add the labels and input fields to the container 
        grid_user_pass.add_widget(lbl_user)
        grid_user_pass.add_widget(ti_user)
        grid_user_pass.add_widget(lbl_password)
        grid_user_pass.add_widget(ti_password)

        # add the grid_container into it's container
        box.add_widget(grid_user_pass)
        root_widget.add_widget(box)
        # add the ok button at the bottom of the grid
        box.add_widget(my_but_is_ok)

        return root_widget
    def __init__(self, **kwargs):
        super(GameRecorder, self).__init__(**kwargs)
        self.orientation = 'vertical' if self.height > self.width else 'horizontal'
        self.bind(size=self.on_size, orientation=self.on_orientation)

        self.game = Game()
        side_box = BoxLayout(orientation='vertical')
        b = BoxLayout(size_hint_y=None, height=dp(50))
        back_button = CustomButton(text='<< Games')
        undo_button = CustomButton(text='Reset')
        undo_button.bind(on_release=self.reset)
        back_button.bind(on_release=self.go_back)
        b.add_widget(back_button)
        b.add_widget(undo_button)

        save_button = CustomButton(text='Save game', size_hint_y=None, height=dp(50))
        save_button.bind(on_release=self.save_popup)
        side_box.add_widget(b)
        side_box.add_widget(save_button)


        moves_scroll = ScrollView()
        self.moves_table=MovesGrid(padding=dp(10), spacing=dp(10))
        for move in self.game.move_history:
            self.moves_table.add_widget(MoveButton(text=move))

        side = self.height if self.orientation == 'horizontal' else self.width
        self.board = ChessboardUI(game=self.game, size_hint=(None,None), height=side, width=side)
        self.board.bind(move_made=self.change_moves)

        self.add_widget(self.board)
        moves_scroll.add_widget(self.moves_table)
        side_box.add_widget(moves_scroll)
        self.add_widget(side_box)
Example #16
0
    def _create_subpopup(self, instance):
        ''' shows the sub popup '''
        # create the popup
        content         = GridLayout(cols=1, spacing='5dp')
        scrollview      = ScrollView( do_scroll_x=False)
        scrollcontent   = GridLayout(cols=1,  spacing='5dp', size_hint=(None, None))
        scrollcontent.bind(minimum_height=scrollcontent.setter('height'))
        self.subpopup   = popup = Popup(content=content, title=self.uOption, size_hint=(0.5, 0.9),  auto_dismiss=False)

        #we need to open the popup first to get the metrics
        popup.open()
        #Add some space on top
        content.add_widget(Widget(size_hint_y=None, height=dp(2)))
        # add all the options
        uid = str(self.uid)
        for option in self.aSubOption:
            state = 'down' if option == self.value else 'normal'
            oTbtn = ToggleButton(text=option, state=state, group=uid, size=(popup.width, dp(55)), size_hint=(None, None))
            oTbtn.bind(on_release=self._set_suboption)
            scrollcontent.add_widget(oTbtn)

        # finally, add a cancel button to return on the previous panel
        scrollview.add_widget(scrollcontent)
        content.add_widget(scrollview)
        content.add_widget(SettingSpacer())
        oMbtn = cMultiLineButton(text=ReplaceVars('$lvar(5009)'), size=(popup.width, dp(50)),size_hint=(0.9, None), halign='center', valign='middle')
        oMbtn.bind(on_release=popup.dismiss)
        content.add_widget(oMbtn)
Example #17
0
    def change_ctx(self, text, *args):
        popup = self.parent.parent.parent.parent.parent
        container = self.ids.cols_container
        amount = self.ids.amount

        if not self._old_height:
            self._old_height = self.height

        if text == 'Columns':
            # hide amount
            amount.size_hint_x = 0
            amount.width = 0
            amount.background_color = (0, 0, 0, 0)

            # add layout for columns
            container.add_widget(AppendColsLayout())
            self.height = self.height + dp(90)
            container.height = dp(90)
        else:
            # show amount
            amount.size_hint_x = 1
            amount.background_color = (1, 1, 1, 1)

            self.height = self._old_height
            container.height = 0

            if container.children:
                container.clear_widgets()

        popup.recalc_height(popup.ids.taskbody, self.parent)
 def init_tracks_list(self):
     if self.track_manager and self.trackDb:
         matchedTracks = []
         for track in self.trackDb.tracks:
             matchedTrack = self.track_manager.find_track_by_short_id(track.trackId)
             if matchedTrack:
                 matchedTracks.append(matchedTrack)
                 
         grid = kvFind(self, 'rcid', 'tracksgrid')
         grid.clear_widgets()
         if len(matchedTracks) == 0:
             grid.add_widget(EmptyTrackDbView())
             self.tracksGrid.height = dp(self.TRACK_ITEM_MIN_HEIGHT)
         else:
             self.tracksGrid.height = dp(self.TRACK_ITEM_MIN_HEIGHT) * (len(matchedTracks) + 1)
             index = 0
             for track in matchedTracks:
                 trackDbView = TrackDbItemView(track=track, index=index)
                 trackDbView.bind(on_remove_track=self.on_remove_track)
                 trackDbView.size_hint_y = None
                 trackDbView.height = dp(self.TRACK_ITEM_MIN_HEIGHT)
                 grid.add_widget(trackDbView)
                 index += 1
             
         self.disableView(False)
Example #19
0
    def move(self):
        if self.dead:
            if self.image.pos[0] > resources.rocket['width'] * -1 and\
                    self.image.pos[1] > resources.rocket['height'] * -1:
                self.image.pos = (self.image.pos[0] - dp(20),
                                  self.image.pos[1] - dp(20))
                self.image.size = (self.image.size[0] - dp(25),
                                   self.image.size[1] - dp(10))
            return

        if self.force:
            self.image.source = resources.rocket['sprite1']
            self.image.reload()
            # if self.image.pos[1] < (Window.height - self.default_y - 150):
            #     self.die()
            self.image.pos = (self.image.pos[0], self.image.pos[1] + Sizer.get_rocket_speed())
            self.pos = (self.image.pos[0], self.image.pos[1] + Sizer.get_rocket_speed())
        else:
            self.image.source = resources.rocket['sprite2']
            self.image.reload()

            self.image.pos = (self.image.pos[0], self.image.pos[1] - Sizer.get_rocket_speed())
            self.pos = (self.image.pos[0], self.image.pos[1] - Sizer.get_rocket_speed())

            if (
                self.image.pos[1] < (self.image.size[1] / 2) * -1 or
                self.image.pos[1] > Window.height + self.image.size[1]
            ):
                self.die()
Example #20
0
 def _create_popup(self, instance):
     """Modified from SettingString's popup."""
     # create popup layout
     self.popup = SliderPopup(title=self.title, setting=self,
                              value=float(self.value),
                              size=(min(0.95 * Window.width, dp(500)), dp(250)))
     self.popup.open()
Example #21
0
    def __init__(self, username, userid, name):
        """

        """
        self.name = name
        self.username = username
        self.userid = userid
        super(LevelSelect, self).__init__()

        conn = sqlite3.connect(filehome + 'database.db')  # Opens the connection to the database.
        c = conn.cursor()
        levels = c.execute('''SELECT levelid, levelname, leveldesc FROM level''')  # Gets the levels from the database

        box = BoxLayout(orientation = 'vertical')
        box.add_widget(Banner(False, 2, self.userid))  # Adds the top banner, as this is the main menu we need a logout button and not a back button. 
        lvlAccordion = Accordion(orientation = 'vertical', min_space = dp(25), anim_duration = 1)
        for i in levels:
            item = AccordionItem(title = i[1], min_space = dp(25), background_normal='images/blue32025.png', background_selected='images/orange32025.png')    
            boxa = BoxLayout(orientation = 'vertical')
            lbl = Label(text = i[2], text_size = (300, None))
            boxa.add_widget(lbl)
            btn = Button(text = 'Go', id = str(i[0])+','+i[1], on_press = self.selectlevel, background_normal = 'images/orange32030.png', background_down = 'images/blue32025.png', size_hint_y = None, height = dp(30))
            boxa.add_widget(btn)
            item.add_widget(boxa)
            lvlAccordion.add_widget(item)
        box.add_widget(lvlAccordion)  # Adds the Accordion to the box
        self.add_widget(box)  # Adds the box widget to the screen
        conn.close()
Example #22
0
    def __init__(self, **kwargs):
        super(MyScreen, self).__init__(**kwargs)
        scrollView = ScrollView()
        self.add_widget(scrollView)

        boxLayout = BoxLayout(orientation='vertical', height=dp(1000), padding=dp(48))
        scrollView.add_widget(boxLayout)
        textField = SingleLineTextField(id='text_filed', size_hint=(0.8, None), height=dp(48))
        textField.hint_text='This is a pretty text filed'
        boxLayout.add_widget(textField)
        buttonContainer = BoxLayout(orientation='horizontal', height=dp(48))
        flatButton = MDFlatButton(text='FlatButton')
        # size is not working somehow
        # flatButton.size = (3*dp(48), dp(48))
        buttonContainer.add_widget(flatButton)
        raiseButton = MDRaisedButton(text='RaiseButton')
        # raiseButton.size = (3*dp(48), dp(48))
        buttonContainer.add_widget(raiseButton)
        boxLayout.add_widget(buttonContainer)

        switchContainer = BoxLayout(orientation='horizontal')
        checkbox1 = MDCheckbox(group='test')
        # checkbox1.size=(dp(48), dp(48))
        switchContainer.add_widget(checkbox1)
        checkbox2 = MDCheckbox(group='test')
        # checkbox2.size=(dp(48), dp(48))
        switchContainer.add_widget(checkbox2)
        boxLayout.add_widget(switchContainer)
Example #23
0
    def ShowList(self):
        ''' Shows the discover results '''
        # create the popup
        oContent         = GridLayout(cols=1, spacing='5dp')
        oScrollview      = ScrollView( do_scroll_x=False)
        self.oScrollContent   = StackLayout(size_hint=(None, None))
        self.oPopup   = oPopup = Popup(content=oContent, title=ReplaceVars('$lvar(5028)'), size_hint=(0.9, 0.9),  auto_dismiss=False)

        #we need to open the popup first to get the metrics
        oPopup.open()
        #Add some space on top
        oContent.add_widget(Widget(size_hint_y=None, height=dp(2)))
        aDiscoverScripts=oORCA.oScripts.GetScriptListForScriptType("DEVICE_DISCOVER")
        aScrollContent=[]
        for uDiscoverScriptName in aDiscoverScripts:
            oScrollContentSingle   = GridLayout(size_hint=(None, None))
            aScrollContent.append(oScrollContentSingle)
            oScrollContentSingle.bind(minimum_height=oScrollContentSingle.setter('height'))
            oORCA.oScripts.RunScript(uDiscoverScriptName,{'createlist':1,'oGrid':oScrollContentSingle})
            self.oScrollContent.add_widget(cLabel(text=oORCA.oScripts.aScripts[uDiscoverScriptName].uSubType, background_color=[0.2, 0.2, 0.2, 1.0], color=[0.9, 0.9, 0.9, 1.0], size=(oPopup.width, dp(30)),size_hint=(None, None), halign='center'))
            self.oScrollContent.add_widget(oScrollContentSingle)
            self.oScrollContent.add_widget(SettingSpacer())

        # finally, add a cancel button to return on the previous panel
        oScrollview.add_widget(self.oScrollContent)
        oContent.add_widget(oScrollview)
        oContent.add_widget(SettingSpacer())

        oBtn = Button(text=ReplaceVars('$lvar(5000)'), size=(oPopup.width, dp(50)),size_hint=(1, None))
        oBtn.bind(on_release=self.On_Cancel)
        oContent.add_widget(oBtn)

        #resize the Scrollcontent to fit to all Childs. Needs to be done, after the popup has been shown
        Clock.schedule_once(self.SetScrollSize, 0)
Example #24
0
    def __init__(self, **kwargs):
        # ID of the command being executed
        self._cmd_id = None

        # List of the "completed" statuses.
        # The first status should be "Done"
        self._completed = []

        # If True - sends a request to retrieve a command status
        self._wait_completion = False

        # requested command
        self._command = (0, '')

        super(RemoteControlUI, self).__init__(
            orientation='vertical', spacing=2, padding=3, **kwargs)

        # Control buttons panel
        pnl_controls = BoxLayout(size_hint_y=None, height=metrics.dp(35))
        pnl_controls.add_widget(
            Button(text='Refresh', on_release=self._get_commands))
        pnl_controls.add_widget(
            Button(text='Close', on_release=App.get_running_app().stop))
        self.add_widget(pnl_controls)

        # Command buttons panel
        self._pnl_commands = BoxLayout(orientation='vertical')
        self.add_widget(self._pnl_commands)

        # Info panel
        lbl_info = Label(
            text=self.info_text, size_hint_y=None, height=metrics.dp(35))
        self.bind(info_text=lbl_info.setter('text'))
        self.add_widget(lbl_info)
Example #25
0
 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')
Example #26
0
 def __init__(self, **kwargs):
     super(Collide, self).__init__(**kwargs)
     self.remove_width = dp(280)
     self.remove_height = dp(120)
     if self.debug:
         with self.canvas:
             Color(1, 0, 0)
             self.rect = Rectangle()
 def on_bt_configure(self, instance, value):
     if not self._bt_popup:
         content = AdvancedBluetoothConfigView(self.config.connectivityConfig)
         popup = editor_popup(title="Configure Bluetooth", content=content,
                              answerCallback=self.on_bluetooth_popup_answer,
                              size=(dp(600), dp(300)))
         self._bt_popup = popup
         self._bt_config_view = content
Example #28
0
 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)
Example #29
0
 def set_background(self):
     texture = GameContext.resources['textures']['toolbar_bg']
     th, tw = texture.size
     th, tw = dp(th), dp(tw)
     with self.canvas.before:
         Color(1, 1, 1, 1)
         for i in xrange(50):
             Rectangle(pos=(i*tw, 0) , size=(tw, th), texture=texture)
	def on_text(self, *args):
		#get text field text
		text_input_value = self.header_textinput.text
		#once user has type 3 letters and more, start substring search
		if len(text_input_value)>2:

			#if previous listview exists, remove it
			self.closeListView()

			#start search, put the response data in a list adapter
			suggestions = app.datamall_bus_stop.busnamesubstringSearch(text_input_value)
			
			#ListitemButton Behaviour
			args_converter = lambda row_index, rec: {
			'text':rec['text'],
			'size_hint':(None,None),
			'height': '50dp',
			'width': self.header_textinput.width
			}

			suggestion_listadapter = ListAdapter(
				data=suggestions,
				args_converter=args_converter,
				selection_mode='multiple',
				selection_limit=1,
				allow_empty_selection=True,
				cls=ListItemButton
				)
			#binds each listview button to the autofill function
			suggestion_listadapter.bind(on_selection_change=self.selection_change)
			
			#Logger.info("heightheight"+str(dp(60)))
			#Logger.info("heightheight"+str(float(dp(50)*len(suggestions)/self.height)))

			self.suggestion_listview = ListView(
				adapter=suggestion_listadapter,
				size_hint_y=(float(dp(50)*len(suggestions)/self.height)) if (float(dp(50)*len(suggestions)/self.height))<0.4 else 0.4,
				width=self.header_textinput.width,
				pos_hint={"top":(self.height-self.header_textinput.height*1.3)/self.height},
				x=self.header_textinput.x
				)

			#The container is a GridLayout widget held within a ScrollView widget.
			#So we are giving the ScrollViewParent a custom scroll effect
			#ListView >> ScrollView >> GridLayout
			#effect_cls is an ObjectProperty and defaults to DampedScrollEffect.
			self.suggestion_listview.container.parent.effect_cls = self.scrolleffect

			#Timeout allowed to trigger the scroll_distance, in milliseconds. If the user has not moved scroll_distance within the timeout, the scrolling will be disabled, and the touch event will go to the children.
			self.suggestion_listview.container.parent.scroll_distance = 10
			self.suggestion_listview.container.parent.scroll_timeout = 	1000

			self.listview_widget_collector.append(self.suggestion_listview)
			self.ids['searchbusscreen_floatlayout'].add_widget(self.suggestion_listview)

		else:
			#User is deleting his input, so naturally, we shall close the listview (if it exists)
			self.closeListView()
Example #31
0
class MDBottomNavigationHeader(ThemableBehavior, ButtonBehavior,
                               MDAnchorLayout):
    panel_color = ColorProperty([1, 1, 1, 0])
    """
    Panel color of bottom navigation.

    :attr:`panel_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `[1, 1, 1, 0]`.
    """

    tab = ObjectProperty()
    """
    :attr:`tab` is an :class:`~MDBottomNavigationItem`
    and defaults to `None`.
    """

    panel = ObjectProperty()
    """
    :attr:`panel` is an :class:`~MDBottomNavigation`
    and defaults to `None`.
    """

    active = BooleanProperty(False)

    text = StringProperty()
    """
    :attr:`text` is an :class:`~MDTab.text`
    and defaults to `''`.
    """

    text_color_normal = ColorProperty([1, 1, 1, 1])
    """
    Text color of the label when it is not selected.

    :attr:`text_color_normal` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `[1, 1, 1, 1]`.
    """

    text_color_active = ColorProperty([1, 1, 1, 1])
    """
    Text color of the label when it is selected.

    :attr:`text_color_active` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `[1, 1, 1, 1]`.
    """

    selected_color_background = ColorProperty(None)
    """
    The background color of the highlighted item when using Material Design v3.

    .. versionadded:: 1.0.0

    :attr:`selected_color_background` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `None`.
    """

    opposite_colors = BooleanProperty(True)

    _label = ObjectProperty()
    _label_font_size = NumericProperty("12sp")
    _text_color_normal = ColorProperty([1, 1, 1, 1])
    _text_color_active = ColorProperty([1, 1, 1, 1])
    _selected_region_width = NumericProperty(dp(64))

    def __init__(self, panel, tab):
        self.panel = panel
        self.tab = tab
        super().__init__()
        self._text_color_normal = (self.theme_cls.disabled_hint_text_color
                                   if self.text_color_normal == [1, 1, 1, 1]
                                   else self.text_color_normal)
        self._label = self.ids._label
        self._label_font_size = sp(12)
        self.theme_cls.bind(disabled_hint_text_color=self._update_theme_style)
        self.active = False

    def on_press(self) -> None:
        """Called when clicking on a panel item."""

        if self.theme_cls.material_style == "M2":
            Animation(_label_font_size=sp(14), d=0.1).start(self)
        elif self.theme_cls.material_style == "M3":
            Animation(
                _selected_region_width=dp(64),
                t="in_out_sine",
                d=0,
            ).start(self)
        Animation(
            _text_color_normal=self.theme_cls.primary_color if
            self.text_color_active == [1, 1, 1, 1] else self.text_color_active,
            d=0.1,
        ).start(self)

    def _update_theme_style(self, instance_theme_manager: ThemeManager,
                            color: list):
        """Called when the application theme style changes (White/Black)."""

        if not self.active:
            self._text_color_normal = (color if self.text_color_normal == [
                1, 1, 1, 1
            ] else self.text_color_normal)
Example #32
0
 def _update_ticks(self, size):
     # re-compute the positions of the bounding rectangle
     mesh = self._mesh_rect
     vert = mesh.vertices
     if self.draw_border:
         s0, s1, s2, s3 = size
         vert[0] = s0
         vert[1] = s1
         vert[4] = s2
         vert[5] = s1
         vert[8] = s2
         vert[9] = s3
         vert[12] = s0
         vert[13] = s3
         vert[16] = s0
         vert[17] = s1
     else:
         vert[0:18] = [0 for k in range(18)]
     mesh.vertices = vert
     # re-compute the positions of the x/y axis ticks
     mesh = self._mesh_ticks
     vert = mesh.vertices
     start = 0
     xpoints = self._ticks_majorx
     ypoints = self._ticks_majory
     xpoints2 = self._ticks_minorx
     ypoints2 = self._ticks_minory
     ylog = self.ylog
     xlog = self.xlog
     xmin = self.xmin
     xmax = self.xmax
     if xlog:
         xmin = log10(xmin)
         xmax = log10(xmax)
     ymin = self.ymin
     ymax = self.ymax
     if ylog:
         xmin = log10(ymin)
         ymax = log10(ymax)
     if len(xpoints):
         top = size[3] if self.x_grid else metrics.dp(12) + size[1]
         ratio = (size[2] - size[0]) / float(xmax - xmin)
         for k in range(start, len(xpoints) + start):
             vert[k * 8] = size[0] + (xpoints[k - start] - xmin) * ratio
             vert[k * 8 + 1] = size[1]
             vert[k * 8 + 4] = vert[k * 8]
             vert[k * 8 + 5] = top
         start += len(xpoints)
     if len(xpoints2):
         top = metrics.dp(8) + size[1]
         ratio = (size[2] - size[0]) / float(xmax - xmin)
         for k in range(start, len(xpoints2) + start):
             vert[k * 8] = size[0] + (xpoints2[k - start] - xmin) * ratio
             vert[k * 8 + 1] = size[1]
             vert[k * 8 + 4] = vert[k * 8]
             vert[k * 8 + 5] = top
         start += len(xpoints2)
     if len(ypoints):
         top = size[2] if self.y_grid else metrics.dp(12) + size[0]
         ratio = (size[3] - size[1]) / float(ymax - ymin)
         for k in range(start, len(ypoints) + start):
             vert[k * 8 + 1] = size[1] + (ypoints[k - start] - ymin) * ratio
             vert[k * 8 + 5] = vert[k * 8 + 1]
             vert[k * 8] = size[0]
             vert[k * 8 + 4] = top
         start += len(ypoints)
     if len(ypoints2):
         top = metrics.dp(8) + size[0]
         ratio = (size[3] - size[1]) / float(ymax - ymin)
         for k in range(start, len(ypoints2) + start):
             vert[k * 8 +
                  1] = size[1] + (ypoints2[k - start] - ymin) * ratio
             vert[k * 8 + 5] = vert[k * 8 + 1]
             vert[k * 8] = size[0]
             vert[k * 8 + 4] = top
     mesh.vertices = vert
 def show_floating_labels(self):
     i = 0
     for lbl in self.lbl_list:
         i += 0.3
         pos_x = Window.width / 2 - (lbl.width + dp(23))
         Animation(x=pos_x, d=i, t="out_elastic").start(lbl)
 def animateLightningBoltIcon(self):
     Anim = Animation(lightningBoltPosX=dp(10), t='out_quad', d=0.02) + Animation(lightningBoltPosX=dp(0), t='out_elastic', d=0.5)
     Anim.start(self)
Example #35
0
 def on_progress(*args):
     self._line_blank_space_right_point = (
         self._hint_lbl.width + dp(5))
Example #36
0
class Button_Item(ThemableBehavior, ButtonBehavior, BoxLayout):
    transition = StringProperty('out_quad')
    duration = NumericProperty(0.3)
    button_bg_color = ListProperty(None)
    button_width = NumericProperty(dp(120))
    text_size = NumericProperty(dp(13))
    text_color = ListProperty(None)
    button_height = NumericProperty(dp(40))
    icon_size = NumericProperty(dp(20))
    icon_color = ListProperty(None)
    text = StringProperty()
    icon = StringProperty()
    mode = OptionProperty('color_on_normal',
                          options=['color_on_normal', 'color_on_active'])
    # ================
    badgeitem_size = NumericProperty(dp(20))
    badge_bg_color = ListProperty()
    badgeitem_padding = NumericProperty(dp(3))
    badgeitem_color = ListProperty()
    badge_position = StringProperty('right')
    badge_text = StringProperty('')
    badge_bold = BooleanProperty(False)
    badge_offset = NumericProperty(0.4)
    badge_disabled = BooleanProperty(False)

    _bg_opacity = NumericProperty(1)

    def __init__(self, **kwargs):
        super().__init__(**kwargs)

    def on_release(self):
        for button in self.parent.children:
            if button == self:
                continue
            button._button_shrink()

        self._button_expand()
        return super().on_release()

    def _button_expand(self):
        label_anim = Animation(opacity=1,
                               transition=self.transition,
                               duration=self.duration)
        label_anim.start(self.ids._label)

        anim = Animation(width=self.button_width,
                         _bg_opacity=1,
                         t=self.transition,
                         duration=self.duration)
        anim.start(self)

    def _button_shrink(self):
        if self.mode == 'color_on_active':
            opacity = 0
        else:
            opacity = 1

        label_anim = Animation(opacity=0,
                               transition=self.transition,
                               duration=self.duration)
        label_anim.start(self.ids._label)

        but_anim = Animation(width=self.height,
                             _bg_opacity=opacity,
                             t=self.transition,
                             duration=self.duration)
        but_anim.start(self)
Example #37
0
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     self.height = dp(72)
Example #38
0
 def _update_action_buttons(self, *args):
     self._action_area.clear_widgets()
     for btn in self._action_buttons:
         btn.content.texture_update()
         btn.width = btn.content.texture_size[0] + dp(16)
         self._action_area.add_widget(btn)
Example #39
0
 def show_menu_list_animation(self):
     Animation(y=dp(60), d=0.6, t="out_elastic").start(self.ids.menu_dialog)
     self.menu_open = True
Example #40
0
    def back_animation(self):
        Animation(
            size=(dp(250), dp(250)),
            d=0.5,
        ).start(self.ids.helmet_img)
        Animation(
            y=-self.ids.shadow_planet_img.height,
            d=1.2,
        ).start(self.ids.shadow_planet_img)
        Animation(
            opacity=0,
            d=1.2,
        ).start(self.ids.box_name_planet)
        Animation(
            opacity=0,
            size=(0, 0),
            d=0.7,
        ).start(self.ids.earth_img)
        Animation(
            opacity=0,
            d=1.2,
        ).start(self.ids.light_img)
        Animation(
            opacity=0,
            d=0.7,
            t="in_sine",
        ).start(self.ids.bg_img)
        Animation(
            angle=45,
            size=(dp(100), dp(100)),
            pos_hint={"center_y": 0.5},
            d=1,
            t="in_back",
        ).start(self.ids.planet_img)
        Animation(
            color=(0, 0, 0, 1),
            d=1,
        ).start(self.ids.toolbar)
        Animation(opacity=1, d=0.5).start(self.ids.box_carousel)

        Animation(
            opacity=0,
            y=-self.ids.planet_lbl.height,
            d=0.9,
            t="in_out_back",
        ).start(self.ids.planet_lbl)
        Animation(
            opacity=0,
            y=-self.ids.info_lbl.height,
            d=1.0,
            t="in_out_back",
        ).start(self.ids.info_lbl)
        Animation(
            opacity=0,
            y=-self.ids.more_lbl.height,
            d=1.1,
            t="in_out_back",
        ).start(self.ids.more_lbl)
        Animation(
            opacity=0,
            y=self.ids.sep.height,
            d=1.2,
            t="in_out_back",
        ).start(self.ids.sep)
        self.animation_back = False
Example #41
0
class MDSelectionList(MDList):
    """
    :Events:
        `on_selected`
            Called when a list item is selected.
        `on_unselected`
            Called when a list item is unselected.
    """

    selected_mode = BooleanProperty(False)
    """
    List item selection mode. If `True` when clicking on a list item, it will
    be selected.

    :attr:`selected_mode` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    icon = StringProperty("check")
    """
    Name of the icon with which the selected list item will be marked.

    :attr:`icon` is an :class:`~kivy.properties.StringProperty`
    and defaults to `'check'`.
    """

    icon_pos = ListProperty()
    """
    The position of the icon that will mark the selected list item.

    :attr:`icon_pos` is an :class:`~kivy.properties.ListProperty`
    and defaults to `[]`.
    """

    icon_bg_color = ColorProperty([1, 1, 1, 1])
    """
    Background color of the icon that will mark the selected list item.

    :attr:`icon_bg_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `[1, 1, 1, 1]`.
    """

    icon_check_color = ColorProperty([0, 0, 0, 1])
    """
    Color of the icon that will mark the selected list item.

    :attr:`icon_check_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `[1, 1, 1, 1]`.
    """

    overlay_color = ColorProperty([0, 0, 0, 0.2])
    """
    The overlay color of the selected list item..

    :attr:`overlay_color` is an :class:`~kivy.properties.ColorProperty`
    and defaults to `[0, 0, 0, 0.2]]`.
    """

    progress_round_size = NumericProperty(dp(46))
    """
    Size of the spinner for switching of `selected_mode` mode.

    :attr:`progress_round_size` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `dp(46)`.
    """

    progress_round_color = ColorProperty(None)
    """
    Color of the spinner for switching of `selected_mode` mode.

    :attr:`progress_round_color` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `None`.
    """
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.register_event_type("on_selected")
        self.register_event_type("on_unselected")

    def add_widget(self, widget, index=0, canvas=None):
        selection_icon = SelectionIconCheck(
            icon=self.icon,
            md_bg_color=self.icon_bg_color,
            icon_check_color=self.icon_check_color,
        )
        container = SelectionItem(
            size_hint=(1, None),
            height=widget.height,
            instance_item=widget,
            instance_icon=selection_icon,
            overlay_color=self.overlay_color,
            progress_round_size=self.progress_round_size,
            progress_round_color=self.progress_round_color,
            owner=self,
        )
        container.add_widget(widget)

        if not self.icon_pos:
            pos = (
                dp(12),
                container.height / 2 - selection_icon.height / 2,
            )
        else:
            pos = self.icon_pos
        selection_icon.pos = pos
        container.add_widget(selection_icon)
        return super().add_widget(container, index, canvas)

    def get_selected(self) -> bool:
        """Returns ``True`` if at least one item in the list is checked."""

        selected = False
        for item in self.children:
            if item.selected:
                selected = True
                break
        return selected

    def get_selected_list_items(self) -> list:
        """
        Returns a list of marked objects:

        [<kivymd.uix.selection.SelectionItem object>, ...]
        """

        selected_list_items = []
        for item in self.children:
            if item.selected:
                selected_list_items.append(item)
        return selected_list_items

    def unselected_all(self) -> None:
        for item in self.children:
            item.do_unselected_item()
        self.selected_mode = False

    def selected_all(self) -> None:
        for item in self.children:
            item.do_selected_item()
        self.selected_mode = True

    def on_selected(self, *args):
        """Called when a list item is selected."""

        if not self.selected_mode:
            self.selected_mode = True

    def on_unselected(self, *args):
        """Called when a list item is unselected."""

        self.selected_mode = self.get_selected()
Example #42
0
class SelectionItem(ThemableBehavior, MDRelativeLayout, TouchBehavior):
    selected = BooleanProperty(False)
    """
    Whether or not an item is checked.

    :attr:`selected` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    owner = ObjectProperty()
    """
    Instance of :class:`~kivymd.uix.selection.MDSelectionList` class.

    :attr:`owner` is an :class:`~kivy.properties.ObjectProperty`
    and defaults to `None`.
    """

    instance_item = ObjectProperty()
    """
    User item. Must be a Kivy or KivyMD widget.

    :attr:`instance_item` is an :class:`~kivy.properties.ObjectProperty`
    and defaults to `None`.
    """

    instance_icon = ObjectProperty()
    """
    Instance of :class:`~kivymd.uix.selection.SelectionIconCheck` class.

    :attr:`instance_icon` is an :class:`~kivy.properties.ObjectProperty`
    and defaults to `None`.
    """

    overlay_color = ColorProperty([0, 0, 0, 0.2])
    """See :attr:`~MDSelectionList.overlay_color`."""

    progress_round_size = NumericProperty(dp(46))
    """See :attr:`~MDSelectionList.progress_round_size`."""

    progress_round_color = ColorProperty(None)
    """See :attr:`~MDSelectionList.progress_round_color`."""

    _progress_round = NumericProperty(0)
    _progress_line_end = NumericProperty(0)
    _progress_animation = BooleanProperty(False)
    _touch_long = BooleanProperty(False)
    _instance_progress_inner_circle_color = ObjectProperty()
    _instance_progress_inner_circle_ellipse = ObjectProperty()
    _instance_progress_inner_outer_color = ObjectProperty()
    _instance_progress_inner_outer_line = ObjectProperty()
    _instance_overlay_color = ObjectProperty()
    _instance_overlay_rounded_rec = ObjectProperty()

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        Clock.schedule_once(self.set_progress_round)

    def set_progress_round(self, interval: Union[int, float]) -> None:
        with self.canvas.after:
            self._instance_progress_inner_circle_color = Color(rgba=(0, 0, 0,
                                                                     0))
            self._instance_progress_inner_circle_ellipse = Ellipse(
                size=self.get_progress_round_size(),
                pos=self.get_progress_round_pos(),
            )
            self.bind(
                pos=self.update_progress_inner_circle_ellipse,
                size=self.update_progress_inner_circle_ellipse,
            )
            # FIXME: Radius value is not displayed.
            self._instance_overlay_color = Color(rgba=(0, 0, 0, 0))
            self._instance_overlay_rounded_rec = RoundedRectangle(
                size=self.size,
                pos=self.pos,
                radius=self.instance_item.radius if hasattr(
                    self.instance_item, "radius") else [
                        0,
                    ],
            )
            self.bind(
                pos=self.update_overlay_rounded_rec,
                size=self.update_overlay_rounded_rec,
            )
            self._instance_progress_inner_outer_color = Color(rgba=(0, 0, 0,
                                                                    0))
            self._instance_progress_inner_outer_line = SmoothLine(
                width=dp(4),
                circle=[
                    self.center_x,
                    self.center_y,
                    self.progress_round_size * 0.58,
                    0,
                    0,
                ],
            )

    def do_selected_item(self, *args) -> None:
        Animation(scale=1, d=0.2).start(self.instance_icon)
        self.selected = True
        self._progress_animation = False
        self._instance_overlay_color.rgba = self.get_overlay_color()
        self.owner.dispatch("on_selected", self)

    def do_unselected_item(self) -> None:
        Animation(scale=0, d=0.2).start(self.instance_icon)
        self.selected = False
        self._instance_overlay_color.rgba = self.get_overlay_color()
        self.owner.dispatch("on_unselected", self)

    def do_animation_progress_line(self, animation: Animation,
                                   instance_selection_item,
                                   value: float) -> None:
        self._instance_progress_inner_outer_line.circle = (
            self.center_x,
            self.center_y,
            self.progress_round_size * 0.58,
            0,
            360 * value,
        )

    def update_overlay_rounded_rec(self, *args) -> None:
        self._instance_overlay_rounded_rec.size = self.size
        self._instance_overlay_rounded_rec.pos = self.pos

    def update_progress_inner_circle_ellipse(self, *args) -> None:
        self._instance_progress_inner_circle_ellipse.size = (
            self.get_progress_round_size())
        self._instance_progress_inner_circle_ellipse.pos = (
            self.get_progress_round_pos())

    def reset_progress_animation(self) -> None:
        Animation.cancel_all(self)
        self._progress_animation = False
        self._instance_progress_inner_circle_color.rgba = (0, 0, 0, 0)
        self._instance_progress_inner_outer_color.rgba = (0, 0, 0, 0)
        self._instance_progress_inner_outer_line.circle = [
            self.center_x,
            self.center_y,
            self.progress_round_size * 0.58,
            0,
            0,
        ]
        self._progress_line_end = 0

    def get_overlay_color(self) -> list:
        return self.overlay_color if self.selected else (0, 0, 0, 0)

    def get_progress_round_pos(self) -> tuple:
        return (
            self.center_x - self.progress_round_size / 2,
            self.center_y - self.progress_round_size / 2,
        )

    def get_progress_round_size(self) -> tuple:
        return self.progress_round_size, self.progress_round_size

    def get_progress_round_color(self) -> tuple:
        return (self.theme_cls.primary_color if not self.progress_round_color
                else self.progress_round_color)

    def get_progress_line_color(self) -> tuple:
        return (self.theme_cls.primary_color[:-1] +
                [0.5] if not self.progress_round_color else
                self.progress_round_color[:-1] + [0.5])

    def on_long_touch(self, *args) -> None:
        if not self.owner.get_selected():
            self._touch_long = True
            self._progress_animation = True

    def on_touch_up(self, touch):
        if self.collide_point(*touch.pos):
            if self._touch_long:
                self._touch_long = False
        return super().on_touch_up(touch)

    def on_touch_down(self, touch):
        if self.collide_point(*touch.pos):
            if self.selected:
                self.do_unselected_item()
            else:
                if self.owner.selected_mode:
                    self.do_selected_item()
        return super().on_touch_down(touch)

    def on__touch_long(self, instance_selection_tem,
                       touch_value: bool) -> None:
        if not touch_value:
            self.reset_progress_animation()

    def on__progress_animation(self, instance_selection_tem,
                               touch_value: bool) -> None:
        if touch_value:
            anim = Animation(_progress_line_end=360, d=1, t="in_out_quad")
            anim.bind(
                on_progress=self.do_animation_progress_line,
                on_complete=self.do_selected_item,
            )
            anim.start(self)
            self._instance_progress_inner_outer_color.rgba = (
                self.get_progress_line_color())
            self._instance_progress_inner_circle_color.rgba = (
                self.get_progress_round_color())
        else:
            self.reset_progress_animation()
Example #43
0
class ThreeLineIconListItem(ContainerSupport, ThreeLineListItem):
    _txt_left_pad = NumericProperty(dp(72))
Example #44
0
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     self._txt_right_pad = dp(40) + m_res.HORIZ_MARGINS
Example #45
0
 def __init__(self, **kwargs):
     super().__init__(**kwargs)
     self.height = dp(72) if not self._height else self._height
Example #46
0
 def __init__(self):
     super(HohenGame, self).__init__()
     self.textinput = TextInput(hint_text='Your commands here..',
                                x=metrics.dp(10),
                                y=metrics.dp(48),
                                multiline=False,
                                width=metrics.dp(470),
                                height=metrics.dp(38))
     self.cmd = Label(text="Welcome to Hohenheim!",
                      x=metrics.dp(196),
                      y=metrics.dp(130),
                      text_size=(metrics.dp(460), metrics.dp(160)),
                      markup=True)
     self.textinput.bind(on_text_validate=self.on_enter)
     self.giant = Sprite(source='images/giant.png',
                         x=metrics.dp(620),
                         y=metrics.dp(330))
     self.depo = Sprite(source='images/deposit.png',
                        x=metrics.dp(220),
                        y=metrics.dp(470))
     self.axe = Sprite(source='images/axe.png',
                       x=metrics.dp(1220),
                       y=metrics.dp(470))
     self.invaxe = Image(source='images/axe.png',
                         x=metrics.dp(self.invx('axe')),
                         y=metrics.dp(self.invy('axe')),
                         width=metrics.dp(30))
     self.invdepo = Image(source='images/deposit.png',
                          x=metrics.dp(self.invx('depo')),
                          y=metrics.dp(self.invy('depo')),
                          width=metrics.dp(30))
     self.background = Sprite(source='images/background_nobridge.jpg')
     self.bridge = Sprite(source='images/bridge.jpg',
                          x=metrics.dp(500),
                          y=metrics.dp(260))
     self.bridge_active = Sprite(source='images/bridge_active.jpg',
                                 x=metrics.dp(500),
                                 y=metrics.dp(260))
     self.takehelp = {'axe': self.axe, 'depo': self.depo}
     self.gmhelp = {
         'giant': self.giant,
         'bridge': self.bridge,
         'bridge_active': self.bridge_active
     }
     self.invhelp = {'axe': self.invaxe, 'depo': self.invdepo}
     self.add_widget(self.background)
     self.add_widget(self.textinput)
     self.add_widget(self.cmd)
     self.addobjects()
Example #47
0
    def on_focus(self, *args):
        disabled_hint_text_color = self.theme_cls.disabled_hint_text_color
        Animation.cancel_all(self, "_line_width", "_hint_y",
                             "_hint_lbl_font_size")
        self._set_text_len_error()

        if self.focus:
            _fill_color = self.fill_color
            _fill_color[3] = self.fill_color[3] - 0.1
            if not self._get_has_error():

                def on_progress(*args):
                    self._line_blank_space_right_point = (
                        self._hint_lbl.width + dp(5))

                animation = Animation(
                    _line_blank_space_left_point=self._hint_lbl.x - dp(5),
                    _current_hint_text_color=self.line_color_focus,
                    fill_color=_fill_color,
                    duration=0.2,
                    t="out_quad",
                )
                animation.bind(on_progress=on_progress)
                animation.start(self)
            self.has_had_text = True
            Animation.cancel_all(self, "_line_width", "_hint_y",
                                 "_hint_lbl_font_size")
            if not self.text:
                self._anim_lbl_font_size(dp(14), sp(12))
            Animation(
                _line_width=self.width,
                duration=(0.2 if self.line_anim else 0),
                t="out_quad",
            ).start(self)
            if self._get_has_error():
                self._anim_current_error_color(self.error_color)
                if self.helper_text_mode == "on_error" and (
                        self.error or self._text_len_error):
                    self._anim_current_error_color(self.error_color)
                elif (self.helper_text_mode == "on_error" and not self.error
                      and not self._text_len_error):
                    self._anim_current_error_color((0, 0, 0, 0))
                elif self.helper_text_mode in ("persistent", "on_focus"):
                    self._anim_current_error_color(disabled_hint_text_color)
            else:
                self._anim_current_right_lbl_color(disabled_hint_text_color)
                Animation(
                    duration=0.2,
                    _current_hint_text_color=self.line_color_focus).start(self)
                if self.helper_text_mode == "on_error":
                    self._anim_current_error_color((0, 0, 0, 0))
                if self.helper_text_mode in ("persistent", "on_focus"):
                    self._anim_current_error_color(disabled_hint_text_color)
        else:
            _fill_color = self.fill_color
            _fill_color[3] = self.fill_color[3] + 0.1
            Animation(fill_color=_fill_color, duration=0.2,
                      t="out_quad").start(self)
            if not self.text:
                self._anim_lbl_font_size(dp(38), sp(16))
                Animation(
                    _line_blank_space_right_point=0,
                    _line_blank_space_left_point=0,
                    duration=0.2,
                    t="out_quad",
                ).start(self)
            if self._get_has_error():
                self._anim_get_has_error_color(self.error_color)
                if self.helper_text_mode == "on_error" and (
                        self.error or self._text_len_error):
                    self._anim_current_error_color(self.error_color)
                elif (self.helper_text_mode == "on_error" and not self.error
                      and not self._text_len_error):
                    self._anim_current_error_color((0, 0, 0, 0))
                elif self.helper_text_mode == "persistent":
                    self._anim_current_error_color(disabled_hint_text_color)
                elif self.helper_text_mode == "on_focus":
                    self._anim_current_error_color((0, 0, 0, 0))
            else:
                Animation(duration=0.2,
                          color=(1, 1, 1, 1)).start(self._hint_lbl)
                self._anim_get_has_error_color()
                if self.helper_text_mode == "on_error":
                    self._anim_current_error_color((0, 0, 0, 0))
                elif self.helper_text_mode == "persistent":
                    self._anim_current_error_color(disabled_hint_text_color)
                elif self.helper_text_mode == "on_focus":
                    self._anim_current_error_color((0, 0, 0, 0))
                Animation(
                    _line_width=0,
                    duration=(0.2 if self.line_anim else 0),
                    t="out_quad",
                ).start(self)
Example #48
0
 def build(self):
     Game = Widget()
     Game.add_widget(HohenGame())
     Window.size = int(metrics.dp(1366)), int(metrics.dp(768))
     #Window.fullscreen = True
     return Game
Example #49
0
 def __init__(self, **kwargs):
     super(MultiLineListItem, self).__init__(**kwargs)
     self._num_lines = ceil(len(self.text) / 120.0)
     self.height = dp(37 + 20 * (self._num_lines - 1))
     self.text_size = self.width, None
     self.__post_init__(kwargs)
Example #50
0
 def get_normal_height(self):
     return ((Window.height * 80 / 100) - self._spacer_top - dp(52) -
             self.ids.container.padding[1] -
             self.ids.container.padding[-1] - 100)
Example #51
0
class MaterialList(ThemeBehaviour, BoxLayout):

    title = StringProperty('')

    tile_rows = BoundedNumericProperty(1, min=1, max=3)

    list_type = OptionProperty('text',
                               options=('text', 'icon_text', 'avatar_text',
                                        'avatar_text_icon'))

    text_color = ListProperty()

    text_color_selected = ListProperty()

    background_color_selected = ListProperty()

    background_color_disabled = ListProperty()

    divider_color = ListProperty([1, 1, 1, 0])

    selection_mode = OptionProperty('single',
                                    options=('none', 'single', 'multiple'))

    allow_empty_selection = BooleanProperty(False)

    selection_limit = NumericProperty(-1)

    list_data = ListProperty()

    selection = ListProperty([])

    _tile_height = NumericProperty(dp(48))
    _list_view = ObjectProperty()

    def __init__(self, **kwargs):
        super(MaterialList, self).__init__(**kwargs)
        self.register_event_type('on_selection')
        self.text_color = self._theme_cls.primary_text_color()
        self.text_color_selected = self._theme_cls.accent_color
        self.background_color_selected = get_rgba_color(
            [self._theme_cls.theme_style, 'FlatButtonDown'])
        self.background_color_disabled = self._theme_cls.disabled_bg_color()

        self.bind(tile_rows=self._set_tile_height, list_data=self._get_adapter)

    def on_selection(self, *args):
        pass

    def _get_adapter(self, *args):
        if self.list_type == 'text':
            converter = lambda row_index, rec: {
                'text':
                rec['text'],
                'secondary_text':
                rec['secondary_text'] if 'secondary_text' in rec else '',
                'tile_rows':
                self.tile_rows,
                'text_color_selected':
                self.text_color_selected,
                'background_color_selected':
                self.background_color_selected,
                'background_color_disabled':
                self.background_color_disabled,
                'divider_color':
                self.divider_color,
                'size_hint_y':
                None,
                'height':
                self._tile_height,
                'callback':
                rec['callback'] if 'callback' in rec else None
            }
            adapter = ListAdapter(data=self.list_data,
                                  args_converter=converter,
                                  cls=TextTile)
            adapter.bind(selection=self.setter('selection'))
            self._list_view.adapter = adapter
            self._list_view.adapter.selection_mode = self.selection_mode
            self._list_view.adapter.selection_limit = self.selection_limit
            self._list_view.adapter.allow_empty_selection = self.allow_empty_selection

        if self.list_type == 'icon_text':
            converter = lambda row_index, rec: {
                'icon':
                rec['icon'],
                'text':
                rec['text'],
                'secondary_text':
                rec['secondary_text'] if 'secondary_text' in rec else '',
                'tile_rows':
                self.tile_rows,
                'text_color_selected':
                self.text_color_selected,
                'background_color_selected':
                self.background_color_selected,
                'background_color_disabled':
                self.background_color_disabled,
                'divider_color':
                self.divider_color,
                'size_hint_y':
                None,
                'height':
                self._tile_height,
                'callback':
                rec['callback'] if 'callback' in rec else None
            }

            adapter = ListAdapter(data=self.list_data,
                                  args_converter=converter,
                                  cls=IconTextTile)
            adapter.bind(selection=self.setter('selection'))
            self._list_view.adapter = adapter
            self._list_view.adapter.selection_mode = self.selection_mode
            self._list_view.adapter.selection_limit = self.selection_limit
            self._list_view.adapter.allow_empty_selection = self.allow_empty_selection
        if self.list_type == 'avatar_text':
            converter = lambda row_index, rec: {
                'avatar':
                rec['avatar'],
                'text':
                rec['text'],
                'secondary_text':
                rec['secondary_text'] if 'secondary_text' in rec else '',
                'tile_rows':
                self.tile_rows,
                'text_color_selected':
                self.text_color_selected,
                'background_color_selected':
                self.background_color_selected,
                'background_color_disabled':
                self.background_color_disabled,
                'divider_color':
                self.divider_color,
                'size_hint_y':
                None,
                'height':
                self._tile_height,
                'callback':
                rec['callback'] if 'callback' in rec else None
            }

            adapter = ListAdapter(data=self.list_data,
                                  args_converter=converter,
                                  cls=AvatarTextTile)
            adapter.bind(selection=self.setter('selection'))
            self._list_view.adapter = adapter
            self._list_view.adapter.selection_mode = self.selection_mode
            self._list_view.adapter.selection_limit = self.selection_limit
            self._list_view.adapter.allow_empty_selection = self.allow_empty_selection

    def _set_tile_height(self, *args):
        if self.tile_rows == 1:
            if self.tile_type == 'text' or self.tile_type == 'icon_text':
                self._tile_height = dp(48)
            else:
                self._tile_height = dp(56)
        elif self.tile_rows == 2:
            self._tile_height = dp(72)
        else:
            self._tile_height = dp(88)
Example #52
0
 def update_height(self, *_):
     self._spacer_top = self.content_cls.height + dp(24)
 def _get_horizontal_margins(self):
     if DEVICE_TYPE == "mobile":
         return dp(16)
     else:
         return dp(24)
Example #54
0
class ThreeLineAvatarIconListItem(ThreeLineAvatarListItem):
    # dp(40) = dp(16) + dp(24):
    _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS)
Example #55
0
    def set_content(self, instance_content_dialog):
        def _events_callback(result_press):
            self.dismiss()
            if result_press:
                self.events_callback(result_press, self)

        if self.device_ios:  # create buttons for iOS
            self.background = self._background

            if instance_content_dialog.__class__ is ContentInputDialog:
                self.text_field = TextInput(
                    size_hint=(1, None), multiline=False, height=dp(33),
                    cursor_color=self.theme_cls.primary_color,
                    hint_text=instance_content_dialog.hint_text,
                    background_normal='{}ios_entr_ti.png'.format(images_path),
                    background_active='{}ios_entr_ti.png'.format(images_path))
                instance_content_dialog.ids.box_input.height = dp(33)
                instance_content_dialog.ids.box_input.add_widget(
                    self.text_field)

            if self.text_button_cancel != '':
                anchor = 'left'
            else:
                anchor = 'center'
            box_button_ok = AnchorLayout(anchor_x=anchor)
            box_button_ok.add_widget(
                MDTextButton(
                    text=self.text_button_ok, font_size='18sp',
                    on_release=lambda x: _events_callback(
                        self.text_button_ok)))
            instance_content_dialog.ids.box_buttons.add_widget(box_button_ok)

            if self.text_button_cancel != '':
                box_button_ok.anchor_x = 'left'
                box_button_cancel = AnchorLayout(anchor_x='right')
                box_button_cancel.add_widget(
                    MDTextButton(
                        text=self.text_button_cancel, font_size='18sp',
                        on_release=lambda x: _events_callback(
                            self.text_button_cancel)))
                instance_content_dialog.ids.box_buttons.add_widget(
                    box_button_cancel)

        else:  # create buttons for Android
            if instance_content_dialog.__class__ is ContentInputDialog:
                self.text_field = MDTextField(
                    size_hint=(1, None), height=dp(48),
                    hint_text=instance_content_dialog.hint_text)
                instance_content_dialog.ids.box_input.height = dp(48)
                instance_content_dialog.ids.box_input.add_widget(
                    self.text_field)
                instance_content_dialog.ids.box_buttons.remove_widget(
                    instance_content_dialog.ids.sep)

            box_buttons = AnchorLayout(
                anchor_x='right', size_hint_y=None, height=dp(30))
            box = BoxLayout(size_hint_x=None, spacing=dp(5))
            box.bind(minimum_width=box.setter('width'))
            button_ok = MDRaisedButton(
                text=self.text_button_ok,
                on_release=lambda x: _events_callback(self.text_button_ok))
            box.add_widget(button_ok)

            if self.text_button_cancel != '':
                button_cancel = MDFlatButton(
                    text=self.text_button_cancel,
                    theme_text_color='Custom',
                    text_color=self.theme_cls.primary_color,
                    on_release=lambda x: _events_callback(
                        self.text_button_cancel))
                box.add_widget(button_cancel)

            box_buttons.add_widget(box)
            instance_content_dialog.ids.box_buttons.add_widget(box_buttons)
            instance_content_dialog.ids.box_buttons.height = button_ok.height
            instance_content_dialog.remove_widget(
                instance_content_dialog.ids.sep)
Example #56
0
class ThreeLineRightIconListItem(ContainerSupport, ThreeLineListItem):
    # dp(40) = dp(16) + dp(24):
    _txt_right_pad = NumericProperty(dp(40) + m_res.HORIZ_MARGINS)
Example #57
0
    def _update_tabs(self, *l):
        self_content = self.content
        if not self_content:
            return
        # cache variables for faster access
        tab_pos = self.tab_pos
        tab_layout = self._tab_layout
        tab_layout.clear_widgets()
        scrl_v = ScrollView(size_hint=(None, 1))
        tabs = self._tab_strip
        parent = tabs.parent
        if parent:
            parent.remove_widget(tabs)
        scrl_v.add_widget(tabs)
        scrl_v.pos = (0, 0)
        self_update_scrollview = self._update_scrollview

        # update scrlv width when tab width changes depends on tab_pos
        if self._partial_update_scrollview is not None:
            tabs.unbind(width=self._partial_update_scrollview)
        self._partial_update_scrollview = partial(self_update_scrollview,
                                                  scrl_v)
        tabs.bind(width=self._partial_update_scrollview)

        # remove all widgets from the tab_strip
        self.clear_widgets(do_super=True)
        tab_height = self.tab_height

        widget_list = []
        tab_list = []
        pos_letter = tab_pos[0]
        if pos_letter == 'b' or pos_letter == 't':
            # bottom or top positions
            # one col containing the tab_strip and the content
            self.cols = 1
            self.rows = 2
            # tab_layout contains the scrollview containing tabs and two blank
            # dummy widgets for spacing
            tab_layout.rows = 1
            tab_layout.cols = 3
            tab_layout.size_hint = (1, None)
            tab_layout.height = (tab_height + tab_layout.padding[1] +
                                 tab_layout.padding[3] + dp(2))
            self_update_scrollview(scrl_v)

            if pos_letter == 'b':
                # bottom
                if tab_pos == 'bottom_mid':
                    tab_list = (Widget(), scrl_v, Widget())
                    widget_list = (self_content, tab_layout)
                else:
                    if tab_pos == 'bottom_left':
                        tab_list = (scrl_v, Widget(), Widget())
                    elif tab_pos == 'bottom_right':
                        # add two dummy widgets
                        tab_list = (Widget(), Widget(), scrl_v)
                    widget_list = (self_content, tab_layout)
            else:
                # top
                if tab_pos == 'top_mid':
                    tab_list = (Widget(), scrl_v, Widget())
                elif tab_pos == 'top_left':
                    tab_list = (scrl_v, Widget(), Widget())
                elif tab_pos == 'top_right':
                    tab_list = (Widget(), Widget(), scrl_v)
                widget_list = (tab_layout, self_content)
        elif pos_letter == 'l' or pos_letter == 'r':
            # left ot right positions
            # one row containing the tab_strip and the content
            self.cols = 2
            self.rows = 1
            # tab_layout contains two blank dummy widgets for spacing
            # "vertically" and the scatter containing scrollview
            # containing tabs
            tab_layout.rows = 3
            tab_layout.cols = 1
            tab_layout.size_hint = (None, 1)
            tab_layout.width = tab_height
            scrl_v.height = tab_height
            self_update_scrollview(scrl_v)

            # rotate the scatter for vertical positions
            rotation = 90 if tab_pos[0] == 'l' else -90
            sctr = Scatter(do_translation=False,
                           rotation=rotation,
                           do_rotation=False,
                           do_scale=False,
                           size_hint=(None, None),
                           auto_bring_to_front=False,
                           size=scrl_v.size)
            sctr.add_widget(scrl_v)

            lentab_pos = len(tab_pos)

            # Update scatter's top when it's pos changes.
            # Needed for repositioning scatter to the correct place after its
            # added to the parent. Use clock_schedule_once to ensure top is
            # calculated after the parent's pos on canvas has been calculated.
            # This is needed for when tab_pos changes to correctly position
            # scatter. Without clock.schedule_once the positions would look
            # fine but touch won't translate to the correct position

            if tab_pos[lentab_pos - 4:] == '_top':
                # on positions 'left_top' and 'right_top'
                sctr.bind(pos=partial(self._update_top, sctr, 'top', None))
                tab_list = (sctr, )
            elif tab_pos[lentab_pos - 4:] == '_mid':
                # calculate top of scatter
                sctr.bind(
                    pos=partial(self._update_top, sctr, 'mid', scrl_v.width))
                tab_list = (Widget(), sctr, Widget())
            elif tab_pos[lentab_pos - 7:] == '_bottom':
                tab_list = (Widget(), Widget(), sctr)

            if pos_letter == 'l':
                widget_list = (tab_layout, self_content)
            else:
                widget_list = (self_content, tab_layout)

        # add widgets to tab_layout
        add = tab_layout.add_widget
        for widg in tab_list:
            add(widg)

        # add widgets to self
        add = self.add_widget
        for widg in widget_list:
            add(widg)
Example #58
0
 def back_to_previous_screen(self, *args):
     if self.menu_open:
         self.menu_open = False
         self.hide_menu_list_animation()
     App.get_running_app().main_widget.ids.scr_mngr.current = "previous"
     App.get_running_app().main_widget.ids.toolbar.height = dp(56)
Example #59
0
 def set_shadow(self, *args):
     self.action_button._hard_shadow_size = (dp(112), dp(112))
     self.action_button._soft_shadow_size = (dp(112), dp(112))
class MDTapTargetView(ThemableBehavior, EventDispatcher):
    """Rough try to mimic the working of Android's TapTargetView.

    :Events:
        :attr:`on_open`
            Called at the time of the start of the widget opening animation.
        :attr:`on_close`
            Called at the time of the start of the widget closed animation.
    """

    widget = ObjectProperty()
    """
    Widget to add ``TapTargetView`` upon.

    :attr:`widget` is an :class:`~kivy.properties.ObjectProperty`
    and defaults to `None`.
    """

    outer_radius = NumericProperty(dp(200))
    """
    Radius for outer circle.

    .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/tap-target-view-widget-outer-radius.png
        :align: center

    :attr:`outer_radius` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `dp(200)`.
    """

    outer_circle_color = ListProperty()
    """
    Color for the outer circle in ``rgb`` format.

    .. code-block:: python

        self.tap_target_view = MDTapTargetView(
            ...
            outer_circle_color=(1, 0, 0)
        )

    .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/tap-target-view-widget-outer-circle-color.png
        :align: center

    :attr:`outer_circle_color` is an :class:`~kivy.properties.ListProperty`
    and defaults to ``theme_cls.primary_color``.
    """

    outer_circle_alpha = NumericProperty(0.96)
    """
    Alpha value for outer circle.

    :attr:`outer_circle_alpha` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `0.96`.
    """

    target_radius = NumericProperty(dp(45))
    """
    Radius for target circle.

    .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/tap-target-view-widget-target-radius.png
        :align: center

    :attr:`target_radius` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `dp(45)`.
    """

    target_circle_color = ListProperty([1, 1, 1])
    """
    Color for target circle in ``rgb`` format.

    .. code-block:: python

        self.tap_target_view = MDTapTargetView(
            ...
            target_circle_color=(1, 0, 0)
        )

    .. image:: https://github.com/HeaTTheatR/KivyMD-data/raw/master/gallery/kivymddoc/tap-target-view-widget-target-circle-color.png
        :align: center

    :attr:`target_circle_color` is an :class:`~kivy.properties.ListProperty`
    and defaults to `[1, 1, 1]`.
    """

    title_text = StringProperty()
    """
    Title to be shown on the view.

    :attr:`title_text` is an :class:`~kivy.properties.StringProperty`
    and defaults to `''`.
    """

    title_text_size = NumericProperty(dp(25))
    """
    Text size for title.

    :attr:`title_text_size` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `dp(25)`.
    """

    title_text_color = ListProperty([1, 1, 1, 1])
    """
    Text color for title.

    :attr:`title_text_color` is an :class:`~kivy.properties.ListProperty`
    and defaults to `[1, 1, 1, 1]`.
    """

    title_text_bold = BooleanProperty(True)
    """
    Whether title should be bold.

    :attr:`title_text_bold` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `True`.
    """

    description_text = StringProperty()
    """
    Description to be shown below the title (keep it short).

    :attr:`description_text` is an :class:`~kivy.properties.StringProperty`
    and defaults to `''`.
    """

    description_text_size = NumericProperty(dp(20))
    """
    Text size for description text.

    :attr:`description_text_size` is an :class:`~kivy.properties.NumericProperty`
    and defaults to `dp(20)`.
    """

    description_text_color = ListProperty([0.9, 0.9, 0.9, 1])
    """
    Text size for description text.

    :attr:`description_text_color` is an :class:`~kivy.properties.ListProperty`
    and defaults to `[0.9, 0.9, 0.9, 1]`.
    """

    description_text_bold = BooleanProperty(False)
    """
    Whether description should be bold.

    :attr:`description_text_bold` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    draw_shadow = BooleanProperty(False)
    """
    Whether to show shadow.

    :attr:`draw_shadow` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    cancelable = BooleanProperty(False)
    """
    Whether clicking outside the outer circle dismisses the view.

    :attr:`cancelable` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    widget_position = OptionProperty(
        "left",
        options=[
            "left",
            "right",
            "top",
            "bottom",
            "left_top",
            "right_top",
            "left_bottom",
            "right_bottom",
            "center",
        ],
    )
    """
    Sets the position of the widget on the :attr:`~outer_circle`. Available options are
    `'left`', `'right`', `'top`', `'bottom`', `'left_top`', `'right_top`',
    `'left_bottom`', `'right_bottom`', `'center`'.

    :attr:`widget_position` is an :class:`~kivy.properties.OptionProperty`
    and defaults to `'left'`.
    """

    title_position = OptionProperty(
        "auto",
        options=[
            "auto",
            "left",
            "right",
            "top",
            "bottom",
            "left_top",
            "right_top",
            "left_bottom",
            "right_bottom",
        ],
    )
    """
    Sets the position of :attr`~title_text` on the outer circle. Only works if
    :attr`~widget_position` is set to `'center'`. In all other cases, it
    calculates the :attr`~title_position` itself.
    Must be set to other than `'auto`' when :attr`~widget_position` is set
    to `'center`'.

    Available options are `'auto'`, `'left`', `'right`', `'top`', `'bottom`',
    `'left_top`', `'right_top`', `'left_bottom`', `'right_bottom`', `'center`'.

    :attr:`title_position` is an :class:`~kivy.properties.OptionProperty`
    and defaults to `'auto'`.
    """

    stop_on_outer_touch = BooleanProperty(False)
    """
    Whether clicking on outer circle stops the animation.

    :attr:`stop_on_outer_touch` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `False`.
    """

    stop_on_target_touch = BooleanProperty(True)
    """
    Whether clicking on target circle should stop the animation.

    :attr:`stop_on_target_touch` is an :class:`~kivy.properties.BooleanProperty`
    and defaults to `True`.
    """

    state = OptionProperty("close", options=["close", "open"])
    """
    State of :class:`~MDTapTargetView`.

    :attr:`state` is an :class:`~kivy.properties.OptionProperty`
    and defaults to `'close'`.
    """

    _outer_radius = NumericProperty(0)
    _target_radius = NumericProperty(0)

    def __init__(self, **kwargs):
        self.ripple_max_dist = dp(90)
        self.on_outer_radius(self, self.outer_radius)
        self.on_target_radius(self, self.target_radius)

        self.core_title_text = Label(
            markup=True, size_hint=(None, None), bold=self.title_text_bold
        )
        self.core_title_text.bind(texture_size=self.core_title_text.setter("size"))
        self.core_description_text = Label(markup=True, size_hint=(None, None))
        self.core_description_text.bind(
            texture_size=self.core_description_text.setter("size")
        )

        super().__init__(**kwargs)
        self.register_event_type("on_outer_touch")
        self.register_event_type("on_target_touch")
        self.register_event_type("on_outside_click")
        self.register_event_type("on_open")
        self.register_event_type("on_close")

        if not self.outer_circle_color:
            self.outer_circle_color = self.theme_cls.primary_color[:-1]

    def _initialize(self):
        setattr(self.widget, "_outer_radius", 0)
        setattr(self.widget, "_target_radius", 0)
        setattr(self.widget, "target_ripple_radius", 0)
        setattr(self.widget, "target_ripple_alpha", 0)

        # Bind some function on widget event when this function is called
        # instead of when the class itself is initialized to prevent all
        # widgets of all instances to get bind at once and start messing up.
        self.widget.bind(on_touch_down=self._some_func)

    def _draw_canvas(self):
        _pos = self._ttv_pos()
        self.widget.canvas.before.clear()

        with self.widget.canvas.before:
            # Outer circle.
            Color(
                *self.outer_circle_color,
                self.outer_circle_alpha,
                group="ttv_group",
            )
            _rad1 = self.widget._outer_radius
            Ellipse(size=(_rad1, _rad1), pos=_pos[0], group="ttv_group")

            # Title text.
            Color(*self.title_text_color, group="ttv_group")
            Rectangle(
                size=self.core_title_text.texture.size,
                texture=self.core_title_text.texture,
                pos=_pos[1],
                group="ttv_group",
            )

            # Description text.
            Color(*self.description_text_color, group="ttv_group")
            Rectangle(
                size=self.core_description_text.texture.size,
                texture=self.core_description_text.texture,
                pos=(
                    _pos[1][0],
                    _pos[1][1] - self.core_description_text.size[1] - 5,
                ),
                group="ttv_group",
            )

            # Target circle.
            Color(*self.target_circle_color, group="ttv_group")
            _rad2 = self.widget._target_radius
            Ellipse(
                size=(_rad2, _rad2),
                pos=(
                    self.widget.x - (_rad2 / 2 - self.widget.size[0] / 2),
                    self.widget.y - (_rad2 / 2 - self.widget.size[0] / 2),
                ),
                group="ttv_group",
            )

            # Target ripple.
            Color(
                *self.target_circle_color,
                self.widget.target_ripple_alpha,
                group="ttv_group",
            )
            _rad3 = self.widget.target_ripple_radius
            Ellipse(
                size=(_rad3, _rad3),
                pos=(
                    self.widget.x - (_rad3 / 2 - self.widget.size[0] / 2),
                    self.widget.y - (_rad3 / 2 - self.widget.size[0] / 2),
                ),
                group="ttv_group",
            )

    def stop(self, *args):
        """Starts widget close animation."""

        # It needs a better implementation.
        self.anim_ripple.unbind(on_complete=self._repeat_ripple)
        self.core_title_text.opacity = 0
        self.core_description_text.opacity = 0
        anim = Animation(
            d=0.15,
            t="in_cubic",
            **dict(
                zip(
                    ["_outer_radius", "_target_radius", "target_ripple_radius"],
                    [0, 0, 0],
                )
            ),
        )
        anim.bind(on_complete=self._after_stop)
        anim.start(self.widget)

    def _after_stop(self, *args):
        self.widget.canvas.before.remove_group("ttv_group")
        args[0].stop_all(self.widget)
        elev = getattr(self.widget, "elevation", None)

        if elev:
            self._fix_elev()
        self.dispatch("on_close")

        # Don't forget to unbind the function or it'll mess
        # up with other next bindings.
        self.widget.unbind(on_touch_down=self._some_func)
        self.state = "close"

    def _fix_elev(self):
        with self.widget.canvas.before:
            Color(a=self.widget._soft_shadow_a)
            Rectangle(
                texture=self.widget._soft_shadow_texture,
                size=self.widget._soft_shadow_size,
                pos=self.widget._soft_shadow_pos,
            )
            Color(a=self.widget._hard_shadow_a)
            Rectangle(
                texture=self.widget._hard_shadow_texture,
                size=self.widget._hard_shadow_size,
                pos=self.widget._hard_shadow_pos,
            )
            Color(a=1)

    def start(self, *args):
        """Starts widget opening animation."""

        self._initialize()
        self._animate_outer()
        self.state = "open"
        self.core_title_text.opacity = 1
        self.core_description_text.opacity = 1
        self.dispatch("on_open")

    def _animate_outer(self):
        anim = Animation(
            d=0.2,
            t="out_cubic",
            **dict(
                zip(
                    ["_outer_radius", "_target_radius"],
                    [self._outer_radius, self._target_radius],
                )
            ),
        )
        anim.cancel_all(self.widget)
        anim.bind(on_progress=lambda x, y, z: self._draw_canvas())
        anim.bind(on_complete=self._animate_ripple)
        anim.start(self.widget)
        setattr(self.widget, "target_ripple_radius", self._target_radius)
        setattr(self.widget, "target_ripple_alpha", 1)

    def _animate_ripple(self, *args):
        self.anim_ripple = Animation(
            d=1,
            t="in_cubic",
            target_ripple_radius=self._target_radius + self.ripple_max_dist,
            target_ripple_alpha=0,
        )
        self.anim_ripple.stop_all(self.widget)
        self.anim_ripple.bind(on_progress=lambda x, y, z: self._draw_canvas())
        self.anim_ripple.bind(on_complete=self._repeat_ripple)
        self.anim_ripple.start(self.widget)

    def _repeat_ripple(self, *args):
        setattr(self.widget, "target_ripple_radius", self._target_radius)
        setattr(self.widget, "target_ripple_alpha", 1)
        self._animate_ripple()

    def on_open(self, *args):
        """Called at the time of the start of the widget opening animation."""

    def on_close(self, *args):
        """Called at the time of the start of the widget closed animation."""

    def on_draw_shadow(self, instance, value):
        Logger.warning(
            "The shadow adding method will be implemented in future versions"
        )

    def on_description_text(self, instance, value):
        self.core_description_text.text = value

    def on_description_text_size(self, instance, value):
        self.core_description_text.font_size = value

    def on_description_text_bold(self, instance, value):
        self.core_description_text.bold = value

    def on_title_text(self, instance, value):
        self.core_title_text.text = value

    def on_title_text_size(self, instance, value):
        self.core_title_text.font_size = value

    def on_title_text_bold(self, instance, value):
        self.core_title_text.bold = value

    def on_outer_radius(self, instance, value):
        self._outer_radius = self.outer_radius * 2

    def on_target_radius(self, instance, value):
        self._target_radius = self.target_radius * 2

    def on_target_touch(self):
        if self.stop_on_target_touch:
            self.stop()

    def on_outer_touch(self):
        if self.stop_on_outer_touch:
            self.stop()

    def on_outside_click(self):
        if self.cancelable:
            self.stop()

    def _some_func(self, wid, touch):
        """
        This function decides which one to dispatch based on the touch
        position.
        """

        if self._check_pos_target(touch.pos):
            self.dispatch("on_target_touch")
        elif self._check_pos_outer(touch.pos):
            self.dispatch("on_outer_touch")
        else:
            self.dispatch("on_outside_click")

    def _check_pos_outer(self, pos):
        """
        Checks if a given `pos` coordinate is within the :attr:`~outer_radius`.
        """

        cx = self.circ_pos[0] + self._outer_radius / 2
        cy = self.circ_pos[1] + self._outer_radius / 2
        r = self._outer_radius / 2
        h, k = pos

        lhs = (cx - h) ** 2 + (cy - k) ** 2
        rhs = r ** 2
        if lhs <= rhs:
            return True
        return False

    def _check_pos_target(self, pos):
        """
        Checks if a given `pos` coordinate is within the
        :attr:`~target_radius`.
        """

        cx = self.widget.pos[0] + self.widget.width / 2
        cy = self.widget.pos[1] + self.widget.height / 2
        r = self._target_radius / 2
        h, k = pos

        lhs = (cx - h) ** 2 + (cy - k) ** 2
        rhs = r ** 2
        if lhs <= rhs:
            return True
        return False

    def _ttv_pos(self):
        """
        Calculates the `pos` value for outer circle and text
        based on the position provided.

        :returns: A tuple containing pos for the circle and text.
        """

        _rad1 = self.widget._outer_radius
        _center_x = self.widget.x - (_rad1 / 2 - self.widget.size[0] / 2)
        _center_y = self.widget.y - (_rad1 / 2 - self.widget.size[0] / 2)

        if self.widget_position == "left":
            circ_pos = (_center_x + _rad1 / 3, _center_y)
            title_pos = (_center_x + _rad1 / 1.4, _center_y + _rad1 / 1.4)
        elif self.widget_position == "right":
            circ_pos = (_center_x - _rad1 / 3, _center_y)
            title_pos = (_center_x - _rad1 / 10, _center_y + _rad1 / 1.4)
        elif self.widget_position == "top":
            circ_pos = (_center_x, _center_y - _rad1 / 3)
            title_pos = (_center_x + _rad1 / 4, _center_y + _rad1 / 4)
        elif self.widget_position == "bottom":
            circ_pos = (_center_x, _center_y + _rad1 / 3)
            title_pos = (_center_x + _rad1 / 4, _center_y + _rad1 / 1.2)
        # Corner ones need to be at a little smaller distance
        # than edge ones that's why _rad1/4.
        elif self.widget_position == "left_top":
            circ_pos = (_center_x + _rad1 / 4, _center_y - _rad1 / 4)
            title_pos = (_center_x + _rad1 / 2, _center_y + _rad1 / 4)
        elif self.widget_position == "right_top":
            circ_pos = (_center_x - _rad1 / 4, _center_y - _rad1 / 4)
            title_pos = (_center_x - _rad1 / 10, _center_y + _rad1 / 4)
        elif self.widget_position == "left_bottom":
            circ_pos = (_center_x + _rad1 / 4, _center_y + _rad1 / 4)
            title_pos = (_center_x + _rad1 / 2, _center_y + _rad1 / 1.2)
        elif self.widget_position == "right_bottom":
            circ_pos = (_center_x - _rad1 / 4, _center_y + _rad1 / 4)
            title_pos = (_center_x, _center_y + _rad1 / 1.2)
        else:
            # Center.
            circ_pos = (_center_x, _center_y)

            if self.title_position == "auto":
                raise ValueError(
                    "widget_position='center' requires title_position to be set."
                )
            elif self.title_position == "left":
                title_pos = (_center_x + _rad1 / 10, _center_y + _rad1 / 2)
            elif self.title_position == "right":
                title_pos = (_center_x + _rad1 / 1.6, _center_y + _rad1 / 2)
            elif self.title_position == "top":
                title_pos = (_center_x + _rad1 / 2.5, _center_y + _rad1 / 1.3)
            elif self.title_position == "bottom":
                title_pos = (_center_x + _rad1 / 2.5, _center_y + _rad1 / 4)
            elif self.title_position == "left_top":
                title_pos = (_center_x + _rad1 / 8, _center_y + _rad1 / 1.4)
            elif self.title_position == "right_top":
                title_pos = (_center_x + _rad1 / 2, _center_y + _rad1 / 1.3)
            elif self.title_position == "left_bottom":
                title_pos = (_center_x + _rad1 / 8, _center_y + _rad1 / 4)
            elif self.title_position == "right_bottom":
                title_pos = (_center_x + _rad1 / 2, _center_y + _rad1 / 3.5)
            else:
                raise ValueError(
                    f"'{self.title_position}'"
                    f"is not a valid value for title_position"
                )

        self.circ_pos = circ_pos
        return circ_pos, title_pos