{% import "partials/icons.html" as ic %} {% import "partials/fields.html" as f %} {# One lanelet constraint, rendered recursively. Children always nest in one list; how many a type takes comes from its spec, the same way a condition composition works. `slot` is the lanelet field this search chooses for -- a spawn, a goal, the lanelet a condition watches. It is what an add or a delete posts back, so the tree is the same whichever lanelet it is answering for. #} {% macro render(node, draft, slot, selected, document=none, inline_fields=false) %} {%- set spec = get_constraint_spec(node.type) -%}
{% if spec %}{{ spec.title }}{% else %}{{ node.type }}{% endif %} {% if not inline_fields %} {{ constraint_summary(node, spec) }} {% endif %}
{# Where the tree is the whole editor -- inside the map picker, with the inspector column behind it -- each node carries its own parameters, so nothing has to be selected somewhere the map is covering. #} {% if inline_fields and spec and spec.fields %}
{{ f.fields(spec.fields, node.params, document, '', draft) }}
{% endif %} {% if spec and spec.accepts_children %}
{% for child in node.constraints %} {{ render(child, draft, slot, selected, document, inline_fields) }} {% endfor %} {% if spec.max_children is none or node.constraints|length < spec.max_children %} {{ add_constraint(draft, slot, node.id) }} {% endif %}
{% endif %}
{% endmacro %} {% macro constraint_summary(node, spec) %} {%- if spec -%} {%- set parts = [] -%} {%- for field_spec in spec.fields -%} {%- set value = node.params.get(field_spec.name, field_spec.default) -%} {%- if value is not none and value != [] -%} {%- set shown = value|join(', ') if value is not string and value is iterable else value -%} {%- set _ = parts.append(shown ~ (' ' ~ field_spec.unit if field_spec.unit else '')) -%} {%- endif -%} {%- endfor -%} {{ parts|join(' ') }} {%- endif -%} {% endmacro %} {% macro add_constraint(draft, slot, parent_id='') %}
{{ ic.icon('plus', 11) }} constraint
{% endmacro %}