aaac851bfd4352bbf6928d970c864c4f18eca174
[audiocontrol.git] / Bindings.py
1 """The Bindings module manages an infrastructure for key bindings."""
2
3 # Event = (context, sequence ...) wobei alle elsts strings sind
4
5 # gebuynbden wird ein Action object. Jede Action hat einen namen unter
6 # der sie registriert wird.  die funktionen zum definieren eines
7 # keymnap und zum binden von keys nehmen diesen namen als argument =>
8 # alle Aktionen m"ussen vorher registriert werden
9
10 # KeyStack => KeyMap => Binding => Action
11
12 # Das Binding Objekt enthaelt das Event unter welchem die Action
13 # gebunden ist. Jedes Binding aht auch einen label zum anzeigen des
14 # bindings
15
16 import Node, Actions, Events, Logger
17
18 class Binding(Node.Node):
19
20     action = Node.NodeReference()
21
22     def __init__(self, event, label, action):
23         Node.Node.__init__(self)
24         self.event = event
25         self.label = label
26         self.action = action
27
28     def keymap(self):
29         return self.owner
30
31     def execute(self):
32         Logger.log('binding', 'execute: %s' % self.action.name)
33         self.action(self)
34
35
36 class KeyMap(Node.Node):
37
38     _map = Node.NodeMap()
39
40     def __init__(self, name=None):
41         Node.Node.__init__(self)
42         self._name = name
43
44     def add(self, binding):
45         if self.owner : raise RuntimeError, 'changing an active KeyMap not supported'
46         self._map[binding.event] = binding
47
48     def unbind(self, event):
49         if self.owner : raise RuntimeError, 'changing an active KeyMap not supported'
50         del self._map[event]
51
52     def name(self):
53         return self._name
54
55     def index(self):
56         if self.owner : return self.owner.indexOf(self)
57         else          : return None
58
59     def keylist(self):
60         return self.owner
61
62     def lookup(self, event):
63         return self._map.get(event,None)
64
65     def bindings(self):
66         return self._map
67
68
69 class KeyList(Node.Node):
70
71     _list = Node.NodeList()
72     
73     def __init__(self):
74         Node.Node.__init__(self)
75         self._callbacks = []
76
77     def indexOf(self, map):
78         return self._list.index(map)
79
80     def append(self, map):
81         self._list.append(map)
82         self._callCallbacks()
83
84     def replaceFromIndex(self, index, maps):
85         self._list[index:] = maps
86         self._callCallbacks()
87
88     def lookup(self, event):
89         for i in range(len(self._list)-1,-1,-1):
90             binding = self._list[i].lookup(event)
91             if binding is not None : return binding
92         return None
93
94     def bindings(self):
95         bindings = {}
96         for map in self._list:
97             bindings.update(map.bindings())
98         return bindings
99
100     def bindingsByContext(self):
101         bindings = {}
102         for map in self._list:
103             for binding in map.bindings().itervalues():
104                 bindings.setdefault(binding.event.context,{})
105                 bindings[binding.event.context][binding.event] = binding
106         return bindings
107
108     def registerCallback(self, cb):
109         self._callbacks.append(cb)
110
111     def unregisterCallback(self, cb):
112         self._callbacks.remove(cb)
113
114     def _callCallbacks(self):
115         for cb in self._callbacks : cb(self)
116
117     def path(self):
118         return ' / '.join([ map.name() for map in self._list if map.name() ])