db78adcb57649fbdbbac33a1687f39da1ed2109d
[blender.git] / release / scripts / startup / bl_ui / space_userpref_keymap.py
1 # ##### BEGIN GPL LICENSE BLOCK #####
2 #
3 #  This program is free software; you can redistribute it and/or
4 #  modify it under the terms of the GNU General Public License
5 #  as published by the Free Software Foundation; either version 2
6 #  of the License, or (at your option) any later version.
7 #
8 #  This program is distributed in the hope that it will be useful,
9 #  but WITHOUT ANY WARRANTY; without even the implied warranty of
10 #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 #  GNU General Public License for more details.
12 #
13 #  You should have received a copy of the GNU General Public License
14 #  along with this program; if not, write to the Free Software Foundation,
15 #  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
16 #
17 # ##### END GPL LICENSE BLOCK #####
18
19 # <pep8 compliant>
20 import bpy
21 from bpy.types import Menu
22
23
24 class USERPREF_MT_keyconfigs(Menu):
25     bl_label = "KeyPresets"
26     preset_subdir = "keyconfig"
27     preset_operator = "wm.keyconfig_activate"
28
29     def draw(self, context):
30         props = self.layout.operator("wm.context_set_value", text="Blender (default)")
31         props.data_path = "window_manager.keyconfigs.active"
32         props.value = "context.window_manager.keyconfigs.default"
33
34         # now draw the presets
35         Menu.draw_preset(self, context)
36
37
38 class InputKeyMapPanel:
39     bl_space_type = 'USER_PREFERENCES'
40     bl_label = "Input"
41     bl_region_type = 'WINDOW'
42     bl_options = {'HIDE_HEADER'}
43
44     def draw_entry(self, display_keymaps, entry, col, level=0):
45         idname, spaceid, regionid, children = entry
46
47         for km, kc in display_keymaps:
48             if km.name == idname and km.space_type == spaceid and km.region_type == regionid:
49                 self.draw_km(display_keymaps, kc, km, children, col, level)
50
51         '''
52         km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
53         if not km:
54             kc = defkc
55             km = kc.keymaps.find(idname, space_type=spaceid, region_type=regionid)
56
57         if km:
58             self.draw_km(kc, km, children, col, level)
59         '''
60
61     def indented_layout(self, layout, level):
62         indentpx = 16
63         if level == 0:
64             level = 0.0001   # Tweak so that a percentage of 0 won't split by half
65         indent = level * indentpx / bpy.context.region.width
66
67         split = layout.split(percentage=indent)
68         col = split.column()
69         col = split.column()
70         return col
71
72     def draw_km(self, display_keymaps, kc, km, children, layout, level):
73         km = km.active()
74
75         layout.context_pointer_set("keymap", km)
76
77         col = self.indented_layout(layout, level)
78
79         row = col.row()
80         row.prop(km, "show_expanded_children", text="", emboss=False)
81         row.label(text=km.name)
82
83         row.label()
84         row.label()
85
86         if km.is_modal:
87             row.label(text="", icon='LINKED')
88         if km.is_user_modified:
89             row.operator("wm.keymap_restore", text="Restore")
90         else:
91             row.label()
92
93         if km.show_expanded_children:
94             if children:
95                 # Put the Parent key map's entries in a 'global' sub-category
96                 # equal in hierarchy to the other children categories
97                 subcol = self.indented_layout(col, level + 1)
98                 subrow = subcol.row()
99                 subrow.prop(km, "show_expanded_items", text="", emboss=False)
100                 pgettext = bpy.app.translations.pgettext
101                 subrow.label(text=pgettext("%s (Global)") % km.name, translate=False)
102             else:
103                 km.show_expanded_items = True
104
105             # Key Map items
106             if km.show_expanded_items:
107                 for kmi in km.keymap_items:
108                     self.draw_kmi(display_keymaps, kc, km, kmi, col, level + 1)
109
110                 # "Add New" at end of keymap item list
111                 col = self.indented_layout(col, level + 1)
112                 subcol = col.split(percentage=0.2).column()
113                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
114
115             col.separator()
116
117             # Child key maps
118             if children:
119                 subcol = col.column()
120                 row = subcol.row()
121
122                 for entry in children:
123                     self.draw_entry(display_keymaps, entry, col, level + 1)
124
125     def draw_kmi(self, display_keymaps, kc, km, kmi, layout, level):
126         map_type = kmi.map_type
127
128         col = self.indented_layout(layout, level)
129
130         if kmi.show_expanded:
131             col = col.column(align=True)
132             box = col.box()
133         else:
134             box = col.column()
135
136         split = box.split(percentage=0.05)
137
138         # header bar
139         row = split.row()
140         row.prop(kmi, "show_expanded", text="", emboss=False)
141
142         row = split.row()
143         row.prop(kmi, "active", text="", emboss=False)
144
145         if km.is_modal:
146             row.prop(kmi, "propvalue", text="")
147         else:
148             row.label(text=kmi.name)
149
150         row = split.row()
151         row.prop(kmi, "map_type", text="")
152         if map_type == 'KEYBOARD':
153             row.prop(kmi, "type", text="", full_event=True)
154         elif map_type == 'MOUSE':
155             row.prop(kmi, "type", text="", full_event=True)
156         elif map_type == 'NDOF':
157             row.prop(kmi, "type", text="", full_event=True)
158         elif map_type == 'TWEAK':
159             subrow = row.row()
160             subrow.prop(kmi, "type", text="")
161             subrow.prop(kmi, "value", text="")
162         elif map_type == 'TIMER':
163             row.prop(kmi, "type", text="")
164         else:
165             row.label()
166
167         if (not kmi.is_user_defined) and kmi.is_user_modified:
168             row.operator("wm.keyitem_restore", text="", icon='BACK').item_id = kmi.id
169         else:
170             row.operator("wm.keyitem_remove", text="", icon='X').item_id = kmi.id
171
172         # Expanded, additional event settings
173         if kmi.show_expanded:
174             box = col.box()
175
176             split = box.split(percentage=0.4)
177             sub = split.row()
178
179             if km.is_modal:
180                 sub.prop(kmi, "propvalue", text="")
181             else:
182                 # One day...
183                 #~ sub.prop_search(kmi, "idname", bpy.context.window_manager, "operators_all", text="")
184                 sub.prop(kmi, "idname", text="")
185
186             if map_type not in {'TEXTINPUT', 'TIMER'}:
187                 sub = split.column()
188                 subrow = sub.row(align=True)
189
190                 if map_type == 'KEYBOARD':
191                     subrow.prop(kmi, "type", text="", event=True)
192                     subrow.prop(kmi, "value", text="")
193                 elif map_type in {'MOUSE', 'NDOF'}:
194                     subrow.prop(kmi, "type", text="")
195                     subrow.prop(kmi, "value", text="")
196
197                 subrow = sub.row()
198                 subrow.scale_x = 0.75
199                 subrow.prop(kmi, "any")
200                 subrow.prop(kmi, "shift")
201                 subrow.prop(kmi, "ctrl")
202                 subrow.prop(kmi, "alt")
203                 subrow.prop(kmi, "oskey", text="Cmd")
204                 subrow.prop(kmi, "key_modifier", text="", event=True)
205
206             # Operator properties
207             box.template_keymap_item_properties(kmi)
208
209             # Modal key maps attached to this operator
210             if not km.is_modal:
211                 kmm = kc.keymaps.find_modal(kmi.idname)
212                 if kmm:
213                     self.draw_km(display_keymaps, kc, kmm, None, layout, level + 1)
214                     layout.context_pointer_set("keymap", km)
215
216     def draw_filtered(self, display_keymaps, filter_text, layout):
217         for km, kc in display_keymaps:
218             km = km.active()
219             layout.context_pointer_set("keymap", km)
220
221             filtered_items = [kmi for kmi in km.keymap_items
222                               if (filter_text in kmi.idname.lower() or
223                                   filter_text in kmi.name.lower())]
224
225             if filtered_items:
226                 col = layout.column()
227
228                 row = col.row()
229                 row.label(text=km.name, icon='DOT')
230
231                 row.label()
232                 row.label()
233
234                 if km.is_user_modified:
235                     row.operator("wm.keymap_restore", text="Restore")
236                 else:
237                     row.label()
238
239                 for kmi in filtered_items:
240                     self.draw_kmi(display_keymaps, kc, km, kmi, col, 1)
241
242                 # "Add New" at end of keymap item list
243                 col = self.indented_layout(layout, 1)
244                 subcol = col.split(percentage=0.2).column()
245                 subcol.operator("wm.keyitem_add", text="Add New", icon='ZOOMIN')
246
247     def draw_hierarchy(self, display_keymaps, layout):
248         from bpy_extras import keyconfig_utils
249         for entry in keyconfig_utils.KM_HIERARCHY:
250             self.draw_entry(display_keymaps, entry, layout)
251
252     def draw_keymaps(self, context, layout):
253         from bpy_extras import keyconfig_utils
254
255         wm = context.window_manager
256         kc = wm.keyconfigs.user
257
258         col = layout.column()
259         sub = col.column()
260
261         subsplit = sub.split()
262         subcol = subsplit.column()
263
264         row = subcol.row(align=True)
265
266         #~ row.prop_search(wm.keyconfigs, "active", wm, "keyconfigs", text="Key Config:")
267         text = bpy.path.display_name(context.window_manager.keyconfigs.active.name)
268         if not text:
269             text = "Blender (default)"
270         row.menu("USERPREF_MT_keyconfigs", text=text)
271         row.operator("wm.keyconfig_preset_add", text="", icon='ZOOMIN')
272         row.operator("wm.keyconfig_preset_add", text="", icon='ZOOMOUT').remove_active = True
273
274         #~ layout.context_pointer_set("keyconfig", wm.keyconfigs.active)
275         #~ row.operator("wm.keyconfig_remove", text="", icon='X')
276
277         row.prop(context.space_data, "filter_text", icon='VIEWZOOM')
278
279         col.separator()
280
281         display_keymaps = keyconfig_utils.keyconfig_merge(kc, kc)
282         if context.space_data.filter_text != "":
283             filter_text = context.space_data.filter_text.lower()
284             self.draw_filtered(display_keymaps, filter_text, col)
285         else:
286             self.draw_hierarchy(display_keymaps, col)
287
288
289 if __name__ == "__main__":  # only for live edit.
290     bpy.utils.register_module(__name__)