| 117 | # The class that does the work |
| 118 | |
| 119 | class DndHandler: |
| 120 | |
| 121 | root = None |
| 122 | |
| 123 | def __init__(self, source, event): |
| 124 | if event.num > 5: |
| 125 | return |
| 126 | root = event.widget._root() |
| 127 | try: |
| 128 | root.__dnd |
| 129 | return # Don't start recursive dnd |
| 130 | except AttributeError: |
| 131 | root.__dnd = self |
| 132 | self.root = root |
| 133 | self.source = source |
| 134 | self.target = None |
| 135 | self.initial_button = button = event.num |
| 136 | self.initial_widget = widget = event.widget |
| 137 | self.release_pattern = "<B%d-ButtonRelease-%d>" % (button, button) |
| 138 | self.save_cursor = widget['cursor'] or "" |
| 139 | widget.bind(self.release_pattern, self.on_release) |
| 140 | widget.bind("<Motion>", self.on_motion) |
| 141 | widget['cursor'] = "hand2" |
| 142 | |
| 143 | def __del__(self): |
| 144 | root = self.root |
| 145 | self.root = None |
| 146 | if root is not None: |
| 147 | try: |
| 148 | del root.__dnd |
| 149 | except AttributeError: |
| 150 | pass |
| 151 | |
| 152 | def on_motion(self, event): |
| 153 | x, y = event.x_root, event.y_root |
| 154 | target_widget = self.initial_widget.winfo_containing(x, y) |
| 155 | source = self.source |
| 156 | new_target = None |
| 157 | while target_widget is not None: |
| 158 | try: |
| 159 | attr = target_widget.dnd_accept |
| 160 | except AttributeError: |
| 161 | pass |
| 162 | else: |
| 163 | new_target = attr(source, event) |
| 164 | if new_target is not None: |
| 165 | break |
| 166 | target_widget = target_widget.master |
| 167 | old_target = self.target |
| 168 | if old_target is new_target: |
| 169 | if old_target is not None: |
| 170 | old_target.dnd_motion(source, event) |
| 171 | else: |
| 172 | if old_target is not None: |
| 173 | self.target = None |
| 174 | old_target.dnd_leave(source, event) |
| 175 | if new_target is not None: |
| 176 | new_target.dnd_enter(source, event) |
no outgoing calls
no test coverage detected
searching dependent graphs…