Skip to content

Instantly share code, notes, and snippets.

@gottadiveintopython
Last active September 28, 2019 09:03
Show Gist options
  • Select an option

  • Save gottadiveintopython/16311ab6e3cf72406ce8bc029243ddcb to your computer and use it in GitHub Desktop.

Select an option

Save gottadiveintopython/16311ab6e3cf72406ce8bc029243ddcb to your computer and use it in GitHub Desktop.
(Kivy) magnet + drag_n_drop = awesome
'''
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])
'''
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