annotate Lib/tkinter/dnd.py @ 87690:66c1c9f32567 default tip

Add use_weakref option to functools.lru_cache The use_weakref option makes lru_cache create weak references to the function arguments when creating the cache key, which prevents them from staying in the memory forever even after all other references to them are gone. This is a proof of concept for http://bugs.python.org/issue19859
author Radomir Dopieralski <devel@sheep.art.pl>
date Tue, 03 Dec 2013 16:02:48 +0100
parents ef4cca2d6171
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
1 """Drag-and-drop support for Tkinter.
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
2
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
3 This is very preliminary. I currently only support dnd *within* one
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
4 application, between different windows (or within the same window).
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
5
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
6 I an trying to make this as generic as possible -- not dependent on
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
7 the use of a particular widget or icon type, etc. I also hope that
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
8 this will work with Pmw.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
9
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
10 To enable an object to be dragged, you must create an event binding
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
11 for it that starts the drag-and-drop process. Typically, you should
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
12 bind <ButtonPress> to a callback function that you write. The function
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
13 should call Tkdnd.dnd_start(source, event), where 'source' is the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
14 object to be dragged, and 'event' is the event that invoked the call
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
15 (the argument to your callback function). Even though this is a class
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
16 instantiation, the returned instance should not be stored -- it will
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
17 be kept alive automatically for the duration of the drag-and-drop.
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
18
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
19 When a drag-and-drop is already in process for the Tk interpreter, the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
20 call is *ignored*; this normally averts starting multiple simultaneous
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
21 dnd processes, e.g. because different button callbacks all
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
22 dnd_start().
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
23
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
24 The object is *not* necessarily a widget -- it can be any
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
25 application-specific object that is meaningful to potential
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
26 drag-and-drop targets.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
27
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
28 Potential drag-and-drop targets are discovered as follows. Whenever
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
29 the mouse moves, and at the start and end of a drag-and-drop move, the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
30 Tk widget directly under the mouse is inspected. This is the target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
31 widget (not to be confused with the target object, yet to be
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
32 determined). If there is no target widget, there is no dnd target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
33 object. If there is a target widget, and it has an attribute
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
34 dnd_accept, this should be a function (or any callable object). The
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
35 function is called as dnd_accept(source, event), where 'source' is the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
36 object being dragged (the object passed to dnd_start() above), and
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
37 'event' is the most recent event object (generally a <Motion> event;
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
38 it can also be <ButtonPress> or <ButtonRelease>). If the dnd_accept()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
39 function returns something other than None, this is the new dnd target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
40 object. If dnd_accept() returns None, or if the target widget has no
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
41 dnd_accept attribute, the target widget's parent is considered as the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
42 target widget, and the search for a target object is repeated from
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
43 there. If necessary, the search is repeated all the way up to the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
44 root widget. If none of the target widgets can produce a target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
45 object, there is no target object (the target object is None).
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
46
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
47 The target object thus produced, if any, is called the new target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
48 object. It is compared with the old target object (or None, if there
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
49 was no old target widget). There are several cases ('source' is the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
50 source object, and 'event' is the most recent event object):
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
51
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
52 - Both the old and new target objects are None. Nothing happens.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
53
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
54 - The old and new target objects are the same object. Its method
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
55 dnd_motion(source, event) is called.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
56
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
57 - The old target object was None, and the new target object is not
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
58 None. The new target object's method dnd_enter(source, event) is
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
59 called.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
60
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
61 - The new target object is None, and the old target object is not
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
62 None. The old target object's method dnd_leave(source, event) is
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
63 called.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
64
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
65 - The old and new target objects differ and neither is None. The old
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
66 target object's method dnd_leave(source, event), and then the new
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
67 target object's method dnd_enter(source, event) is called.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
68
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
69 Once this is done, the new target object replaces the old one, and the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
70 Tk mainloop proceeds. The return value of the methods mentioned above
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
71 is ignored; if they raise an exception, the normal exception handling
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
72 mechanisms take over.
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
73
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
74 The drag-and-drop processes can end in two ways: a final target object
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
75 is selected, or no final target object is selected. When a final
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
76 target object is selected, it will always have been notified of the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
77 potential drop by a call to its dnd_enter() method, as described
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
78 above, and possibly one or more calls to its dnd_motion() method; its
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
79 dnd_leave() method has not been called since the last call to
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
80 dnd_enter(). The target is notified of the drop by a call to its
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
81 method dnd_commit(source, event).
15308
847ae40074d4 Make reindent.py happy (convert everything to 4-space indents!).
Fred Drake <fdrake@acm.org>
parents: 13620
diff changeset
82
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
83 If no final target object is selected, and there was an old target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
84 object, its dnd_leave(source, event) method is called to complete the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
85 dnd sequence.
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
86
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
87 Finally, the source object is notified that the drag-and-drop process
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
88 is over, by a call to source.dnd_end(target, event), specifying either
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
89 the selected target object, or None if no target object was selected.
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
90 The source object can use this to implement the commit action; this is
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
91 sometimes simpler than to do it in the target's dnd_commit(). The
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
92 target's dnd_commit() method could then simply be aliased to
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
93 dnd_leave().
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
94
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
95 At any time during a dnd sequence, the application can cancel the
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
96 sequence by calling the cancel() method on the object returned by
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
97 dnd_start(). This will call dnd_leave() if a target is currently
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
98 active; it will never call dnd_commit().
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
99
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
100 """
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
101
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
102
47130
ef4cca2d6171 Tkinter, step 2: adapt imports.
Georg Brandl <georg@python.org>
parents: 47129
diff changeset
103 import tkinter
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
104
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
105
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
106 # The factory function
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
107
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
108 def dnd_start(source, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
109 h = DndHandler(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
110 if h.root:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
111 return h
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
112 else:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
113 return None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
114
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
115
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
116 # The class that does the work
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
117
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
118 class DndHandler:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
119
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
120 root = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
121
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
122 def __init__(self, source, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
123 if event.num > 5:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
124 return
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
125 root = event.widget._root()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
126 try:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
127 root.__dnd
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
128 return # Don't start recursive dnd
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
129 except AttributeError:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
130 root.__dnd = self
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
131 self.root = root
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
132 self.source = source
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
133 self.target = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
134 self.initial_button = button = event.num
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
135 self.initial_widget = widget = event.widget
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
136 self.release_pattern = "<B%d-ButtonRelease-%d>" % (button, button)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
137 self.save_cursor = widget['cursor'] or ""
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
138 widget.bind(self.release_pattern, self.on_release)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
139 widget.bind("<Motion>", self.on_motion)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
140 widget['cursor'] = "hand2"
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
141
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
142 def __del__(self):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
143 root = self.root
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
144 self.root = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
145 if root:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
146 try:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
147 del root.__dnd
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
148 except AttributeError:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
149 pass
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
150
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
151 def on_motion(self, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
152 x, y = event.x_root, event.y_root
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
153 target_widget = self.initial_widget.winfo_containing(x, y)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
154 source = self.source
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
155 new_target = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
156 while target_widget:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
157 try:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
158 attr = target_widget.dnd_accept
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
159 except AttributeError:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
160 pass
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
161 else:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
162 new_target = attr(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
163 if new_target:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
164 break
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
165 target_widget = target_widget.master
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
166 old_target = self.target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
167 if old_target is new_target:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
168 if old_target:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
169 old_target.dnd_motion(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
170 else:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
171 if old_target:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
172 self.target = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
173 old_target.dnd_leave(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
174 if new_target:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
175 new_target.dnd_enter(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
176 self.target = new_target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
177
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
178 def on_release(self, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
179 self.finish(event, 1)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
180
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
181 def cancel(self, event=None):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
182 self.finish(event, 0)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
183
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
184 def finish(self, event, commit=0):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
185 target = self.target
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
186 source = self.source
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
187 widget = self.initial_widget
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
188 root = self.root
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
189 try:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
190 del root.__dnd
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
191 self.initial_widget.unbind(self.release_pattern)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
192 self.initial_widget.unbind("<Motion>")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
193 widget['cursor'] = self.save_cursor
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
194 self.target = self.source = self.initial_widget = self.root = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
195 if target:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
196 if commit:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
197 target.dnd_commit(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
198 else:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
199 target.dnd_leave(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
200 finally:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
201 source.dnd_end(target, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
202
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
203
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
204
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
205 # ----------------------------------------------------------------------
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
206 # The rest is here for testing and demonstration purposes only!
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
207
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
208 class Icon:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
209
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
210 def __init__(self, name):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
211 self.name = name
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
212 self.canvas = self.label = self.id = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
213
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
214 def attach(self, canvas, x=10, y=10):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
215 if canvas is self.canvas:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
216 self.canvas.coords(self.id, x, y)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
217 return
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
218 if self.canvas:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
219 self.detach()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
220 if not canvas:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
221 return
47130
ef4cca2d6171 Tkinter, step 2: adapt imports.
Georg Brandl <georg@python.org>
parents: 47129
diff changeset
222 label = tkinter.Label(canvas, text=self.name,
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
223 borderwidth=2, relief="raised")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
224 id = canvas.create_window(x, y, window=label, anchor="nw")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
225 self.canvas = canvas
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
226 self.label = label
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
227 self.id = id
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
228 label.bind("<ButtonPress>", self.press)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
229
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
230 def detach(self):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
231 canvas = self.canvas
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
232 if not canvas:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
233 return
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
234 id = self.id
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
235 label = self.label
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
236 self.canvas = self.label = self.id = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
237 canvas.delete(id)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
238 label.destroy()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
239
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
240 def press(self, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
241 if dnd_start(self, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
242 # where the pointer is relative to the label widget:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
243 self.x_off = event.x
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
244 self.y_off = event.y
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
245 # where the widget is relative to the canvas:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
246 self.x_orig, self.y_orig = self.canvas.coords(self.id)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
247
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
248 def move(self, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
249 x, y = self.where(self.canvas, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
250 self.canvas.coords(self.id, x, y)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
251
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
252 def putback(self):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
253 self.canvas.coords(self.id, self.x_orig, self.y_orig)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
254
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
255 def where(self, canvas, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
256 # where the corner of the canvas is relative to the screen:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
257 x_org = canvas.winfo_rootx()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
258 y_org = canvas.winfo_rooty()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
259 # where the pointer is relative to the canvas widget:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
260 x = event.x_root - x_org
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
261 y = event.y_root - y_org
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
262 # compensate for initial pointer offset
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
263 return x - self.x_off, y - self.y_off
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
264
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
265 def dnd_end(self, target, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
266 pass
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
267
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
268 class Tester:
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
269
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
270 def __init__(self, root):
47130
ef4cca2d6171 Tkinter, step 2: adapt imports.
Georg Brandl <georg@python.org>
parents: 47129
diff changeset
271 self.top = tkinter.Toplevel(root)
ef4cca2d6171 Tkinter, step 2: adapt imports.
Georg Brandl <georg@python.org>
parents: 47129
diff changeset
272 self.canvas = tkinter.Canvas(self.top, width=100, height=100)
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
273 self.canvas.pack(fill="both", expand=1)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
274 self.canvas.dnd_accept = self.dnd_accept
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
275
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
276 def dnd_accept(self, source, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
277 return self
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
278
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
279 def dnd_enter(self, source, event):
13620
5b727ab37092 Spelling fixes supplied by Rob W. W. Hooft. All these are fixes in either
Thomas Wouters <thomas@python.org>
parents: 7953
diff changeset
280 self.canvas.focus_set() # Show highlight border
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
281 x, y = source.where(self.canvas, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
282 x1, y1, x2, y2 = source.canvas.bbox(source.id)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
283 dx, dy = x2-x1, y2-y1
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
284 self.dndid = self.canvas.create_rectangle(x, y, x+dx, y+dy)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
285 self.dnd_motion(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
286
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
287 def dnd_motion(self, source, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
288 x, y = source.where(self.canvas, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
289 x1, y1, x2, y2 = self.canvas.bbox(self.dndid)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
290 self.canvas.move(self.dndid, x-x1, y-y1)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
291
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
292 def dnd_leave(self, source, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
293 self.top.focus_set() # Hide highlight border
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
294 self.canvas.delete(self.dndid)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
295 self.dndid = None
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
296
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
297 def dnd_commit(self, source, event):
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
298 self.dnd_leave(source, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
299 x, y = source.where(self.canvas, event)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
300 source.attach(self.canvas, x, y)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
301
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
302 def test():
47130
ef4cca2d6171 Tkinter, step 2: adapt imports.
Georg Brandl <georg@python.org>
parents: 47129
diff changeset
303 root = tkinter.Tk()
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
304 root.geometry("+1+1")
47130
ef4cca2d6171 Tkinter, step 2: adapt imports.
Georg Brandl <georg@python.org>
parents: 47129
diff changeset
305 tkinter.Button(command=root.quit, text="Quit").pack()
7953
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
306 t1 = Tester(root)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
307 t1.top.geometry("+1+60")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
308 t2 = Tester(root)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
309 t2.top.geometry("+120+60")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
310 t3 = Tester(root)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
311 t3.top.geometry("+240+60")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
312 i1 = Icon("ICON1")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
313 i2 = Icon("ICON2")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
314 i3 = Icon("ICON3")
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
315 i1.attach(t1.canvas)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
316 i2.attach(t2.canvas)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
317 i3.attach(t3.canvas)
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
318 root.mainloop()
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
319
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
320 if __name__ == '__main__':
92e36116af42 Another easter present.
Guido van Rossum <guido@python.org>
parents:
diff changeset
321 test()