ó u®¸Qc@swdZddlZd„Zdd d„ƒYZdd d„ƒYZddd „ƒYZd „Zed krseƒndS(sFDrag-and-drop support for Tkinter. This is very preliminary. I currently only support dnd *within* one application, between different windows (or within the same window). I an trying to make this as generic as possible -- not dependent on the use of a particular widget or icon type, etc. I also hope that this will work with Pmw. To enable an object to be dragged, you must create an event binding for it that starts the drag-and-drop process. Typically, you should bind to a callback function that you write. The function should call Tkdnd.dnd_start(source, event), where 'source' is the object to be dragged, and 'event' is the event that invoked the call (the argument to your callback function). Even though this is a class instantiation, the returned instance should not be stored -- it will be kept alive automatically for the duration of the drag-and-drop. When a drag-and-drop is already in process for the Tk interpreter, the call is *ignored*; this normally averts starting multiple simultaneous dnd processes, e.g. because different button callbacks all dnd_start(). The object is *not* necessarily a widget -- it can be any application-specific object that is meaningful to potential drag-and-drop targets. Potential drag-and-drop targets are discovered as follows. Whenever the mouse moves, and at the start and end of a drag-and-drop move, the Tk widget directly under the mouse is inspected. This is the target widget (not to be confused with the target object, yet to be determined). If there is no target widget, there is no dnd target object. If there is a target widget, and it has an attribute dnd_accept, this should be a function (or any callable object). The function is called as dnd_accept(source, event), where 'source' is the object being dragged (the object passed to dnd_start() above), and 'event' is the most recent event object (generally a event; it can also be or ). If the dnd_accept() function returns something other than None, this is the new dnd target object. If dnd_accept() returns None, or if the target widget has no dnd_accept attribute, the target widget's parent is considered as the target widget, and the search for a target object is repeated from there. If necessary, the search is repeated all the way up to the root widget. If none of the target widgets can produce a target object, there is no target object (the target object is None). The target object thus produced, if any, is called the new target object. It is compared with the old target object (or None, if there was no old target widget). There are several cases ('source' is the source object, and 'event' is the most recent event object): - Both the old and new target objects are None. Nothing happens. - The old and new target objects are the same object. Its method dnd_motion(source, event) is called. - The old target object was None, and the new target object is not None. The new target object's method dnd_enter(source, event) is called. - The new target object is None, and the old target object is not None. The old target object's method dnd_leave(source, event) is called. - The old and new target objects differ and neither is None. The old target object's method dnd_leave(source, event), and then the new target object's method dnd_enter(source, event) is called. Once this is done, the new target object replaces the old one, and the Tk mainloop proceeds. The return value of the methods mentioned above is ignored; if they raise an exception, the normal exception handling mechanisms take over. The drag-and-drop processes can end in two ways: a final target object is selected, or no final target object is selected. When a final target object is selected, it will always have been notified of the potential drop by a call to its dnd_enter() method, as described above, and possibly one or more calls to its dnd_motion() method; its dnd_leave() method has not been called since the last call to dnd_enter(). The target is notified of the drop by a call to its method dnd_commit(source, event). If no final target object is selected, and there was an old target object, its dnd_leave(source, event) method is called to complete the dnd sequence. Finally, the source object is notified that the drag-and-drop process is over, by a call to source.dnd_end(target, event), specifying either the selected target object, or None if no target object was selected. The source object can use this to implement the commit action; this is sometimes simpler than to do it in the target's dnd_commit(). The target's dnd_commit() method could then simply be aliased to dnd_leave(). At any time during a dnd sequence, the application can cancel the sequence by calling the cancel() method on the object returned by dnd_start(). This will call dnd_leave() if a target is currently active; it will never call dnd_commit(). iÿÿÿÿNcCs$t||ƒ}|jr|SdSdS(N(t DndHandlertroottNone(tsourceteventth((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyt dnd_startls RcBsJeZdZd„Zd„Zd„Zd„Zdd„Zdd„Z RS(cCsæ|jdkrdS|jjƒ}y|jdSWn#tk rV||_||_nX||_d|_|j|_ }|j|_ }d||f|_ |dp©d|_ |j |j |jƒ|j d|jƒd|dtcursortsthand2(tnumtwidgett_roott_DndHandler__dndtAttributeErrorRRRttargettinitial_buttontinitial_widgettrelease_patternt save_cursortbindt on_releaset on_motion(tselfRRRtbuttonR ((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyt__init__zs$     cCs=|j}d|_|r9y |`Wq9tk r5q9XndS(N(RRR R(RR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyt__del__Žs    c Cs|j|j}}|jj||ƒ}|j}d}xM|r†y |j}Wntk r`nX|||ƒ}|rzPn|j}q:W|j }||kr¸|rü|j ||ƒqünD|rÚd|_ |j ||ƒn|rü|j ||ƒ||_ ndS(N( tx_rootty_rootRtwinfo_containingRRt dnd_acceptRtmasterRt dnd_motiont dnd_leavet dnd_enter( RRtxtyt target_widgetRt new_targettattrt old_target((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR—s.        cCs|j|dƒdS(Ni(tfinish(RR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR²scCs|j|dƒdS(Ni(R)(RR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pytcancelµsicCsÆ|j}|j}|j}|j}zŠ|`|jj|jƒ|jjdƒ|j|dR( RRRRR tunbindRRRt dnd_commitR!tdnd_end(RRtcommitRRR R((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR)¸s     N( t__name__t __module__RRRRRRR*R)(((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRvs    tIconcBsVeZd„Zddd„Zd„Zd„Zd„Zd„Zd„Zd„Z RS( cCs$||_d|_|_|_dS(N(tnameRtcanvastlabeltid(RR2((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRÒs i cCsÀ||jkr,|jj|j||ƒdS|jrB|jƒn|sLdStj|d|jddddƒ}|j||d|ddƒ}||_||_||_|j d |j ƒdS( Nttextt borderwidthitrelieftraisedtwindowtanchortnws ( R3tcoordsR5tdetachtTkintertLabelR2t create_windowR4Rtpress(RR3R#R$R4R5((s"/sys/lib/python2.7/lib-tk/Tkdnd.pytattachÖs     cCsW|j}|sdS|j}|j}d|_|_|_|j|ƒ|jƒdS(N(R3R5R4Rtdeletetdestroy(RR3R5R4((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR>æs    cCsOt||ƒrK|j|_|j|_|jj|jƒ\|_|_ ndS(N( RR#tx_offR$ty_offR3R=R5tx_origty_orig(RR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRBðs  cCs8|j|j|ƒ\}}|jj|j||ƒdS(N(twhereR3R=R5(RRR#R$((s"/sys/lib/python2.7/lib-tk/Tkdnd.pytmoveøscCs#|jj|j|j|jƒdS(N(R3R=R5RHRI(R((s"/sys/lib/python2.7/lib-tk/Tkdnd.pytputbacküscCsJ|jƒ}|jƒ}|j|}|j|}||j||jfS(N(t winfo_rootxt winfo_rootyRRRFRG(RR3Rtx_orgty_orgR#R$((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRJÿs     cCsdS(N((RRR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR- s( R/R0RRCR>RBRKRLRJR-(((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR1Ðs     tTestercBs>eZd„Zd„Zd„Zd„Zd„Zd„ZRS(cCs_tj|ƒ|_tj|jddddƒ|_|jjddddƒ|j|j_dS(Ntwidthidtheighttfilltbothtexpandi(R?tToplevelttoptCanvasR3tpackR(RR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRs!cCs|S(N((RRR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRsc Cs˜|jjƒ|j|j|ƒ\}}|jj|jƒ\}}}}||||} } |jj|||| || ƒ|_|j||ƒdS(N(R3t focus_setRJtbboxR5tcreate_rectangletdndidR ( RRRR#R$tx1ty1tx2ty2tdxtdy((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR"s  !&c Csa|j|j|ƒ\}}|jj|jƒ\}}}}|jj|j||||ƒdS(N(RJR3R\R^RK( RRRR#R$R_R`RaRb((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR s!cCs-|jjƒ|jj|jƒd|_dS(N(RXR[R3RDR^R(RRR((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR!$s cCsE|j||ƒ|j|j|ƒ\}}|j|j||ƒdS(N(R!RJR3RC(RRRR#R$((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyR,)s(R/R0RRR"R R!R,(((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyRQ s      cCsîtjƒ}|jdƒtjd|jddƒjƒt|ƒ}|jjdƒt|ƒ}|jjdƒt|ƒ}|jjdƒtdƒ}td ƒ}td ƒ}|j |j ƒ|j |j ƒ|j |j ƒ|j ƒdS( Ns+1+1tcommandR6tQuits+1+60s+120+60s+240+60tICON1tICON2tICON3( R?tTktgeometrytButtontquitRZRQRXR1RCR3tmainloop(Rtt1tt2tt3ti1ti2ti3((s"/sys/lib/python2.7/lib-tk/Tkdnd.pyttest.s         t__main__((((t__doc__R?RRR1RQRuR/(((s"/sys/lib/python2.7/lib-tk/Tkdnd.pytds  Z<"