Back to index

python3.2  3.2.2
Classes | Functions | Variables
idlelib.MultiCall Namespace Reference

Classes

class  _SimpleBinder
class  _ComplexBinder

Functions

def expand_substates
def _parse_sequence
def _triplet_to_sequence
def MultiCallCreator
def bindseq

Variables

int MC_KEYPRESS = 0
int MC_ACTIVATE = 4
int MC_DEACTIVATE = 8
int MC_FOCUSOUT = 13
int MC_MOUSEWHEEL = 18
int MC_SHIFT = 1
int MC_OPTION = 1
tuple _modifiers = (("Shift",), ("Control",), ("Option",), ("Command",))
tuple _modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND)
tuple _modifier_names
tuple _states = range(1 << len(_modifiers))
list _state_names
tuple _state_subsets = expand_substates(_states)
list _state_codes = []
int r = 0
tuple _types
tuple _binder_classes = (_ComplexBinder,)
tuple _type_names
tuple _keysym_re = re.compile(r"^\w+$")
tuple _button_re = re.compile(r"^[1-5]$")
dictionary _multicall_dict = {}
tuple root = tkinter.Tk()
tuple text = MultiCallCreator(tkinter.Text)
 __eventinfo
 __binders

Detailed Description

MultiCall - a class which inherits its methods from a Tkinter widget (Text, for
example), but enables multiple calls of functions per virtual event - all
matching events will be called, not only the most specific one. This is done
by wrapping the event functions - event_add, event_delete and event_info.
MultiCall recognizes only a subset of legal event sequences. Sequences which
are not recognized are treated by the original Tk handling mechanism. A
more-specific event will be called before a less-specific event.

The recognized sequences are complete one-event sequences (no emacs-style
Ctrl-X Ctrl-C, no shortcuts like <3>), for all types of events.
Key/Button Press/Release events can have modifiers.
The recognized modifiers are Shift, Control, Option and Command for Mac, and
Control, Alt, Shift, Meta/M for other platforms.

For all events which were handled by MultiCall, a new member is added to the
event instance passed to the binded functions - mc_type. This is one of the
event type constants defined in this module (such as MC_KEYPRESS).
For Key/Button events (which are handled by MultiCall and may receive
modifiers), another member is added - mc_state. This member gives the state
of the recognized modifiers, as a combination of the modifier constants
also defined in this module (for example, MC_SHIFT).
Using these members is absolutely portable.

The order by which events are called is defined by these rules:
1. A more-specific event will be called before a less-specific event.
2. A recently-binded event will be called before a previously-binded event,
   unless this conflicts with the first rule.
Each function will be called at most once for each event.

Function Documentation

def idlelib.MultiCall._parse_sequence (   sequence) [private]
Get a string which should describe an event sequence. If it is
successfully parsed as one, return a tuple containing the state (as an int),
the event type (as an index of _types), and the detail - None if none, or a
string if there is one. If the parsing is unsuccessful, return None.

Definition at line 252 of file MultiCall.py.

00252 
00253 def _parse_sequence(sequence):
00254     """Get a string which should describe an event sequence. If it is
00255     successfully parsed as one, return a tuple containing the state (as an int),
00256     the event type (as an index of _types), and the detail - None if none, or a
00257     string if there is one. If the parsing is unsuccessful, return None.
00258     """
00259     if not sequence or sequence[0] != '<' or sequence[-1] != '>':
00260         return None
00261     words = sequence[1:-1].split('-')
00262     modifiers = 0
00263     while words and words[0] in _modifier_names:
00264         modifiers |= 1 << _modifier_names[words[0]]
00265         del words[0]
00266     if words and words[0] in _type_names:
00267         type = _type_names[words[0]]
00268         del words[0]
00269     else:
00270         return None
00271     if _binder_classes[type] is _SimpleBinder:
00272         if modifiers or words:
00273             return None
00274         else:
00275             detail = None
00276     else:
00277         # _ComplexBinder
00278         if type in [_type_names[s] for s in ("KeyPress", "KeyRelease")]:
00279             type_re = _keysym_re
00280         else:
00281             type_re = _button_re
00282 
00283         if not words:
00284             detail = None
00285         elif len(words) == 1 and type_re.match(words[0]):
00286             detail = words[0]
00287         else:
00288             return None
00289 
00290     return modifiers, type, detail

Here is the call graph for this function:

def idlelib.MultiCall._triplet_to_sequence (   triplet) [private]

Definition at line 291 of file MultiCall.py.

00291 
00292 def _triplet_to_sequence(triplet):
00293     if triplet[2]:
00294         return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'-'+ \
00295                triplet[2]+'>'
00296     else:
00297         return '<'+_state_names[triplet[0]]+_types[triplet[1]][0]+'>'

def idlelib.MultiCall.bindseq (   seq,
  n = [0] 
)

Definition at line 403 of file MultiCall.py.

00403 
00404     def bindseq(seq, n=[0]):
00405         def handler(event):
00406             print(seq)
00407         text.bind("<<handler%d>>"%n[0], handler)
00408         text.event_add("<<handler%d>>"%n[0], seq)
        n[0] += 1
For each item of states return a list containing all combinations of
that item with individual bits reset, sorted by the number of set bits.

Definition at line 114 of file MultiCall.py.

00114 
00115 def expand_substates(states):
00116     '''For each item of states return a list containing all combinations of
00117     that item with individual bits reset, sorted by the number of set bits.
00118     '''
00119     def nbits(n):
00120         "number of bits set in n base 2"
00121         nb = 0
00122         while n:
00123             n, rem = divmod(n, 2)
00124             nb += rem
00125         return nb
00126     statelist = []
00127     for state in states:
00128         substates = list(set(state & x for x in states))
00129         substates.sort(key=nbits, reverse=True)
00130         statelist.append(substates)
00131     return statelist

Here is the call graph for this function:

Return a MultiCall class which inherits its methods from the
given widget class (for example, Tkinter.Text). This is used
instead of a templating mechanism.

Definition at line 299 of file MultiCall.py.

00299 
00300 def MultiCallCreator(widget):
00301     """Return a MultiCall class which inherits its methods from the
00302     given widget class (for example, Tkinter.Text). This is used
00303     instead of a templating mechanism.
00304     """
00305     if widget in _multicall_dict:
00306         return _multicall_dict[widget]
00307 
00308     class MultiCall (widget):
00309         assert issubclass(widget, tkinter.Misc)
00310 
00311         def __init__(self, *args, **kwargs):
00312             widget.__init__(self, *args, **kwargs)
00313             # a dictionary which maps a virtual event to a tuple with:
00314             #  0. the function binded
00315             #  1. a list of triplets - the sequences it is binded to
00316             self.__eventinfo = {}
00317             self.__binders = [_binder_classes[i](i, widget, self)
00318                               for i in range(len(_types))]
00319 
00320         def bind(self, sequence=None, func=None, add=None):
00321             #print("bind(%s, %s, %s)" % (sequence, func, add),
00322             #      file=sys.__stderr__)
00323             if type(sequence) is str and len(sequence) > 2 and \
00324                sequence[:2] == "<<" and sequence[-2:] == ">>":
00325                 if sequence in self.__eventinfo:
00326                     ei = self.__eventinfo[sequence]
00327                     if ei[0] is not None:
00328                         for triplet in ei[1]:
00329                             self.__binders[triplet[1]].unbind(triplet, ei[0])
00330                     ei[0] = func
00331                     if ei[0] is not None:
00332                         for triplet in ei[1]:
00333                             self.__binders[triplet[1]].bind(triplet, func)
00334                 else:
00335                     self.__eventinfo[sequence] = [func, []]
00336             return widget.bind(self, sequence, func, add)
00337 
00338         def unbind(self, sequence, funcid=None):
00339             if type(sequence) is str and len(sequence) > 2 and \
00340                sequence[:2] == "<<" and sequence[-2:] == ">>" and \
00341                sequence in self.__eventinfo:
00342                 func, triplets = self.__eventinfo[sequence]
00343                 if func is not None:
00344                     for triplet in triplets:
00345                         self.__binders[triplet[1]].unbind(triplet, func)
00346                     self.__eventinfo[sequence][0] = None
00347             return widget.unbind(self, sequence, funcid)
00348 
00349         def event_add(self, virtual, *sequences):
00350             #print("event_add(%s, %s)" % (repr(virtual), repr(sequences)),
00351             #      file=sys.__stderr__)
00352             if virtual not in self.__eventinfo:
00353                 self.__eventinfo[virtual] = [None, []]
00354 
00355             func, triplets = self.__eventinfo[virtual]
00356             for seq in sequences:
00357                 triplet = _parse_sequence(seq)
00358                 if triplet is None:
00359                     #print("Tkinter event_add(%s)" % seq, file=sys.__stderr__)
00360                     widget.event_add(self, virtual, seq)
00361                 else:
00362                     if func is not None:
00363                         self.__binders[triplet[1]].bind(triplet, func)
00364                     triplets.append(triplet)
00365 
00366         def event_delete(self, virtual, *sequences):
00367             if virtual not in self.__eventinfo:
00368                 return
00369             func, triplets = self.__eventinfo[virtual]
00370             for seq in sequences:
00371                 triplet = _parse_sequence(seq)
00372                 if triplet is None:
00373                     #print("Tkinter event_delete: %s" % seq, file=sys.__stderr__)
00374                     widget.event_delete(self, virtual, seq)
00375                 else:
00376                     if func is not None:
00377                         self.__binders[triplet[1]].unbind(triplet, func)
00378                     triplets.remove(triplet)
00379 
00380         def event_info(self, virtual=None):
00381             if virtual is None or virtual not in self.__eventinfo:
00382                 return widget.event_info(self, virtual)
00383             else:
00384                 return tuple(map(_triplet_to_sequence,
00385                                  self.__eventinfo[virtual][1])) + \
00386                        widget.event_info(self, virtual)
00387 
00388         def __del__(self):
00389             for virtual in self.__eventinfo:
00390                 func, triplets = self.__eventinfo[virtual]
00391                 if func:
00392                     for triplet in triplets:
00393                         self.__binders[triplet[1]].unbind(triplet, func)
00394 
00395 
00396     _multicall_dict[widget] = MultiCall
00397     return MultiCall

Here is the call graph for this function:


Variable Documentation

Definition at line 316 of file MultiCall.py.

Definition at line 315 of file MultiCall.py.

Definition at line 243 of file MultiCall.py.

Definition at line 251 of file MultiCall.py.

Definition at line 250 of file MultiCall.py.

tuple idlelib.MultiCall._modifier_masks = (MC_SHIFT, MC_CONTROL, MC_OPTION, MC_COMMAND)

Definition at line 50 of file MultiCall.py.

Initial value:
00001 dict([(name, number)
00002                          for number in range(len(_modifiers))
00003                          for name in _modifiers[number]])

Definition at line 56 of file MultiCall.py.

tuple idlelib.MultiCall._modifiers = (("Shift",), ("Control",), ("Option",), ("Command",))

Definition at line 49 of file MultiCall.py.

Definition at line 298 of file MultiCall.py.

Definition at line 135 of file MultiCall.py.

Initial value:
00001 [''.join(m[0]+'-'
00002                         for i, m in enumerate(_modifiers)
00003                         if (1 << i) & s)
00004                 for s in _states]

Definition at line 109 of file MultiCall.py.

Definition at line 132 of file MultiCall.py.

Definition at line 108 of file MultiCall.py.

Initial value:
00001 dict([(name, number)
00002                      for number in range(len(_types))
00003                      for name in _types[number]])

Definition at line 246 of file MultiCall.py.

Initial value:
00001 (
00002     ("KeyPress", "Key"), ("KeyRelease",), ("ButtonPress", "Button"),
00003     ("ButtonRelease",), ("Activate",), ("Circulate",), ("Colormap",),
00004     ("Configure",), ("Deactivate",), ("Destroy",), ("Enter",), ("Expose",),
00005     ("FocusIn",), ("FocusOut",), ("Gravity",), ("Leave",), ("Map",),
00006     ("Motion",), ("MouseWheel",), ("Property",), ("Reparent",), ("Unmap",),
00007     ("Visibility",),
00008 )

Definition at line 233 of file MultiCall.py.

Definition at line 39 of file MultiCall.py.

Definition at line 40 of file MultiCall.py.

Definition at line 41 of file MultiCall.py.

Definition at line 38 of file MultiCall.py.

Definition at line 42 of file MultiCall.py.

Definition at line 45 of file MultiCall.py.

Definition at line 44 of file MultiCall.py.

Definition at line 137 of file MultiCall.py.

Definition at line 400 of file MultiCall.py.

Definition at line 401 of file MultiCall.py.