UI: support tool generators (no visible change)

This allows toolbar definitions to dynamically generate tools,
needed for generating a tool list from brushes for eg.
This commit is contained in:
Campbell Barton
2018-04-29 12:26:00 +02:00
parent e017876f78
commit f4ba7667dc
2 changed files with 79 additions and 65 deletions

View File

@@ -58,6 +58,10 @@ def _keymap_fn_from_seq(keymap_data):
return keymap_fn
def _item_is_fn(item):
return (not (type(item) is type and issubclass(item, ToolDef)) and callable(item))
class ToolDef:
"""
Tool definition,
@@ -137,14 +141,23 @@ class ToolSelectPanelHelper:
@staticmethod
def _tools_flatten(tools):
"""
Flattens, skips None and calls generators.
"""
for item in tools:
if item is not None:
if type(item) is tuple:
for sub_item in item:
if sub_item is not None:
yield sub_item
if _item_is_fn(sub_item):
yield from sub_item(context)
else:
yield sub_item
else:
yield item
if _item_is_fn(item):
yield from item(context)
else:
yield item
@classmethod
def _tool_vars_from_def(cls, item, context_mode):
@@ -220,7 +233,8 @@ class ToolSelectPanelHelper:
if item_parent is None:
continue
for item in item_parent if (type(item_parent) is tuple) else (item_parent,):
if item is None:
# skip None or generator function
if item is None or _item_is_fn(item):
continue
keymap_data = item.keymap
if keymap_data is not None:
@@ -341,68 +355,63 @@ class ToolSelectPanelHelper:
# Start iteration
ui_gen.send(None)
for tool_items in self.tools_from_context(context):
if tool_items:
for item in tool_items:
if item is None:
ui_gen.send(True)
continue
if type(item) is tuple:
is_active = False
i = 0
for i, sub_item in enumerate(item):
if sub_item is None:
continue
tool_def, icon_name = self._tool_vars_from_def(sub_item, context_mode)
is_active = (tool_def == tool_def_active)
if is_active:
index = i
break
del i, sub_item
for item in self.tools_from_context(context):
if item is None:
ui_gen.send(True)
continue
if type(item) is tuple:
is_active = False
i = 0
for i, sub_item in enumerate(item):
if sub_item is None:
continue
tool_def, icon_name = self._tool_vars_from_def(sub_item, context_mode)
is_active = (tool_def == tool_def_active)
if is_active:
# not ideal, write this every time :S
self._tool_group_active[item[0].text] = index
else:
index = self._tool_group_active.get(item[0].text, 0)
index = i
break
del i, sub_item
item = item[index]
use_menu = True
if is_active:
# not ideal, write this every time :S
self._tool_group_active[item[0].text] = index
else:
index = -1
use_menu = False
index = self._tool_group_active.get(item[0].text, 0)
tool_def, icon_name = self._tool_vars_from_def(item, context_mode)
is_active = (tool_def == tool_def_active)
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
item = item[index]
use_menu = True
else:
index = -1
use_menu = False
sub = ui_gen.send(False)
tool_def, icon_name = self._tool_vars_from_def(item, context_mode)
is_active = (tool_def == tool_def_active)
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
if use_menu:
props = sub.operator_menu_hold(
"wm.tool_set",
text=item.text if show_text else "",
depress=is_active,
menu="WM_MT_toolsystem_submenu",
icon_value=icon_value,
)
else:
props = sub.operator(
"wm.tool_set",
text=item.text if show_text else "",
depress=is_active,
icon_value=icon_value,
)
props.keymap = tool_def[0] or ""
props.manipulator_group = tool_def[1] or ""
props.index = index
sub = ui_gen.send(False)
if use_menu:
props = sub.operator_menu_hold(
"wm.tool_set",
text=item.text if show_text else "",
depress=is_active,
menu="WM_MT_toolsystem_submenu",
icon_value=icon_value,
)
else:
props = sub.operator(
"wm.tool_set",
text=item.text if show_text else "",
depress=is_active,
icon_value=icon_value,
)
props.keymap = tool_def[0] or ""
props.manipulator_group = tool_def[1] or ""
props.index = index
# Signal to finish any remaining layout edits.
ui_gen.send(None)
def tools_from_context(cls, context):
return (cls._tools[None], cls._tools.get(context.mode, ()))
@staticmethod
def _active_tool(context, with_icon=False):
"""
@@ -420,15 +429,14 @@ class ToolSelectPanelHelper:
tool_def_active, index_active = ToolSelectPanelHelper._tool_vars_from_active_with_index(context)
context_mode = context.mode
for tool_items in cls.tools_from_context(context):
for item in cls._tools_flatten(tool_items):
tool_def, icon_name = cls._tool_vars_from_def(item, context_mode)
if (tool_def == tool_def_active):
if with_icon:
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
else:
icon_value = 0
return (item, icon_value)
for item in cls._tools_flatten(cls.tools_from_context(context)):
tool_def, icon_name = cls._tool_vars_from_def(item, context_mode)
if (tool_def == tool_def_active):
if with_icon:
icon_value = ToolSelectPanelHelper._icon_value_from_icon_handle(icon_name)
else:
icon_value = 0
return (item, icon_value)
return None, 0
@staticmethod

View File

@@ -414,7 +414,13 @@ class VIEW3D_PT_tools_active(ToolSelectPanelHelper, Panel):
@classmethod
def tools_from_context(cls, context):
return (cls._tools[None], cls._tools.get(context.mode, ()))
for tools in (cls._tools[None], cls._tools.get(context.mode, ())):
for item in tools:
if not (type(item) is type and issubclass(item, ToolDef)) and callable(item):
yield from item(context)
else:
yield item
@classmethod
def tools_all(cls):