Initial checkin
[ejpi] / src / libraries / gtkpieboard.py
1 #!/usr/bin/env python
2
3
4 from __future__ import division
5
6 import copy
7 import warnings
8
9 import gobject
10 import gtk
11
12 import gtkpie
13
14
15 class PieKeyboard(gtk.Table):
16
17         def __init__(self, style, rows, columns, alternateStyles=True):
18                 super(PieKeyboard, self).__init__(rows, columns, homogeneous=True)
19
20                 self.__cells = {}
21                 for row in xrange(rows):
22                         for column in xrange(columns):
23                                 popup = gtkpie.PiePopup(
24                                         self._alternate_style(row, column, style) if alternateStyles else style
25                                 )
26                                 self.attach(popup, column, column+1, row, row+1)
27                                 self.__cells[(row, column)] = popup
28
29         def add_slice(self, row, column, slice, direction):
30                 pie = self.__cells[(row, column)]
31                 pie.add_slice(slice, direction)
32
33         def add_slices(self, row, column, slices):
34                 pie = self.__cells[(row, column)]
35                 for direction, slice in slices.iteritems():
36                         pie.add_slice(slice, direction)
37
38         def get_pie(self, row, column):
39                 return self.__cells[(row, column)]
40
41         @classmethod
42         def _alternate_style(cls, row, column, style):
43                 i = row + column
44                 isEven = (i % 2) == 0
45
46                 if not isEven:
47                         return style
48
49                 altStyle = copy.copy(style)
50                 selected = altStyle[True]
51                 notSelected = altStyle[False]
52                 altStyle[False] = selected
53                 altStyle[True] = notSelected
54                 return altStyle
55
56
57 class KeyboardModifier(object):
58
59         def __init__(self, name):
60                 self.name = name
61                 self.lock = False
62                 self.once = False
63
64         @property
65         def isActive(self):
66                 return self.lock or self.once
67
68         def on_toggle_lock(self, *args, **kwds):
69                 self.lock = not self.lock
70
71         def on_toggle_once(self, *args, **kwds):
72                 self.once = not self.once
73
74         def reset_once(self):
75                 self.once = False
76
77
78 gobject.type_register(PieKeyboard)
79
80
81 def parse_keyboard_data(text):
82         return eval(text)
83
84
85 def load_keyboard(keyboardName, dataTree, keyboard, keyboardHandler):
86         for (row, column), pieData in dataTree.iteritems():
87                 showAllSlices = pieData["showAllSlices"]
88                 keyboard.get_pie(row, column).showAllSlices = showAllSlices
89                 for direction, directionName in enumerate(gtkpie.PieSlice.SLICE_DIRECTION_NAMES):
90                         if directionName not in pieData:
91                                 continue
92                         sliceName = "%s-(%d, %d)-%s" % (keyboardName, row, column, directionName)
93
94                         sliceData = pieData[directionName]
95                         sliceAction = sliceData["action"]
96                         sliceType = sliceData["type"]
97                         if sliceType == "text":
98                                 text = sliceData["text"]
99                                 # font = sliceData["font"] # @TODO
100                                 slice = gtkpie.TextLabelPieSlice(text, handler=keyboardHandler)
101                         elif sliceType == "image":
102                                 path = sliceData["path"]
103                                 slice = gtkpie.ImageLabelPieSlice(path, handler=keyboardHandler)
104
105                         slice.name = sliceName
106                         keyboard.add_slice(row, column, slice, direction)
107                         keyboardHandler.map_slice_action(slice, sliceAction)
108
109
110 class KeyboardHandler(object):
111
112         def __init__(self, keyhandler):
113                 self.__keyhandler = keyhandler
114                 self.__commandHandlers = {}
115                 self.__modifiers = {}
116                 self.__sliceActions = {}
117
118                 self.register_modifier("Shift")
119                 self.register_modifier("Super")
120                 self.register_modifier("Control")
121                 self.register_modifier("Alt")
122
123         def register_command_handler(self, command, handler):
124                 #@todo Make this handle multiple handlers or switch to gobject events
125                 self.__commandHandlers["[%s]" % command] = handler
126
127         def unregister_command_handler(self, command):
128                 #@todo Make this handle multiple handlers or switch to gobject events
129                 del self.__commandHandlers["[%s]" % command]
130
131         def register_modifier(self, modifierName):
132                 mod = KeyboardModifier(modifierName)
133                 self.register_command_handler(modifierName, mod.on_toggle_lock)
134                 self.__modifiers["<%s>" % modifierName] = mod
135
136         def unregister_modifier(self, modifierName):
137                 self.unregister_command_handler(modifierName)
138                 del self.__modifiers["<%s>" % modifierName]
139
140         def map_slice_action(self, slice, action):
141                 self.__sliceActions[slice.name] = action
142
143         def __call__(self, pie, slice, direction):
144                 try:
145                         action = self.__sliceActions[slice.name]
146                 except KeyError:
147                         return
148
149                 activeModifiers = [
150                         mod.name
151                         for mod in self.__modifiers.itervalues()
152                                 if mod.isActive
153                 ]
154
155                 needResetOnce = False
156                 if action.startswith("[") and action.endswith("]"):
157                         commandName = action[1:-1]
158                         if action in self.__commandHandlers:
159                                 self.__commandHandlers[action](commandName, activeModifiers)
160                                 needResetOnce = True
161                         else:
162                                 warnings.warn("Unknown command: [%s]" % commandName)
163                 elif action.startswith("<") and action.endswith(">"):
164                         modName = action[1:-1]
165                         for mod in self.__modifiers.itervalues():
166                                 if mod.name == modName:
167                                         mod.on_toggle_once()
168                                         break
169                         else:
170                                 warnings.warn("Unknown modifier: <%s>" % modName)
171                 else:
172                         self.__keyhandler(action, activeModifiers)
173                         needResetOnce = True
174
175                 if needResetOnce:
176                         for mod in self.__modifiers.itervalues():
177                                 mod.reset_once()