annotate Lib/tkinter/dnd.py @ 79691:05c8928362ee

Merge __next__ method link fixes with 3.3.
author Ezio Melotti <ezio.melotti@gmail.com>
date Fri, 12 Oct 2012 13:46:37 +0300
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()