Last active
September 28, 2019 09:03
-
-
Save gottadiveintopython/16311ab6e3cf72406ce8bc029243ddcb to your computer and use it in GitHub Desktop.
(Kivy) magnet + drag_n_drop = awesome
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| https://youtu.be/fP0Pxy_3cSI | |
| ''' | |
| from kivy.app import runTouchApp | |
| from kivy.lang import Builder | |
| from kivy.uix.label import Label | |
| import rich_drag_n_drop | |
| KV_CODE = ''' | |
| BoxLayout: | |
| RichDraggableGridLayout: | |
| id: left | |
| drag_classes: ['test', ] | |
| cols: 4 | |
| Widget: | |
| size_hint_x: None | |
| width: 1 | |
| canvas: | |
| Color: | |
| rgb: .5, 0, 1 | |
| Rectangle: | |
| pos: self.pos | |
| size: self.size | |
| RichDraggableBoxLayout: | |
| id: right | |
| size_hint_x: .3 | |
| orientation: 'vertical' | |
| drag_classes: ['test', ] | |
| ''' | |
| root = Builder.load_string(KV_CODE) | |
| left = root.ids.left | |
| for i in range (10): | |
| left.add_widget( | |
| Label(text=str(i), font_size='80'), | |
| drag_cls='test') | |
| right = root.ids.right | |
| for text in 'ABCDE': | |
| right.add_widget( | |
| Label(text=text, font_size='80'), | |
| drag_cls='test') | |
| runTouchApp(root) | |
| print('left:', [c.text for c in left.children_without_case]) | |
| print('right:', [c.text for c in right.children_without_case]) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| ''' | |
| Installation | |
| ============ | |
| python -m pip install kivy_garden.drag_n_drop --extra-index-url https://kivy-garden.github.io/simple/ | |
| garden install magnet | |
| ''' | |
| __all__ = ( | |
| 'RichDraggableLayoutBehavior', 'RichDraggableGridLayout', | |
| 'RichDraggableBoxLayout', | |
| ) | |
| from kivy.uix.boxlayout import BoxLayout | |
| from kivy.uix.gridlayout import GridLayout | |
| from kivy.garden.magnet import Magnet | |
| from kivy_garden.drag_n_drop import ( | |
| DraggableController, DraggableLayoutBehavior, DraggableObjectBehavior, | |
| SpacerWidget, | |
| ) | |
| class DraggableMagnet(DraggableObjectBehavior, Magnet): | |
| def initiate_drag(self): | |
| self.parent.remove_widget(self) | |
| class RichDraggableLayoutBehavior(DraggableLayoutBehavior): | |
| def __init__(self, **kwargs): | |
| super().__init__(**kwargs) | |
| magnet = Magnet(duration=.2) | |
| magnet.add_widget(SpacerWidget()) | |
| self.spacer_widget = magnet | |
| self.drag_controller = DraggableController() | |
| def add_widget(self, widget, index=0, *, drag_cls=''): | |
| if isinstance(widget, Magnet): | |
| super().add_widget(widget, index=index) | |
| else: | |
| magnet = DraggableMagnet( | |
| drag_cls=drag_cls, | |
| duration=.5, | |
| drag_controller=self.drag_controller | |
| ) | |
| magnet.add_widget(widget) | |
| super().add_widget(magnet, index=index) | |
| def remove_widget(self, widget): | |
| if isinstance(widget, Magnet): | |
| super().remove_widget(widget) | |
| else: | |
| for c in self.children: | |
| if c.children[0] == widget: | |
| c.remove_widget(widget) | |
| super().remove_widget(c) | |
| def handle_drag_release(self, index, drag_widget): | |
| c = drag_widget.children[0] | |
| s = self.spacer_widget | |
| c.pos, c.size = s.pos, s.size | |
| self.add_widget(drag_widget, index) | |
| @property | |
| def children_without_case(self): | |
| return (magnet.children[0] for magnet in self.children) | |
| class RichDraggableGridLayout(RichDraggableLayoutBehavior, GridLayout): | |
| def compare_pos_to_widget(self, widget, pos): | |
| x, y = pos | |
| if y > widget.top: | |
| return 'before' | |
| elif y < widget.y: | |
| return 'after' | |
| elif x > widget.right: | |
| return 'after' | |
| elif x < widget.x: | |
| return 'before' | |
| else: | |
| spacer = self.spacer_widget | |
| if widget.parent is spacer.parent: | |
| children = widget.parent.children | |
| if children.index(spacer) > children.index(widget): | |
| return 'after' | |
| return 'before' | |
| class RichDraggableBoxLayout(RichDraggableLayoutBehavior, BoxLayout): | |
| def compare_pos_to_widget(self, widget, pos): | |
| if self.orientation == 'vertical': | |
| return 'before' if pos[1] >= widget.center_y else 'after' | |
| return 'before' if pos[0] < widget.center_x else 'after' |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment