async def job(w, t):
     if actually_ended:
         with pytest.raises(MotionEventAlreadyEndedError):
             async for __ in ak.rest_of_touch_moves(w, t):
                 pass
     else:
         async for __ in ak.rest_of_touch_moves(w, t):
             pass
Esempio n. 2
0
 async def draw_rect(self, touch):
     from kivy.graphics import Line, Color, Rectangle, InstructionGroup
     from kivy.utils import get_random_color
     inst_group = InstructionGroup()
     self.canvas.add(inst_group)
     inst_group.add(Color(*get_random_color()))
     line = Line(width=2)
     inst_group.add(line)
     ox, oy = self.to_local(*touch.opos)
     on_touch_move_was_fired = False
     async for __ in ak.rest_of_touch_moves(self, touch):
         # Don't await anything during this async-for-loop
         on_touch_move_was_fired = True
         x, y = self.to_local(*touch.pos)
         min_x = min(x, ox)
         min_y = min(y, oy)
         max_x = max(x, ox)
         max_y = max(y, oy)
         line.rectangle = [min_x, min_y, max_x - min_x, max_y - min_y]
     if on_touch_move_was_fired:
         inst_group.add(Color(*get_random_color(alpha=.3)))
         inst_group.add(
             Rectangle(
                 pos=(min_x, min_y),
                 size=(
                     max_x - min_x,
                     max_y - min_y,
                 ),
             ))
     else:
         self.canvas.remove(inst_group)
 async def _test(w, t):
     n = 0
     async for __ in ak.rest_of_touch_moves(w, t):
         n += 1
     assert n == n_touch_moves
     nonlocal done
     done = True
Esempio n. 4
0
    async def _watch_touch(self, touch):
        spacer = self._inactive_spacers.pop()
        self._active_spacers.append(spacer)

        # assigning to a local variable might improve performance
        collide_point = self.collide_point
        get_drop_insertion_index_move = self.get_drop_insertion_index_move
        remove_widget = self.remove_widget
        add_widget = self.add_widget
        touch_ud = touch.ud

        try:
            restore_widget_location(
                spacer,
                touch_ud['kivyx_draggable'].drag_context.original_location,
                ignore_parent=True)
            add_widget(spacer)
            async for __ in ak.rest_of_touch_moves(self, touch):
                x, y = touch.pos
                if collide_point(x, y):
                    new_idx = get_drop_insertion_index_move(x, y, spacer)
                    if new_idx is not None:
                        remove_widget(spacer)
                        add_widget(spacer, index=new_idx)
                else:
                    del touch_ud[self.__ud_key]
                    return
            if 'kivyx_droppable' not in touch_ud:
                touch_ud['kivyx_droppable'] = self
                touch_ud['kivyx_droppable_index'] = self.children.index(spacer)
        finally:
            self.remove_widget(spacer)
            self._inactive_spacers.append(spacer)
            self._active_spacers.remove(spacer)
Esempio n. 5
0
 async def draw_rect(self, touch):
     from kivy.graphics import Line, Color, Rectangle, InstructionGroup
     from kivy.utils import get_random_color
     inst_group = InstructionGroup()
     self.canvas.add(inst_group)
     inst_group.add(Color(*get_random_color()))
     line = Line(width=2)
     inst_group.add(line)
     ox, oy = x, y = self.to_local(*touch.opos)
     async for __ in ak.rest_of_touch_moves(self,
                                            touch,
                                            stop_dispatching=True):
         # Don't await anything during the iteration
         x, y = self.to_local(*touch.pos)
         min_x, max_x = (x, ox) if x < ox else (ox, x)
         min_y, max_y = (y, oy) if y < oy else (oy, y)
         line.rectangle = (
             min_x,
             min_y,
             max_x - min_x,
             max_y - min_y,
         )
     if x == ox and y == oy:
         self.canvas.remove(inst_group)
     else:
         inst_group.add(Color(*get_random_color(alpha=.3)))
         inst_group.add(
             Rectangle(
                 pos=(min_x, min_y),
                 size=(
                     max_x - min_x,
                     max_y - min_y,
                 ),
             ))
Esempio n. 6
0
 async def _true_when_a_touch_ended_false_when_it_moved_too_much(
         self, touch):
     drag_distance = self.drag_distance
     ox, oy = touch.opos
     async for __ in ak.rest_of_touch_moves(self, touch):
         dx = abs(touch.x - ox)
         dy = abs(touch.y - oy)
         if dy > drag_distance or dx > drag_distance:
             return False
     return True
Esempio n. 7
0
    async def _watch_touch_movement(self, touch):
        draggable = touch.ud['kivyx_draggable']
        collide_point = self.collide_point

        self.dispatch('on_drag_enter', touch, draggable)
        try:
            async for __ in ak.rest_of_touch_moves(self, touch):
                if not collide_point(*touch.pos):
                    return
        finally:
            self.dispatch('on_drag_leave', touch, draggable)
            del touch.ud[self.__ud_key]
 async def _test(w, t):
     import weakref
     nonlocal n_touch_moves
     weak_w = weakref.ref(w)
     assert weak_w not in t.grab_list
     async for __ in ak.rest_of_touch_moves(w, t):
         assert weak_w in t.grab_list
         n_touch_moves += 1
         if n_touch_moves == 2:
             break
     assert weak_w not in t.grab_list
     await ak.event(w, 'on_touch_up')
 async def _test(w, t):
     import weakref
     nonlocal n_touch_moves
     weak_w = weakref.ref(w)
     assert weak_w not in t.grab_list
     if holds_a_ref:
         agen = ak.rest_of_touch_moves(w, t)
         async for __ in agen:
             assert weak_w in t.grab_list
             n_touch_moves += 1
             if n_touch_moves == 2:
                 break
     else:
         async for __ in ak.rest_of_touch_moves(w, t):
             assert weak_w in t.grab_list
             n_touch_moves += 1
             if n_touch_moves == 2:
                 break
     assert weak_w not in t.grab_list  # fails if holds_a_ref is True
     await ak.event(w, 'on_touch_up')
     nonlocal done
     done = True
Esempio n. 10
0
    async def _true_when_a_touch_ended_false_when_it_moved_too_much(
            self, touch):
        # assigning to a local variable might improve performance
        abs_ = abs
        drag_distance = self.drag_distance

        ox, oy = touch.opos
        async for __ in ak.rest_of_touch_moves(self, touch):
            dx = abs_(touch.x - ox)
            dy = abs_(touch.y - oy)
            if dy > drag_distance or dx > drag_distance:
                return False
        return True
Esempio n. 11
0
    async def _watch_touch_events(self):
        from asynckivy import animate, rest_of_touch_moves, event, MotionEventAlreadyEndedError, cancel_protection

        def accepts_touch(w, t) -> bool:
            return w.collide_point(*t.opos) and (not t.is_mouse_scrolling)

        # 'itertools.cycle()' is no use here because it cannot react to
        # the property changes. There might be a better way than this, though.
        def color_iter(w):
            while True:
                yield w.border_color2
                yield w.border_color1
        color_iter = color_iter(self)

        def change_border_color(dt):
            self._border_color = next(color_iter)

        blink_ev = Clock.create_trigger(change_border_color, .1, interval=True)
        collide_point = self.collide_point
        dispatch = self.dispatch

        try:
            while True:
                __, touch = await event(self, 'on_touch_down', filter=accepts_touch, stop_dispatching=True)
                dispatch('on_press')
                blink_ev()
                try:
                    async for __ in rest_of_touch_moves(self, touch, stop_dispatching=True):
                        if collide_point(*touch.pos):
                            blink_ev()
                        else:
                            blink_ev.cancel()
                            self._border_color = self.border_color1
                except MotionEventAlreadyEndedError:
                    blink_ev.cancel()
                    self._border_color = self.border_color1
                    continue
                if collide_point(*touch.pos):
                    async with cancel_protection():
                        await animate(self, _scaling=.9, d=.05)
                        await animate(self, _scaling=1, d=.05)
                    dispatch('on_release')
                blink_ev.cancel()
                self._border_color = self.border_color1
        finally:
            blink_ev.cancel()
            self._border_color = self.border_color1
Esempio n. 12
0
    async def _async_main(self):
        from asynckivy import rest_of_touch_moves, event
        from kivy.graphics import Line, Color, Rectangle, InstructionGroup
        from kivy.utils import get_random_color

        def will_accept_touch(w, t) -> bool:
            return w.collide_point(*t.opos) and (not t.is_mouse_scrolling)

        while True:
            __, touch = await event(self,
                                    'on_touch_down',
                                    filter=will_accept_touch,
                                    stop_dispatching=True)
            inst_group = InstructionGroup()
            self.canvas.add(inst_group)
            inst_group.add(Color(*get_random_color()))
            line = Line(width=2)
            inst_group.add(line)
            ox, oy = x, y = self.to_local(*touch.opos)
            async for __ in rest_of_touch_moves(self,
                                                touch,
                                                stop_dispatching=True):
                # Don't await anything during the iteration
                x, y = self.to_local(*touch.pos)
                min_x, max_x = (x, ox) if x < ox else (ox, x)
                min_y, max_y = (y, oy) if y < oy else (oy, y)
                line.rectangle = (
                    min_x,
                    min_y,
                    max_x - min_x,
                    max_y - min_y,
                )
            if x == ox and y == oy:
                self.canvas.remove(inst_group)
            else:
                inst_group.add(Color(*get_random_color(alpha=.3)))
                inst_group.add(
                    Rectangle(
                        pos=(min_x, min_y),
                        size=(
                            max_x - min_x,
                            max_y - min_y,
                        ),
                    ))
Esempio n. 13
0
 async def _handle_touch(self, touch):
     from asynckivy import animate, Event, rest_of_touch_moves, start
     self._ctx = True
     self.dispatch('on_press')
     try:
         flag_proceed_blinking = Event()
         flag_proceed_blinking.set()
         coro_blink = start(self._blink(flag_proceed_blinking))
         async for __ in rest_of_touch_moves(self, touch):
             if self.collide_point(*touch.pos):
                 flag_proceed_blinking.set()
             else:
                 flag_proceed_blinking.clear()
         if self.collide_point(*touch.pos):
             await animate(self, _scaling=.9, d=.05)
             await animate(self, _scaling=1, d=.05)
             self.dispatch('on_release')
     finally:
         coro_blink.close()
         self._ctx = None
Esempio n. 14
0
 async def main(cls, *, widgets, ctx):
     from kivy.graphics import Line, Color, InstructionGroup
     import asynckivy as ak
     abs_ = abs
     target = widgets['target']
     to_local = target.to_local
     is_inside = _is_inside
     while True:
         __, touch = await ak.event(target, 'on_touch_down', filter=is_inside, stop_dispatching=True)
         target.canvas.add(ig := InstructionGroup())
         ig.add(Color(*ctx.line_color))
         ig.add(line := Line(width=ctx.line_width, points=[*to_local(*touch.opos)]))
         precision = ctx.freehand_precision
         last_x, last_y = touch.opos
         async for __ in ak.rest_of_touch_moves(target, touch):
             if abs_(last_x - touch.x) + abs_(last_y - touch.y) > precision:
                 p = line.points
                 p.extend(to_local(*touch.pos))
                 line.points = p
                 last_x, last_y = touch.pos
Esempio n. 15
0
 async def main(cls, *, widgets, ctx):
     from kivy.graphics import Line, Color, InstructionGroup
     import asynckivy as ak
     target = widgets['target']
     to_local = target.to_local
     shape_name = cls._shape_name
     is_inside = _is_inside
     while True:
         __, touch = await ak.event(target, 'on_touch_down', filter=is_inside, stop_dispatching=True)
         ox, oy = x, y = to_local(*touch.opos)
         target.canvas.add(ig := InstructionGroup())
         ig.add(Color(*ctx.line_color))
         ig.add(line := Line(width=ctx.line_width))
         async for __ in ak.rest_of_touch_moves(target, touch):
             x, y = to_local(*touch.pos)
             min_x, max_x = (x, ox) if x < ox else (ox, x)
             min_y, max_y = (y, oy) if y < oy else (oy, y)
             setattr(line, shape_name, (min_x, min_y, max_x - min_x, max_y - min_y, ))
         if x == ox and y == oy:
             target.canvas.remove(ig)
Esempio n. 16
0
 async def main(cls, *, widgets, ctx):
     from kivy.graphics import Color, InstructionGroup
     import kivy.graphics
     import asynckivy as ak
     target = widgets['target']
     shape_cls = getattr(kivy.graphics, cls._shape_name)
     to_local = target.to_local
     is_inside = _is_inside
     while True:
         __, touch = await ak.event(target, 'on_touch_down', filter=is_inside, stop_dispatching=True)
         ox, oy = x, y = to_local(*touch.opos)
         target.canvas.add(ig := InstructionGroup())
         ig.add(Color(*ctx.fill_color))
         ig.add(shape := shape_cls(size=(0, 0)))
         async for __ in ak.rest_of_touch_moves(target, touch):
             x, y = to_local(*touch.pos)
             min_x, max_x = (x, ox) if x < ox else (ox, x)
             min_y, max_y = (y, oy) if y < oy else (oy, y)
             shape.pos = min_x, min_y
             shape.size = max_x - min_x, max_y - min_y
         if x == ox and y == oy:
             target.canvas.remove(ig)
 async def _test(parent, t):
     async for __ in ak.rest_of_touch_moves(
             parent, t, stop_dispatching=stop_dispatching):
         pass
 async def _test(w, t):
     n = 0
     async for __ in ak.rest_of_touch_moves(w, t):
         n += 1
     assert n == n_touch_moves
 async def _test(parent, t):
     async for __ in ak.rest_of_touch_moves(parent, t, eat_touch=eat_touch):
         pass
     nonlocal done
     done = True
Esempio n. 20
0
    async def _treat_a_touch_as_a_drag(self, touch, *, do_transform=False):
        self.is_being_dragged = True
        try:
            # NOTE: I don't know the difference from 'get_root_window()'
            window = self.get_parent_window()
            touch_ud = touch.ud
            original_pos_win = self.to_window(*self.pos)
            original_location = save_widget_location(self)
            self._drag_ctx = ctx = DragContext(
                original_pos_win=original_pos_win,
                original_location=original_location,
            )

            if do_transform:
                touch.push()
                touch.apply_transform_2d(self.parent.to_widget)
            offset_x = touch.ox - self.x
            offset_y = touch.oy - self.y
            if do_transform:
                touch.pop()

            # move self under the Window
            self.parent.remove_widget(self)
            self.size_hint = (
                None,
                None,
            )
            self.pos_hint = {}
            self.pos = (
                original_pos_win[0] + touch.x - touch.ox,
                original_pos_win[1] + touch.y - touch.oy,
            )
            window.add_widget(self)

            # mark the touch so that the other widgets can react to the drag
            touch_ud['kivyx_drag_cls'] = self.drag_cls
            touch_ud['kivyx_draggable'] = self

            self.dispatch('on_drag_start', touch)
            async for __ in ak.rest_of_touch_moves(self, touch):
                self.x = touch.x - offset_x
                self.y = touch.y - offset_y

            # we need to give the other widgets the time to react to
            # 'on_touch_up'
            await ak.sleep(-1)

            ctx.droppable = droppable = touch_ud.get('kivyx_droppable', None)
            failed = droppable is None or \
                not droppable.accepts_drag(touch, self)
            r = self.dispatch('on_drag_fail' if failed else 'on_drag_success',
                              touch)
            if isawaitable(r):
                await r
            # I cannot remember why this 'ak.sleep()' exists.
            # It might be unnecessary.
            await ak.sleep(-1)
        except GeneratorExit:
            ctx.cancelled = True
            raise
        finally:
            self.dispatch('on_drag_end', touch)
            self.is_being_dragged = False
            self._drag_ctx = None
            touch_ud['kivyx_droppable'] = None
            del touch_ud['kivyx_drag_cls']
            del touch_ud['kivyx_draggable']
Esempio n. 21
0
    async def _treat_a_touch_as_a_drag(self,
                                       touch,
                                       *,
                                       do_transform=False,
                                       drag_from=None):
        if drag_from is None:
            drag_from = self
        self.is_being_dragged = True
        try:
            # NOTE: I don't know the difference from 'get_root_window()'
            window = drag_from.get_parent_window()
            touch_ud = touch.ud
            original_pos_win = drag_from.to_window(*drag_from.pos)
            original_location = save_widget_location(
                drag_from, ignore_parent=(drag_from is not self))
            original_location.setdefault('weak_parent', None)
            self._drag_ctx = ctx = DragContext(
                original_pos_win=original_pos_win,
                original_location=original_location,
            )

            if do_transform:
                touch.push()
                touch.apply_transform_2d(drag_from.parent.to_widget)
            offset_x = touch.ox - drag_from.x
            offset_y = touch.oy - drag_from.y
            if do_transform:
                touch.pop()

            # move self under the Window
            if self.parent is None:  # more like (drag_from is not self)
                restore_widget_location(self,
                                        original_location,
                                        ignore_parent=True)
            else:
                self.parent.remove_widget(self)
            self.size_hint = (
                None,
                None,
            )
            self.pos_hint = {}
            self.pos = (
                original_pos_win[0] + touch.x - touch.ox,
                original_pos_win[1] + touch.y - touch.oy,
            )
            window.add_widget(self)

            # mark the touch so that other widgets can react to the drag
            touch_ud['kivyx_drag_cls'] = self.drag_cls
            touch_ud['kivyx_draggable'] = self

            self.dispatch('on_drag_start', touch)
            async for __ in ak.rest_of_touch_moves(self, touch):
                self.x = touch.x - offset_x
                self.y = touch.y - offset_y

            # wait for other widgets to react to 'on_touch_up'
            await ak.sleep(-1)

            ctx.droppable = droppable = touch_ud.get('kivyx_droppable', None)
            if droppable is None or (not droppable.accepts_drag(touch, self)):
                ctx.state = 'failed'
                r = self.dispatch('on_drag_fail', touch)
            else:
                ctx.state = 'succeeded'
                r = self.dispatch('on_drag_success', touch)
            async with ak.cancel_protection():
                if isawaitable(r):
                    await r
                # I cannot remember why this 'ak.sleep()' exists.
                # It might be unnecessary.
                await ak.sleep(-1)
        except GeneratorExit:
            ctx.state = 'cancelled'
            self.dispatch('on_drag_cancel', touch)
            raise
        finally:
            self.dispatch('on_drag_end', touch)
            self.is_being_dragged = False
            self._drag_ctx = None
            touch_ud['kivyx_droppable'] = None
            del touch_ud['kivyx_drag_cls']
            del touch_ud['kivyx_draggable']