Esempio n. 1
0
    def _add_expanded_image (self, wid):
        for child in self._expansion_cont.children:
            if type (child) == FloatLayout:
                self._expansion_cont.remove_widget (child)
        self.pre_cont = BoxLayout (size_hint = (1, 1), padding=10, orientation='horizontal')
        self.pre_cont.canvas.add (Color (0,0,0,0.75))
        self.pre_cont.canvas.add (Rectangle (size=self._expansion_cont.size))
        _handler = Scatter ()
        _image = Image (source = self._img.source,
                        keep_ratio =False, allow_stretch=True)
        _btn = Button (text='Hide', size_hint = (0.05, 1))

        def _center (wid, val):
            img_width = val[0]*0.75
            img_height = img_width / _image.image_ratio
            _image.size = (img_width, img_height)
            _image.pos = ((val[0] - img_width)/2, (val[1] - img_height) / 2)

        _handler.bind (size=_center)
        _btn.bind (on_release =self._rmv_expanded_image)
        _handler.add_widget (_image)
        self.pre_cont.add_widget (_btn)
        self.pre_cont.add_widget (_handler)

        self._expansion_cont.add_widget (self.pre_cont)
Esempio n. 2
0
def create_controller():
	#create controller for swiping and pinching in the center

	# few parameters for scaling

	# this defines the active area of dragging/zooming
	normal_scale = 4.5
	# amount of pinch for zoom in and out
	zoom_in_scale = 5.5
	zoom_out_scale = 3.5
	# distance to drag in x and y direction for action
	x_sensitive= Window.center[0]/3
	y_sensitive = Window.center[1]/3


	# Controller(scatter object) that can be scaled and translate
	controller = Scatter(size_hint = (None,None), do_rotation=False, do_translation=True,
	do_scale=True, scale = normal_scale,
	scale_min= zoom_out_scale, scale_max=zoom_in_scale, center = Window.center)

	# a reference object to show the active area
	#control_object = Image()
	#controller.add_widget(control_object)

	#create microscope control parts
	microscope_control = microscope_controller()
	mc.step = 100

# this provides actions when moving and zooming the scatter objects
	def control_feedback(arg1, arg2):
		'the callback functions for controller scatter object'

		if controller.center[0] - Window.center[0] > x_sensitive:
			microscope_control.drag_right()

		elif controller.center[0] - Window.center[0] < -1* x_sensitive:
			microscope_control.drag_left()

		elif controller.center[1] - Window.center[1] > y_sensitive:
			microscope_control.drag_top()

		elif controller.center[1] - Window.center[1] < -1*y_sensitive:
			microscope_control.drag_bot()

		elif controller.scale < zoom_out_scale*1.1:
			microscope_control.pinch_out()

		elif controller.scale > zoom_in_scale*0.9:
			microscope_control.pinch_in()

		'after taking actions, reset scatter location and scale'
		controller.center = Window.center
		controller.scale = normal_scale


	# bind a function to controller when release touch
	controller.bind(on_touch_up = control_feedback)

	return controller
Esempio n. 3
0
    def create_map_controller(self):
        """ A scatter object to manipulate motor movement"""
        map_controller = Scatter(
            size_hint = (1,1), do_rotation=False, do_translation=True,
            do_scale=True,auto_bring_to_front = False)
        map_controller.center = Window.center
        # automatically determine the size based on screen size
        default_scale = Window.height / map_controller.height*1
        # determine the size of active area
        map_controller.scale = default_scale
        # determine the amount of zoom and drag needed before moving
        map_controller.scale_max = default_scale*1.2
        map_controller.scale_min = default_scale*0.8
        # dummy object showing active area
        if debug_mode is True:
            map_controller.add_widget(Image())
    
        def map_control_feedback(instance, value):
            """the callback functions for map_controller scatter object"""
            if debug_mode is True: 
                if map_controller.center[0] - Window.center[0] > self.drag_x_sensitive:
                    print('moving x+')
                elif map_controller.center[0] - Window.center[0] < -1* self.drag_x_sensitive:
                    print('moving x-')
                elif map_controller.center[1] - Window.center[1] > self.drag_y_sensitive:
                    print('moving y+')
                elif map_controller.center[1] - Window.center[1] < -1* self.drag_y_sensitive:
                    print('moving y-')
                elif map_controller.scale < default_scale*0.9:
                    print('pinch -')
                elif map_controller.scale > default_scale*1.1:
                    print('pinch +')
            elif debug_mode is False:
                if map_controller.center[0] - Window.center[0] > self.drag_x_sensitive:
                    mc.stage_library('move_x', '-')
                elif map_controller.center[0] - Window.center[0] < -1* self.drag_x_sensitive:
                    mc.stage_library('move_x', '+')
                elif map_controller.center[1] - Window.center[1] > self.drag_y_sensitive:
                    mc.stage_library('move_y', '-')
                elif map_controller.center[1] - Window.center[1] < -1*self.drag_y_sensitive:
                    mc.stage_library('move_y', '+')
                elif map_controller.scale < default_scale*0.9:
                    mc.camera_library('zoom_out')
                elif map_controller.scale > default_scale*1.1:
                    mc.camera_library('zoom_in')
            #after taking actions, reset scatter location and scale to default
            map_controller.center = Window.center
            map_controller.scale = default_scale

        map_controller.bind(on_touch_up = map_control_feedback)
        return map_controller
Esempio n. 4
0
class ViewerScreen(Screen):
    def drawing_toggle(self, *args):
        if self.btns[1] == 'ic_action_view_image.png':
            self.btns[1] = 'ic_action_view_drawing.png'
            self.both.remove_widget(self.overlay)
        elif self.btns[1] == 'ic_action_view_drawing.png':
            self.btns[1] = 'ic_action_view_image.png'
            self.both.add_widget(self.overlay)
        app.update_buttons()

    def set_image(self, img_fn):
        self.image.source = img_fn
        app.paint_screen.image.source = img_fn
        try:
            filesystem.listdir(img_fn + '.overlays')
        except:
            app.paint_screen.painter.color = (0, 0, 0, 0)
            self.btns[1] = None
            self.both.remove_widget(self.overlay)
        else:
            self.btns[1] = 'ic_action_view_image.png'
            self.overlay.source = filesystem.join(
                img_fn + '.overlays',
                filesystem.listdir(img_fn + '.overlays')[-1])
            app.paint_screen.painter.color = (1, 1, 1, 1)
            app.paint_screen.painter.source = self.overlay.source
            try:
                self.both.add_widget(self.overlay)
            except WidgetException:
                pass  # The overlay widget may already be added, in which case I don't care.
        self.both.scale = 1
        self.both.rotation = 0
        self.both.pos = [0, 0]

    def __init__(self, *args, **kwargs):
        super(ViewerScreen, self).__init__(*args, **kwargs)
        self.layout = FloatLayout()
        self.add_widget(self.layout)

        self.image = ImageCanvas(pos_hint={'center_x': 0.5, 'center_y': 0.5})
        self.overlay = AsyncImage(pos_hint={'center_x': 0.5, 'center_y': 0.5})

        self.both = Scatter(size_hint=[1, 1], do_rotation=False)
        self.both.add_widget(self.image)
        self.layout.add_widget(self.both)
        self.both.bind(size=self.fix_size)

    def fix_size(self, *args):
        self.image.size = self.both.size
        self.overlay.size = self.both.size
Esempio n. 5
0
 def show_gems(self, dt=None, dummy=None):
     self.gem_scatters = []
     filler = (8 - len(self.weapons)) / 2.0
     for i in range(len(self.weapons)):
         gem = self.gems[self.weapons[i]]
         scatter = Scatter(do_rotation=False, do_scale=False, color=(0,0,0,0), size_hint=(0.1,0.1))
         scatter.add_widget(gem)
         gem.bind(on_touch_down=self.flash_hero)            
         scatter.bind(on_touch_up=self.drop_gem)
         scatter.pos = ((filler + i) * X_BLOCK, 0)
         scatter.scale = 1
         try:
             self.graphics_widget.add_widget(scatter)
             self.gem_scatters.append(scatter)
         except:
             pass
Esempio n. 6
0
def create_map_controller():
    map_controller = Scatter(
        size_hint = (1,1), do_rotation=False, do_translation=True,
        do_scale=True, scale = 1, center = Window.center)
    # automatically determine the size based on screen size
    default_scale = Window.height / map_controller.height*0.75
    # determine the size of active area
    map_controller.scale = default_scale
    # determine the amount of zoom and drag needed before moving
    map_controller.scale_max = default_scale*1.2
    map_controller.scale_min = default_scale*0.8
    x_sensitive = Window.width*0.3
    y_sensitive = Window.height*0.3
    # dummy object showing active area
    map_controller.add_widget(Image())

    def map_control_feedback(instance, value):
        """the callback functions for map_controller scatter object"""
        if map_controller.center[0] - Window.center[0] > x_sensitive:
            #microscope_control.drag_right()
            print('moving x+')
        elif map_controller.center[0] - Window.center[0] < -1* x_sensitive:
            #microscope_control.drag_left()
            pass
        elif map_controller.center[1] - Window.center[1] > y_sensitive:
            #microscope_control.drag_top()
            print('moving y+')
        elif map_controller.center[1] - Window.center[1] < -1*y_sensitive:
            #microscope_control.drag_bot()
            pass
        elif map_controller.scale < default_scale*0.9:
            #microscope_control.pinch_out()
            print('pinch')
        elif map_controller.scale > default_scale*1.1:
            #microscope_control.pinch_in()
            pass
        #after taking actions, reset scatter location and scale to default
        map_controller.center = Window.center
        map_controller.scale = default_scale
        
    map_controller.bind(on_touch_up = map_control_feedback)

    return map_controller
Esempio n. 7
0
class ViewerScreen(Screen):
    def drawing_toggle(self, *args):
        if self.btns[1] == 'ic_action_view_image.png':
            self.btns[1] = 'ic_action_view_drawing.png'
            self.both.remove_widget(self.overlay)
        elif self.btns[1] == 'ic_action_view_drawing.png':
            self.btns[1] = 'ic_action_view_image.png'
            self.both.add_widget(self.overlay)
        app.update_buttons()
    def set_image(self, img_fn):
        self.image.source = img_fn
        app.paint_screen.image.source = img_fn
        try:
            filesystem.listdir(img_fn+'.overlays')
        except:
            app.paint_screen.painter.color = (0,0,0,0)
            self.btns[1] = None
            self.both.remove_widget(self.overlay)
        else:
            self.btns[1] = 'ic_action_view_image.png'
            self.overlay.source = filesystem.join(img_fn+'.overlays', filesystem.listdir(img_fn+'.overlays')[-1])
            app.paint_screen.painter.color = (1,1,1,1)
            app.paint_screen.painter.source = self.overlay.source
            try: self.both.add_widget(self.overlay)
            except WidgetException: pass # The overlay widget may already be added, in which case I don't care.
        self.both.scale = 1
        self.both.rotation = 0
        self.both.pos = [0,0]
    def __init__(self, *args, **kwargs):
        super(ViewerScreen, self).__init__(*args, **kwargs)
        self.layout = FloatLayout()
        self.add_widget(self.layout)

        self.image = ImageCanvas(pos_hint={'center_x': 0.5, 'center_y': 0.5})
        self.overlay = AsyncImage(pos_hint={'center_x': 0.5, 'center_y': 0.5})

        self.both = Scatter(size_hint=[1,1], do_rotation = False)
        self.both.add_widget(self.image)
        self.layout.add_widget(self.both)
        self.both.bind(size=self.fix_size)
    def fix_size(self, *args):
        self.image.size = self.both.size
        self.overlay.size = self.both.size
Esempio n. 8
0
    def show_popup(self):
        if self.popup is not None:
            self.popup.dismiss()
        desc = FrescoDescription(item=self.item)

        count = 0
        content = self.item.get('content', '')
        if content:
            label = Label(text=content)
            label.bind(size=update_size)
            desc.layout.add_widget(label)
            count += 1
        media = self.item.get('media', '')
        if media:
            ext = media.rsplit('.', 1)[-1].lower()
            media = join(dirname(__file__), 'data', media)
            mediawidget = None
            if ext in ('mp3', 'wav', 'ogg'):
                mediawidget = FrescoAudio(source=media)
            elif ext in ('jpg', 'png', 'jpeg', 'gif', 'bmp', 'tga'):
                mediawidget = Image(source=media)
            else:
                pass
            if mediawidget:
                count += 1
                scatter = Scatter(do_translation=False, do_rotation=False,
                        min_scale=.4, max_scale=2)
                scatter.add_widget(mediawidget)
                scatter.bind(size=mediawidget.setter('size'))
                desc.layout.add_widget(mediawidget)
                desc.media = mediawidget

        desc.layout.cols = max(1, count)
        desc.layout.height = 500

        self.popup = popup = Popup(
            title=self.item['title'],
            content=desc,
            size_hint=(.7, .7))
        self.popup.bind(on_dismiss=self.stop_media)
        popup.open()
Esempio n. 9
0
    def build(self):
        
        b = BoxLayout(orientation='vertical')
        t = TextInput(font_size=150,
                      size_hint_y=None,
                      height=200,
                      text='default')

        f = FloatLayout()
        s = Scatter()
        l = Label(text='default',
                  font_size=150)

        t.bind(text=l.setter('text'))
        s.bind(pos=self.callback_pos)

        f.add_widget(s)
        s.add_widget(l)

        b.add_widget(t)
        b.add_widget(f)
        return b
Esempio n. 10
0
def create_map_controller():
    map_controller = Scatter(
        size_hint = (1,1), do_rotation=False, do_translation=True,
        do_scale=True)
    map_controller.center = Window.center
    # automatically determine the size based on screen size
    default_scale = Window.height / map_controller.height*1
    # determine the size of active area
    map_controller.scale = default_scale
    # determine the amount of zoom and drag needed before moving
    map_controller.scale_max = default_scale*1.1
    map_controller.scale_min = default_scale*0.9
    x_sensitive = Window.width*0.1
    y_sensitive = Window.height*0.2
    # dummy object showing active area
    #map_controller.add_widget(Image())

    def map_control_feedback(instance, value):
        """the callback functions for map_controller scatter object"""
        if map_controller.center[0] - Window.center[0] > x_sensitive:
            mc.stage_library('move_x', '-')
        elif map_controller.center[0] - Window.center[0] < -1* x_sensitive:
            mc.stage_library('move_x', '+')
        elif map_controller.center[1] - Window.center[1] > y_sensitive:
            mc.stage_library('move_y', '-')
        elif map_controller.center[1] - Window.center[1] < -1*y_sensitive:
            mc.stage_library('move_y', '+')
        elif map_controller.scale < default_scale*0.9:
            mc.camera_library('zoom_out')
        elif map_controller.scale > default_scale*1.1:
            mc.camera_library('zoom_in')
        #after taking actions, reset scatter location and scale to default
        map_controller.center = Window.center
        map_controller.scale = default_scale
        
    map_controller.bind(on_touch_up = map_control_feedback)
    return map_controller
Esempio n. 11
0
File: main.py Progetto: IanCal/Baess
class Point():
    def __init__(self, pos):
        self.scatter = Scatter(size_hint=(0.05,0.05), do_rotation=False, do_scale=False)
        self.widget = MyPaintWidget()
        self.widget.setClass('unclassified')
        self.widget.setActive()
        self.scatter.x = pos[0]
        self.scatter.y = pos[1]
        self.scatter.add_widget(self.widget)
        def on_move(ob, touch):
            ob.x = min(max(ob.x, -10), ob.parent.size[0] + 10)
            ob.y = min(max(ob.y, -10), ob.parent.size[1] + 10)
        self.scatter.bind(on_touch_up=on_move)

        

    def setOnPress(self, callback):
        self.scatter.bind(on_touch_down=callback)
        
    def setInactive(self):
        self.widget.setInactive()
    def setActive(self):
        self.widget.setActive()

    def setClassification(self, classification):
        self.classification = classification
        self.widget.setClass(classification)

    def setPos(self, pos):
        self.scatter.x = pos[0]
        self.scatter.y = pos[1]

    def getDisplay(self):
        return self.scatter

    def getPos(self):
        return (self.scatter.x, self.scatter.y)
Esempio n. 12
0
    def show_popup(self):
        if self.popup is not None:
            self.popup.dismiss()
        desc = FrescoDescription(item=self.item)

        count = 0
        content = self.item.get("content", "")
        if content:
            label = Label(text=content)
            label.bind(size=update_size)
            desc.layout.add_widget(label)
            count += 1
        media = self.item.get("media", "")
        if media:
            ext = media.rsplit(".", 1)[-1].lower()
            media = join(dirname(__file__), "data", media)
            mediawidget = None
            if ext in ("mp3", "wav", "ogg"):
                mediawidget = FrescoAudio(source=media)
            elif ext in ("jpg", "png", "jpeg", "gif", "bmp", "tga"):
                mediawidget = Image(source=media)
            else:
                pass
            if mediawidget:
                count += 1
                scatter = Scatter(do_translation=False, do_rotation=False, min_scale=0.4, max_scale=2)
                scatter.add_widget(mediawidget)
                scatter.bind(size=mediawidget.setter("size"))
                desc.layout.add_widget(mediawidget)
                desc.media = mediawidget

        desc.layout.cols = max(1, count)
        desc.layout.height = 500

        self.popup = popup = Popup(title=self.item["title"], content=desc, size_hint=(0.7, 0.7))
        self.popup.bind(on_dismiss=self.stop_media)
        popup.open()
Esempio n. 13
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
            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)
Esempio n. 14
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
            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)
Esempio n. 15
0
class DeckWidget(Widget):
    def recalc_pos(self, *args):
        """
            Used whenever the Window size changes. The window size sometimes changes rapidly 
            from full screen when the program is first launched, so this is also ran .5 seconds after __init__.
            
        """
        # Window -> self.parent
        self.parent.size = Window.size
        self.card_size = (self.parent.size[0] - 40, float(self.parent.size[1] - 40))
        self.card_pos = (
            (self.parent.size[0] - self.card_size[0]) / 4,
            (self.parent.size[1] - self.card_size[1]) / 4,
        )  # Centered in self.parent
        self.card_center = self.parent.center
        self.text_position = self.card_center
        self.text_content = str(self.deck.selected) if len(self.deck) > 0 else "(Deck is empty)"
        self.widgets["card_text"].center = self.card_center
        self.widgets["card_text"].text_size = (20, 20)
        self.widgets["card_text"].size = (20, 20)
        self.widgets["card_text_ref"].center = self.card_center
        self.widgets["card_text_ref"].text_size = (20, 20)
        self.widgets["card_text_ref"].size = (20, 20)
        self.touch_move_counter = 0
        self.card_base.size = self.card_size
        self.zoom_out_size = (self.card_size[0] * 0.9, self.card_size[1] * 0.9)
        self.cardflip_animations = {
            "zoom_in": Animation(size=self.card_size, duration=0.5),
            "zoom_out": Animation(size=self.zoom_out_size, duration=0.3),
            "text_zoom_in": Animation(font_size=sp(15), duration=0.5),
            "text_zoom_out": Animation(font_size=sp(12), duration=0.3),
            "zoom_in_out": (
                Animation(size=self.zoom_out_size, duration=0.3) + Animation(size=self.card_size, duration=0.5)
            ),
            "flip_start": Animation(size=(0, self.zoom_out_size[1]), duration=0.2),
            "flip_end": Animation(size=self.zoom_out_size, duration=0.2),
            "is_playing": False,
            "down_success": False,
        }

        self.card_snapback_animation = Animation(center=self.card_center, duration=0.1)

        self.offscreen_animations = {
            "rightward_leave": Animation(center_x=self.card_center[0] * 3, duration=0.2),
            "leftward_leave": Animation(center_x=-self.card_center[0], duration=0.2),
            "from_side_to_center": Animation(center=self.card_center, duration=0.15),
            "fade_out": Animation(opacity=0.5, duration=0.2),
            "fade_in": Animation(opacity=1, duration=0.2),
            "shrink": Animation(size=(self.card_size[0] * 0.5, self.card_size[1] * 0.5), duration=0.2),
            "grow": Animation(size=self.card_size, duration=0.45),
            "is_playing": False,
        }

        self.redraw_card_base()

    def __init__(self, f=None):
        # COMMENTED OUT aND MANUALLY ADDED FOR ANDROID TESTING PURPOSES

        if type(f) == type("a"):
            self.deck = Deck([])
            if self.deck.add_from_txt(f) == False:
                print("LOOOOL: ", f)
                # self.deck += Card("Q#Failed to Open File", "A#Try Again...")
        else:
            self.deck = Deck([])

        # print(self.deck)
        Widget.__init__(self)
        self.card_size = (float(Window.size[0] - 40), float(Window.size[1] - 40))
        self.card_center = Window.center
        self.text_position = self.card_center
        self.text_content = str(self.deck.selected) if not self.deck.is_empty else "(Deck is empty)"

        # Creation of Scatter-Rectangle

        self.card_base = Scatter(
            size=self.card_size,
            center=self.card_center,
            do_rotation=False,
            do_translation_y=False,
            scale_min=0.9,
            scale_max=1,
        )
        self.shape = {"card_base_rect": Rectangle(size=self.card_base.size, center=self.card_base.center)}
        self.card_base.canvas.before.add(Color(255, 255, 255))
        self.card_base.canvas.before.add(self.shape["card_base_rect"])

        # Creation of Label Widget
        self.widgets = {
            "card_text": Label(
                center=self.card_center,
                halign="center",
                valign="middle",
                text_size=self.card_size,
                font_size=sp(15),
                text=self.text_content,
                color=[0, 0, 0, 1],
            ),
            "card_text_ref": Label(
                center=self.card_center,
                halign="center",
                valign="middle",
                text_size=self.card_size,
                font_size=sp(15),
                text=self.text_content,
                color=[0, 0, 0, 1],
            ),
        }
        # Bindings
        def update_text(*args):
            self.widgets["card_text"].center = self.card_base.center

        self.card_base.bind(width=self.redraw_card_base, center_x=update_text)
        Window.bind(on_resize=self.recalc_pos, on_rotate=self.recalc_pos)

        self.add_widget(self.card_base)
        self.add_widget(self.widgets["card_text"], len(self.children))

        Clock.schedule_once(self.recalc_pos, 0.5)

    def change_card_text(self, new_text):
        self.text_content = new_text
        self.widgets["card_text"].text = self.text_content

    def update_selected_text(self):
        self.change_card_text(str(self.deck.get_selected()))

    def redraw_card_base(self, *args):
        """
            Redraws the card. I had issues with canvas ordering and the text would never be drawn on top of the rectangle
            as the rectangle seemed to be always put on top during an animation. So the label widget is removed and redrawn
            after the rectangle is removed and redrawn.
            
            This is called every time an animation occurs that modifies the rectangle size.
        """
        self.card_base.center = self.card_center
        self.remove_widget(self.widgets["card_text"])

        self.card_base.canvas.before.remove(self.shape["card_base_rect"])
        self.shape["card_base_rect"] = Rectangle(size=self.card_base.size, center=self.card_base.center)
        self.card_base.canvas.before.add(self.shape["card_base_rect"])

        self.widgets["card_text"] = Label(
            center=self.card_center,
            size=(20, 20),
            font_size=self.widgets["card_text_ref"].font_size,
            text=self.text_content,
            color=[0, 0, 0, 1],
        )
        self.add_widget(self.widgets["card_text"])
        self.widgets["card_text"].center = self.card_center

    def flip_animation(self):
        """
            Plays a series of animations that will cause the rectangle to appear to flip. Local functions
            are defined for the purpose of being bound when certain animations are complete. This way
            I would be able to do things in the background after certain animations are complete
            (i.e. when card is at the apex of the flip animation and is hardly visible, I want to
            change the stuff on the card in the at_flip_end() function.)
        """
        # self.cardflip_animations['zoom_in_out'].start(self.card_base)
        card_zoom_a = self.cardflip_animations["zoom_out"]
        card_zoom_b = self.cardflip_animations["zoom_in"]
        text_zoom = self.cardflip_animations["text_zoom_out"] + self.cardflip_animations["text_zoom_in"]
        text_zoom.start(self.widgets["card_text_ref"])

        f_e = p = self.cardflip_animations["flip_end"]
        f_s = self.cardflip_animations["flip_start"]

        def toggle_is_playing(*args):
            self.cardflip_animations["is_playing"] = not self.cardflip_animations["is_playing"]
            card_zoom_a.stop(self.card_base)
            card_zoom_b.stop(self.card_base)
            text_zoom.stop(self.card_base)
            f_e.stop(self.card_base)
            f_s.stop(self.card_base)
            card_zoom_b.unbind(on_complete=toggle_is_playing)
            card_zoom_a.unbind(on_complete=at_zoom_end)

        def final_zoom(*args):
            f_e.unbind(on_complete=final_zoom)
            card_zoom_b.start(self.card_base)

        def at_flip_end(*args):
            self.deck.get_selected().flip()
            self.update_selected_text()
            f_s.unbind(on_complete=at_flip_end)
            f_e.bind(on_complete=final_zoom)
            f_e.start(self.card_base)

        def at_zoom_end(*args):
            f_s.bind(on_complete=at_flip_end)
            f_s.start(self.card_base)

        card_zoom_b.bind(on_complete=toggle_is_playing)
        card_zoom_a.bind(on_complete=at_zoom_end)
        card_zoom_a.start(self.card_base)

        # (self.cardflip_animations['zoom_out']+self.cardflip_animations['zoom_in']).start(self.card_base)

    def offscreen_animation(self, right_mode):
        """
            Similar to flip animation. When at the end of the first offscreen transition, I'd want to
            change the stuff on the card which could be done through the local  begin_entrance() functions
        """
        ret_to_center = self.offscreen_animations["grow"] & self.offscreen_animations["from_side_to_center"]
        z = self.offscreen_animations["shrink"] & self.offscreen_animations["rightward_leave"]
        y = self.offscreen_animations["shrink"] & self.offscreen_animations["leftward_leave"]

        def toggle_is_playing(*args):
            self.offscreen_animations["is_playing"] = False

        if right_mode:

            def begin_entrance_z(*args):
                self.deck.get_selected().reset()
                self.deck.prev(self.deck.mode)
                self.update_selected_text()
                self.card_base.center_x = -self.card_center[0] * 0.4
                ret_to_center.bind(on_complete=toggle_is_playing)
                ret_to_center.start(self.card_base)

            z.bind(on_complete=begin_entrance_z)
            z.start(self.card_base)
        else:  # left mode

            def begin_entrance_y(*args):
                self.deck.get_selected().reset()
                self.deck.next(self.deck.mode)
                self.update_selected_text()
                self.card_base.center_x = self.card_center[0] * 2.5
                ret_to_center.bind(on_complete=toggle_is_playing)
                ret_to_center.start(self.card_base)

            y.bind(on_complete=begin_entrance_y)
            y.start(self.card_base)

    def on_touch_up(self, touch):
        """
        Goals:
            -If the card is touch-released very close (<5px) to the original position, it should play a flip animation.
            -When the card is released a bit further, it should transition back to the original position.
            -If the card is released at a point where half of it's face is offscreen, the card should
                transition off screen and another card should transition on screen.
        All of this should not be able to happen again if any animation is already playing.
        """
        if not self.deck.is_empty():
            if (
                self.card_base.center[0] < self.card_center[0] + 5
                and self.card_base.center[0] > self.card_center[0] - 5
            ):
                # Do flip animation
                if not self.cardflip_animations["is_playing"] and self.cardflip_animations["down_success"]:
                    self.cardflip_animations["is_playing"] = True
                    self.flip_animation()
            elif self.card_base.center[0] > (self.card_center[0] * 1.65):
                # Do offscreen/onscreen transition rightwards
                if not self.offscreen_animations["is_playing"]:
                    self.offscreen_animations["is_playing"] = True
                    self.offscreen_animation(True)
            elif self.card_base.center[0] < (self.card_center[0] * 0.35):
                # Do offscreen/onscreen transition leftwards
                if self.deck.mode != None:
                    self.card_snapback_animation.start(self.card_base)
                elif not self.offscreen_animations["is_playing"]:
                    self.offscreen_animations["is_playing"] = True
                    self.offscreen_animation(False)
            else:
                # Do transition-to-origin animation
                self.card_snapback_animation.start(self.card_base)

            # Swipe Emulation - See DeckWidget.on_touch_move()
            if self.touch_move_counter < 7 and self.touch_move_counter > 1:
                x_difference = self.touch_move_current[0] - self.touch_move_init[0]
                y_difference = self.touch_move_current[1] - self.touch_move_init[1]
                if x_difference > 5 and x_difference > y_difference:
                    if not self.offscreen_animations["is_playing"] and not self.cardflip_animations["is_playing"]:
                        self.offscreen_animations["is_playing"] = True
                        self.offscreen_animation(True)
                elif x_difference < -5 and x_difference < y_difference:
                    if not self.offscreen_animations["is_playing"] and not self.cardflip_animations["is_playing"]:
                        self.offscreen_animations["is_playing"] = True
                        self.offscreen_animation(False)
            self.touch_move_counter = 0

    def on_touch_move(self, touch):
        """
            At the last minute, I noticed how my launcher on my android phone behaves when you swap
            the screens. Even if your finger doesn't cover a significant distance. If you swipe quickly
            with a clear direction yet very short distance, the screen will change.
            
            It's only when you move your finger slowly with a short distances will the screen bounce back to 
            the original position. I wanted to try emulating this to an extent; swiping fast should play
            the offscreen animations while swiping slow would cause the snapback animation effect.
            
            Also, the swipe must be bigger in the x-direction than it is in the y-direction.
        """
        if not self.deck.is_empty():
            if self.touch_move_counter == 0:
                self.touch_move_init = touch.pos
            else:
                self.touch_move_current = touch.pos
            self.touch_move_counter += 1

    def on_touch_down(self, touch):
        """
            Dictates what happens when the DeckWidget is clicked/touched but not released yet. 
            Scatter.on_touch_down() handles sliding (card_base is a Scatter). Also, I only want
            this to work if no animations are playing. 
        """
        if not self.deck.is_empty():
            if self.offscreen_animations["is_playing"] == False and self.cardflip_animations["is_playing"] == False:
                self.card_base.on_touch_down(touch)
                self.cardflip_animations["down_success"] = True
            else:
                self.cardflip_animations["down_success"] = False

            if not self.cardflip_animations["is_playing"]:
                self.remove_widget(self.widgets["card_text"])
                self.widgets["card_text"] = Label(
                    center=self.card_base.center,
                    size=(20, 20),
                    font_size=sp(15),
                    text=self.text_content,
                    color=[0, 0, 0, 1],
                )
                self.add_widget(self.widgets["card_text"])
                self.widgets["card_text"].center = self.card_base.center
Esempio n. 16
0
class KivySprite:
    def __init__(self, parent_widget):
        self._parent_widget = parent_widget
        self._scatter_widget = Scatter(#self._tapped,  # callbacks on all areas
                                               do_rotation=False,
                                               do_scale=False,
                                               do_translation=True)
        self._image_widget = Image(source='a.png')
        self._scatter_widget.add_widget(self._image_widget)
        self._parent_widget.add_widget(self._scatter_widget)

        with self._scatter_widget.canvas.before:
            Color(1,0,0)
            Rectangle(pos=self._scatter_widget.pos, size=self._scatter_widget.size)

        self.layer = None
        self.visible = True
        self.rotation_style = 'all around'

        self._scatter_widget.bind(pos=lambda w, p: self._moved())
        self._image_widget.bind(on_touch_down=lambda w, t: self._tapped())

    # to be overriden by Sprite
    def _tapped(self): pass
    def _moved(self): pass
    def _rotated(self): pass
    def _sized(self): pass

    @property
    def image(self):
        return self._image_widget.source

    @image.setter
    def image(self, value):
        self._image_widget.source = value

    @property
    def position(self):
        return self._scatter_widget.pos

    @position.setter
    def position(self, value):
        self._scatter_widget.pos = value

    @property
    def x(self):
        return self.position[0]

    @x.setter
    def x(self, value):
        self._scatter_widget.pos = value - (self._image_widget.size[0]/2), self.y

    @property
    def y(self):
        return self.position[1]

    @y.setter
    def y(self, value):
        self._scatter_widget.pos = self.x, value - (self._image_widget.size[1]/2)

    @property
    def size(self):
        return self._scatter_widget.scale * 100

    @size.setter
    def size(self, value):
        self._scatter_widget.scale = value * 0.01

    @property
    def direction(self):
        return (((self._scatter_widget.rotation + 90) + 179) % 360) - 179

    @direction.setter
    def direction(self, value):
        self._scatter_widget.rotation = value - 90

    @property
    def draggable(self):
        return self._scatter_widget.do_translation

    @draggable.setter
    def draggable(self, value):
        self._scatter_widget.do_translation = value

    def glide(self, x, y, time=None):  # either x, y, time or sprite, time
        if time is None:
            time = y
            y = x.y
            x = x.x
        anim = Animation(x=x, y=y, duration=time)
        anim.start(self._scatter_widget)

    def move(self, steps):
        self.x += steps * math.sin(math.radians(self.direction))
        self.y += steps * math.cos(math.radians(self.direction))
        self._moved()

    def point_towards(self, x, y=None):  # test
        if y is None:  # x is a sprite
            y = x.y
            x = x.x
        dy = y - self.y
        dx = x - self.x
        angle = (-90 if dx < 0 else 90) if dy == 0 else math.degrees(math.atan(dx / dy))
        if dy < 0:
            angle += 180
        self.direction = angle

    def touching(self, other_sprite):
        return self._image_widget.collide_widget(other_sprite._image_widget)