Mercurial > code > home > repos > light9
view light9/tkdnd.py @ 1742:70873145cc71
get mouse events to pixi. fix pixi-vs-adj coordinate issue
Ignore-this: dbf065b862823c312ceebbbe80dc99df
author | Drew Perttula <drewp@bigasterisk.com> |
---|---|
date | Sat, 19 May 2018 21:55:08 +0000 |
parents | 022e997b50c4 |
children | f066d6e874db |
line wrap: on
line source
from glob import glob from os.path import join, basename class TkdndEvent(object): """ see http://www.ellogon.org/petasis/tcltk-projects/tkdnd/tkdnd-man-page for details on the fields The longer attribute names (action instead of %A) were made up for this API. Not all attributes are visible yet, since I have not thought through what conversions they should receive and I don't want to unnecessarily change their types later. """ substitutions = { "%A" : "action", "%b" : "button", "%D" : "data", "%m" : "modifiers", "%T" : "type", "%W" : "targetWindow", "%X" : "mouseX", "%Y" : "mouseY", } @classmethod def makeEvent(cls, *args): ev = cls() for (k, v), arg in zip(sorted(TkdndEvent.substitutions.items()), args): setattr(ev, v, arg) # it would be cool for this to decode text data according to the charset in the type for attr in ['button', 'mouseX', 'mouseY']: setattr(ev, attr, int(getattr(ev, attr))) return (ev,) tclSubstitutions = ' '.join(sorted(substitutions.keys())) def __repr__(self): return "<TkdndEvent %r>" % self.__dict__ class Hover(object): def __init__(self, widget, style): self.widget, self.style = widget, style self.oldStyle = {} def set(self, ev): for k, v in self.style.items(): self.oldStyle[k] = self.widget.cget(k) self.widget.configure(**self.style) return ev.action def restore(self, ev): self.widget.configure(**self.oldStyle) def initTkdnd(tk, tkdndBuildDir): """ pass the 'tk' attribute of any Tkinter object, and the top dir of your built tkdnd package """ tk.call('source', join(tkdndBuildDir, 'library/tkdnd.tcl')) for dll in glob(join(tkdndBuildDir, '*tkdnd*' + tk.call('info', 'sharedlibextension'))): tk.call('tkdnd::initialise', join(tkdndBuildDir, 'library'), join('..', basename(dll)), 'tkdnd') def dragSourceRegister(widget, action='copy', datatype='text/uri-list', data=''): """ if the 'data' param is callable, it will be called every time to look up the current data. If the callable returns None (or data is None to begin with), the drag """ widget.tk.call('tkdnd::drag_source', 'register', widget._w) # with normal Tkinter bind(), the result of your handler isn't # actually returned so the drag doesn't get launched. This is a # corrected version of what bind() does when you pass a function, # but I don't block my tuple from getting returned (as a tcl list) def init(): dataValue = data() if callable(data) else data if dataValue is None: return return (action, datatype, dataValue) funcId = widget._register(init, widget._substitute, 1 # needscleanup ) widget.bind("<<DragInitCmd>>", funcId) def dropTargetRegister(widget, typeList=None, onDropEnter=None, onDropPosition=None, onDropLeave=None, onDrop=None, hoverStyle=None, ): """ the optional callbacks will be called with a TkdndEvent argument. onDropEnter, onDropPosition, and onDrop are supposed to return an action (perhaps the value in event.action). The return value seems to have no effect, but it might just be that errors are getting silenced. Passing hoverStyle sets onDropEnter to call widget.configure(**hoverStyle) and onDropLeave to restore the widget's style. onDrop is also wrapped to do a restore. """ if hoverStyle is not None: hover = Hover(widget, hoverStyle) def wrappedDrop(ev): hover.restore(ev) if onDrop: return onDrop(ev) return dropTargetRegister(widget, typeList=typeList, onDropEnter=hover.set, onDropLeave=hover.restore, onDropPosition=onDropPosition, onDrop=wrappedDrop) if typeList is None: typeList = ['*'] widget.tk.call(*(['tkdnd::drop_target', 'register', widget._w]+typeList)) for sequence, handler in [ ('<<DropEnter>>', onDropEnter), ('<<DropPosition>>', onDropPosition), ('<<DropLeave>>', onDropLeave), ('<<Drop>>', onDrop), ]: if not handler: continue func = widget._register(handler, subst=TkdndEvent.makeEvent, needcleanup=1) widget.bind(sequence, func + " " + TkdndEvent.tclSubstitutions)