diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index cc234b1c..9568800e 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -2329,20 +2329,85 @@ function Emit-CompanionPanel { X "$indent" } -# Табличный addition (СтрокаПоиска/СостояниеПросмотра/УправлениеПоиском) с AdditionSource. -# Item = имя таблицы, Type фиксирован по виду; внутри — companion ContextMenu/ExtendedTooltip. +# Дополнения командной панели таблицы: тип DSL → XML-тег + AdditionSource.Type. +$script:additionTypeMap = [ordered]@{ + 'searchString' = @{ Tag = 'SearchStringAddition'; Type = 'SearchStringRepresentation'; Suffix = 'СтрокаПоиска' } + 'viewStatus' = @{ Tag = 'ViewStatusAddition'; Type = 'ViewStatusRepresentation'; Suffix = 'СостояниеПросмотра' } + 'searchControl' = @{ Tag = 'SearchControlAddition'; Type = 'SearchControl'; Suffix = 'УправлениеПоиском' } +} +# Синонимы типа дополнения (для override-карты additions и резолва тип-ключа). +$script:additionKeySynonyms = @{ + 'searchString' = @('SearchStringAddition','SearchStringRepresentation','строкаПоиска','отображениеСтрокиПоиска') + 'viewStatus' = @('ViewStatusAddition','ViewStatusRepresentation','состояниеПросмотра') + 'searchControl' = @('SearchControlAddition','SearchControl','управлениеПоиском') +} + +# HorizontalLocation: auto (дефолт, тег опускаем) / left / right; forgiving + рус.синонимы. +function Get-HLocation { + param($el) + $v = if ($el -and $el.PSObject.Properties['horizontalLocation']) { $el.horizontalLocation } else { $null } + if (-not $v) { return $null } + switch -Regex ("$v".ToLower()) { + '^(auto|авто)$' { return $null } # дефолт — не эмитим + '^(left|слева|лево)$' { return 'Left' } + '^(right|справа|право)$' { return 'Right' } + default { return "$v" } + } +} + +# Тело дополнения: AdditionSource + свойства (как у поля) + companions. $props может быть $null +# (стандартное дополнение без отклонений). Порядок 1С-толерантен (diff порядок-независим). +function Emit-AdditionBody { + param($props, [string]$source, [string]$srcType, [string]$addName, [string]$indent) + $inner = "$indent`t" + X "$inner" + X "$inner`t$source" + X "$inner`t$srcType" + X "$inner" + if ($props) { + if ($props.PSObject.Properties['title'] -and $props.title) { Emit-MLText -tag "Title" -text $props.title -indent $inner } + Emit-CommonFlags -el $props -indent $inner + if ($props.tooltip) { Emit-MLText -tag "ToolTip" -text $props.tooltip -indent $inner } + if ($props.tooltipRepresentation) { X "$inner$($props.tooltipRepresentation)" } + $hl = Get-HLocation $props; if ($hl) { X "$inner$hl" } + Emit-Layout -el $props -indent $inner + Emit-Appearance -el $props -indent $inner -profile 'field' + } + Emit-Companion -tag "ContextMenu" -name "${addName}КонтекстноеМеню" -indent $inner + Emit-Companion -tag "ExtendedTooltip" -name "${addName}РасширеннаяПодсказка" -indent $inner +} + +# Кастомное дополнение (тип-элемент в commandBar): source дефолтит в текущую таблицу. +function Emit-Addition { + param($el, [string]$name, [int]$id, [string]$typeKey, [string]$indent) + $map = $script:additionTypeMap[$typeKey] + $source = if ($el.source) { "$($el.source)" } elseif ($script:currentTableName) { $script:currentTableName } else { '' } + X "$indent<$($map.Tag) name=`"$name`" id=`"$id`">" + Emit-AdditionBody -props $el -source $source -srcType $map.Type -addName $name -indent $indent + X "$indent" +} + +# Стандартное табличное дополнение (авто-генерация на уровне таблицы). $override — объект отклонений +# из per-table карты additions (или $null = чистый дефолт). function Emit-TableAddition { - param([string]$tag, [string]$tableName, [string]$nameSuffix, [string]$srcType, [string]$indent) - $addName = "$tableName$nameSuffix" + param([string]$typeKey, [string]$tableName, [string]$indent, $override = $null) + $map = $script:additionTypeMap[$typeKey] + $addName = "$tableName$($map.Suffix)" $id = New-Id - X "$indent<$tag name=`"$addName`" id=`"$id`">" - X "$indent`t" - X "$indent`t`t$tableName" - X "$indent`t`t$srcType" - X "$indent`t" - Emit-Companion -tag "ContextMenu" -name "${addName}КонтекстноеМеню" -indent "$indent`t" - Emit-Companion -tag "ExtendedTooltip" -name "${addName}РасширеннаяПодсказка" -indent "$indent`t" - X "$indent" + X "$indent<$($map.Tag) name=`"$addName`" id=`"$id`">" + Emit-AdditionBody -props $override -source $tableName -srcType $map.Type -addName $addName -indent $indent + X "$indent" +} + +# Прочитать override-объект для типа дополнения из per-table карты additions (с синонимами). +function Get-AdditionOverride { + param($additions, [string]$typeKey) + if ($null -eq $additions) { return $null } + foreach ($k in @($typeKey) + $script:additionKeySynonyms[$typeKey]) { + $p = $additions.PSObject.Properties[$k] + if ($p) { return $p.Value } + } + return $null } function Emit-Element { @@ -2392,6 +2457,20 @@ function Emit-Element { "Кнопка" = "button" "Popup" = "popup" "ВсплывающееМеню" = "popup" + # Дополнения командной панели таблицы (тип-как-ключ) — forgiving: XML-тег/Type/рус.имя → канон + "SearchStringAddition" = "searchString" + "SearchStringRepresentation" = "searchString" + "строкаПоиска" = "searchString" + "отображениеСтрокиПоиска" = "searchString" + "Отображение строки поиска" = "searchString" + "ViewStatusAddition" = "viewStatus" + "ViewStatusRepresentation" = "viewStatus" + "состояниеПросмотра" = "viewStatus" + "Состояние просмотра" = "viewStatus" + "SearchControlAddition" = "searchControl" + "SearchControl" = "searchControl" + "управлениеПоиском" = "searchControl" + "Управление поиском" = "searchControl" } foreach ($pair in $synonyms.GetEnumerator()) { if ($null -ne $el.PSObject.Properties[$pair.Key] -and $null -eq $el.PSObject.Properties[$pair.Value]) { @@ -2410,7 +2489,7 @@ function Emit-Element { # у popup/button/cmdBar. Тип-ключ владельца (popup/button/…) должен выиграть. # pages/page ПЕРЕД group: у Page/Pages ключ 'group' — это направление раскладки детей # (Horizontal), а не тип UsualGroup. Реальная UsualGroup ключа page/pages не несёт. - foreach ($key in @("columnGroup","buttonGroup","pages","page","group","input","check","radio","label","labelField","table","button","calendar","cmdBar","popup","picField","picture")) { + foreach ($key in @("columnGroup","buttonGroup","pages","page","group","input","check","radio","label","labelField","table","button","calendar","cmdBar","popup","searchString","viewStatus","searchControl","picField","picture")) { if ($el.$key -ne $null) { $typeKey = $key break @@ -2484,6 +2563,8 @@ function Emit-Element { "autofill"=1 # AutoCommandBar-маркер (autofill heuristic) на элементе/таблице "autoCmdBar"=1 + # дополнения командной панели таблицы (тип-ключи + свойства) + "searchString"=1;"viewStatus"=1;"searchControl"=1;"source"=1;"horizontalLocation"=1;"additions"=1 } # Оформление (цвета/шрифты/граница) — авто-регистрация из самих структур, чтобы allowlist # не дрейфовал при добавлении новых ключей/синонимов. Канонические + forgiving-синонимы. @@ -2514,6 +2595,9 @@ function Emit-Element { "page" { Emit-Page -el $el -name $name -id $id -indent $indent } "button" { Emit-Button -el $el -name $name -id $id -indent $indent -inCmdBar $inCmdBar } "picture" { Emit-PictureDecoration -el $el -name $name -id $id -indent $indent } + "searchString" { Emit-Addition -el $el -name $name -typeKey "searchString" -id $id -indent $indent } + "viewStatus" { Emit-Addition -el $el -name $name -typeKey "viewStatus" -id $id -indent $indent } + "searchControl" { Emit-Addition -el $el -name $name -typeKey "searchControl" -id $id -indent $indent } "picField" { Emit-PictureField -el $el -name $name -id $id -indent $indent } "calendar" { Emit-Calendar -el $el -name $name -id $id -indent $indent } "cmdBar" { Emit-CommandBar -el $el -name $name -id $id -indent $indent } @@ -3529,6 +3613,7 @@ function Emit-DynListTableBlock { function Emit-Table { param($el, [string]$name, [int]$id, [string]$indent) + $script:currentTableName = $name # дефолт source для кастомных дополнений в commandBar X "$indent" $inner = "$indent`t" @@ -3606,9 +3691,10 @@ function Emit-Table { Emit-Companion -tag "AutoCommandBar" -name "${name}КоманднаяПанель" -indent $inner } Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner -content $el.extendedTooltip - Emit-TableAddition -tag "SearchStringAddition" -tableName $name -nameSuffix "СтрокаПоиска" -srcType "SearchStringRepresentation" -indent $inner - Emit-TableAddition -tag "ViewStatusAddition" -tableName $name -nameSuffix "СостояниеПросмотра" -srcType "ViewStatusRepresentation" -indent $inner - Emit-TableAddition -tag "SearchControlAddition" -tableName $name -nameSuffix "УправлениеПоиском" -srcType "SearchControl" -indent $inner + $adds = $el.additions + Emit-TableAddition -typeKey 'searchString' -tableName $name -indent $inner -override (Get-AdditionOverride $adds 'searchString') + Emit-TableAddition -typeKey 'viewStatus' -tableName $name -indent $inner -override (Get-AdditionOverride $adds 'viewStatus') + Emit-TableAddition -typeKey 'searchControl' -tableName $name -indent $inner -override (Get-AdditionOverride $adds 'searchControl') # Columns if ($el.columns -and $el.columns.Count -gt 0) { diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 7bf3b570..7ea65a06 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1811,6 +1811,8 @@ KNOWN_KEYS = { "userSettingsGroup", "rowsPicture", # AutoCommandBar-маркер (autofill heuristic) на элементе/таблице "autoCmdBar", + # дополнения командной панели таблицы (тип-ключи + свойства) + "searchString", "viewStatus", "searchControl", "source", "horizontalLocation", "additions", } # picture/picField — НИЗКИЙ приоритет: 'picture' это и тип (PictureDecoration), и свойство-иконка @@ -1818,7 +1820,7 @@ KNOWN_KEYS = { # pages/page ПЕРЕД group: у Page/Pages ключ 'group' — это направление раскладки детей # (Horizontal), а не тип UsualGroup. Реальная UsualGroup ключа page/pages не несёт. TYPE_KEYS = ["columnGroup", "buttonGroup", "pages", "page", "group", "input", "check", "radio", "label", "labelField", "table", - "button", "calendar", "cmdBar", "popup", "picField", "picture"] + "button", "calendar", "cmdBar", "popup", "searchString", "viewStatus", "searchControl", "picField", "picture"] # Synonyms: model often writes XML name or Russian (ПолеПереключателя/RadioButtonField → radio) ELEMENT_TYPE_SYNONYMS = { @@ -1857,6 +1859,20 @@ ELEMENT_TYPE_SYNONYMS = { "Кнопка": "button", "Popup": "popup", "ВсплывающееМеню": "popup", + # дополнения командной панели таблицы — forgiving: XML-тег/Type/рус.имя → канон + "SearchStringAddition": "searchString", + "SearchStringRepresentation": "searchString", + "строкаПоиска": "searchString", + "отображениеСтрокиПоиска": "searchString", + "Отображение строки поиска": "searchString", + "ViewStatusAddition": "viewStatus", + "ViewStatusRepresentation": "viewStatus", + "состояниеПросмотра": "viewStatus", + "Состояние просмотра": "viewStatus", + "SearchControlAddition": "searchControl", + "SearchControl": "searchControl", + "управлениеПоиском": "searchControl", + "Управление поиском": "searchControl", } # Тип-синонимы, применяемые ТОЛЬКО к строковому значению (имя элемента); объект/массив @@ -2324,18 +2340,89 @@ def emit_companion_panel(lines, tag, name, indent, panel): lines.append(f'{indent}') -def emit_table_addition(lines, tag, table_name, name_suffix, src_type, indent): - # Табличный addition с AdditionSource (Item = имя таблицы, Type фиксирован). - add_name = f'{table_name}{name_suffix}' +# Дополнения командной панели таблицы: тип DSL → XML-тег + AdditionSource.Type + суффикс имени. +ADDITION_TYPE_MAP = { + 'searchString': {'tag': 'SearchStringAddition', 'type': 'SearchStringRepresentation', 'suffix': 'СтрокаПоиска'}, + 'viewStatus': {'tag': 'ViewStatusAddition', 'type': 'ViewStatusRepresentation', 'suffix': 'СостояниеПросмотра'}, + 'searchControl': {'tag': 'SearchControlAddition', 'type': 'SearchControl', 'suffix': 'УправлениеПоиском'}, +} +ADDITION_KEY_SYNONYMS = { + 'searchString': ['SearchStringAddition', 'SearchStringRepresentation', 'строкаПоиска', 'отображениеСтрокиПоиска'], + 'viewStatus': ['ViewStatusAddition', 'ViewStatusRepresentation', 'состояниеПросмотра'], + 'searchControl': ['SearchControlAddition', 'SearchControl', 'управлениеПоиском'], +} +# Имя текущей таблицы — дефолт source для кастомных дополнений в commandBar. +_current_table_name = {'name': None} + + +def get_hlocation(el): + # HorizontalLocation: auto (дефолт, опускаем) / left / right; forgiving + рус. + if not isinstance(el, dict): + return None + v = el.get('horizontalLocation') + if not v: + return None + s = str(v).lower() + if s in ('auto', 'авто'): + return None + if s in ('left', 'слева', 'лево'): + return 'Left' + if s in ('right', 'справа', 'право'): + return 'Right' + return str(v) + + +def emit_addition_body(lines, props, source, src_type, add_name, indent): + # Тело дополнения: AdditionSource + свойства (как у поля) + companions. props может быть None. + inner = f'{indent}\t' + lines.append(f'{inner}') + lines.append(f'{inner}\t{source}') + lines.append(f'{inner}\t{src_type}') + lines.append(f'{inner}') + if props: + if props.get('title'): + emit_mltext(lines, inner, 'Title', props['title']) + emit_common_flags(lines, props, inner) + if props.get('tooltip'): + emit_mltext(lines, inner, 'ToolTip', props['tooltip']) + if props.get('tooltipRepresentation'): + lines.append(f'{inner}{props["tooltipRepresentation"]}') + hl = get_hlocation(props) + if hl: + lines.append(f'{inner}{hl}') + emit_layout(lines, props, inner) + emit_appearance(lines, props, inner, 'field') + emit_companion(lines, 'ContextMenu', f'{add_name}КонтекстноеМеню', inner) + emit_companion(lines, 'ExtendedTooltip', f'{add_name}РасширеннаяПодсказка', inner) + + +def emit_addition(lines, el, name, eid, type_key, indent): + # Кастомное дополнение (тип-элемент в commandBar): source дефолтит в текущую таблицу. + m = ADDITION_TYPE_MAP[type_key] + source = el.get('source') or _current_table_name['name'] or '' + lines.append(f'{indent}<{m["tag"]} name="{name}" id="{eid}">') + emit_addition_body(lines, el, source, m['type'], name, indent) + lines.append(f'{indent}') + + +def emit_table_addition(lines, type_key, table_name, indent, override=None): + # Стандартное табличное дополнение (авто-генерация). override — объект отклонений из карты additions. + m = ADDITION_TYPE_MAP[type_key] + add_name = f'{table_name}{m["suffix"]}' aid = new_id() - lines.append(f'{indent}<{tag} name="{add_name}" id="{aid}">') - lines.append(f'{indent}\t') - lines.append(f'{indent}\t\t{table_name}') - lines.append(f'{indent}\t\t{src_type}') - lines.append(f'{indent}\t') - emit_companion(lines, 'ContextMenu', f'{add_name}КонтекстноеМеню', f'{indent}\t') - emit_companion(lines, 'ExtendedTooltip', f'{add_name}РасширеннаяПодсказка', f'{indent}\t') - lines.append(f'{indent}') + lines.append(f'{indent}<{m["tag"]} name="{add_name}" id="{aid}">') + emit_addition_body(lines, override, table_name, m['type'], add_name, indent) + lines.append(f'{indent}') + + +def get_addition_override(additions, type_key): + # Прочитать override-объект для типа из per-table карты additions (с синонимами). + if not isinstance(additions, dict): + return None + for k in [type_key] + ADDITION_KEY_SYNONYMS[type_key]: + if k in additions: + return additions[k] + return None # Role-adjustable boolean (xr:Common + 0..N xr:Value name="Role.X"). @@ -2866,6 +2953,9 @@ def emit_element(lines, el, indent, in_cmd_bar=False): 'calendar': emit_calendar, 'cmdBar': emit_command_bar, 'popup': emit_popup, + 'searchString': lambda lines, el, name, eid, indent: emit_addition(lines, el, name, eid, 'searchString', indent), + 'viewStatus': lambda lines, el, name, eid, indent: emit_addition(lines, el, name, eid, 'viewStatus', indent), + 'searchControl': lambda lines, el, name, eid, indent: emit_addition(lines, el, name, eid, 'searchControl', indent), } emitter = emitters.get(type_key) @@ -3240,6 +3330,7 @@ def emit_dynlist_table_block(lines, el, indent): def emit_table(lines, el, name, eid, indent): + _current_table_name['name'] = name # дефолт source для кастомных дополнений в commandBar lines.append(f'{indent}
') inner = f'{indent}\t' @@ -3331,9 +3422,10 @@ def emit_table(lines, el, name, eid, indent): else: emit_companion(lines, 'AutoCommandBar', f'{name}\u041a\u043e\u043c\u0430\u043d\u0434\u043d\u0430\u044f\u041f\u0430\u043d\u0435\u043b\u044c', inner) emit_companion(lines, 'ExtendedTooltip', f'{name}\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u043d\u0430\u044f\u041f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430', inner, el.get('extendedTooltip')) - emit_table_addition(lines, 'SearchStringAddition', name, '\u0421\u0442\u0440\u043e\u043a\u0430\u041f\u043e\u0438\u0441\u043a\u0430', 'SearchStringRepresentation', inner) - emit_table_addition(lines, 'ViewStatusAddition', name, '\u0421\u043e\u0441\u0442\u043e\u044f\u043d\u0438\u0435\u041f\u0440\u043e\u0441\u043c\u043e\u0442\u0440\u0430', 'ViewStatusRepresentation', inner) - emit_table_addition(lines, 'SearchControlAddition', name, '\u0423\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u0435\u041f\u043e\u0438\u0441\u043a\u043e\u043c', 'SearchControl', inner) + adds = el.get('additions') + emit_table_addition(lines, 'searchString', name, inner, get_addition_override(adds, 'searchString')) + emit_table_addition(lines, 'viewStatus', name, inner, get_addition_override(adds, 'viewStatus')) + emit_table_addition(lines, 'searchControl', name, inner, get_addition_override(adds, 'searchControl')) # Columns if el.get('columns') and len(el['columns']) > 0: diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index 6ac1cd1a..b49cae83 100644 --- a/.claude/skills/form-decompile/scripts/form-decompile.ps1 +++ b/.claude/skills/form-decompile/scripts/form-decompile.ps1 @@ -1,4 +1,4 @@ -# form-decompile v0.50 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.51 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -214,7 +214,9 @@ function ConvertTo-CompactJson { # --- 2. Helpers --- # Companion-элементы (авто-генерируемые компилятором) — пропускаем при обходе детей. -$COMPANION_TAGS = @('ContextMenu','ExtendedTooltip','AutoCommandBar','SearchStringAddition','ViewStatusAddition','SearchControlAddition') +# Дополнения (Search*/ViewStatus) БОЛЬШЕ не companion — декомпилируются как тип-элементы +# (кастомные в AutoCommandBar/ChildItems → commandBar.children; стандартные на уровне таблицы → карта additions). +$COMPANION_TAGS = @('ContextMenu','ExtendedTooltip','AutoCommandBar') # Извлечь мультиязычный Title/Presentation → string (ru) или ordered hash {ru,en,...} function Get-LangText { @@ -1114,7 +1116,8 @@ $ELEMENT_KEY = @{ 'UsualGroup'='group'; 'ColumnGroup'='columnGroup'; 'ButtonGroup'='buttonGroup'; 'InputField'='input'; 'CheckBoxField'='check'; 'RadioButtonField'='radio'; 'LabelDecoration'='label'; 'LabelField'='labelField'; 'PictureDecoration'='picture'; 'PictureField'='picField'; 'CalendarField'='calendar'; - 'Table'='table'; 'Pages'='pages'; 'Page'='page'; 'Button'='button'; 'CommandBar'='cmdBar'; 'Popup'='popup' + 'Table'='table'; 'Pages'='pages'; 'Page'='page'; 'Button'='button'; 'CommandBar'='cmdBar'; 'Popup'='popup'; + 'SearchStringAddition'='searchString'; 'ViewStatusAddition'='viewStatus'; 'SearchControlAddition'='searchControl' } function Decompile-Children { @@ -1256,6 +1259,37 @@ function Add-FormatProps { $efmt = $node.SelectSingleNode("lf:EditFormat", $ns); if ($efmt) { $t = Get-LangText $efmt; if ($null -ne $t -and $t -ne '') { $obj['editFormat'] = $t } } } +# Ядро дополнения: source + общие свойства (Add-CommonProps) + horizontalLocation. +# Layout (Add-Layout) добавляется ОТДЕЛЬНО (в Decompile-Element — пост-обработкой, в standalone — явно). +function Add-AdditionCore { + param($obj, $node, [string]$elName) + $src = $node.SelectSingleNode("lf:AdditionSource/lf:Item", $ns); if ($src) { $obj['source'] = $src.InnerText } + Add-CommonProps $obj $node $elName + $hl = Get-Child $node 'HorizontalLocation'; if ($hl) { $obj['horizontalLocation'] = $hl.ToLower() } +} + +# Стандартные дополнения уровня таблицы (прямые дети
): извлечь ТОЛЬКО отклонения в карту +# { тип: {свойства} }. Имя (=tableName+suffix) и source (=tableName) — дефолтные, опускаем. +function Decompile-TableAdditions { + param($tableNode, [string]$tableName) + $tagToKey = @{ 'SearchStringAddition'='searchString'; 'ViewStatusAddition'='viewStatus'; 'SearchControlAddition'='searchControl' } + $map = [ordered]@{} + foreach ($child in $tableNode.ChildNodes) { + if ($child.NodeType -ne [System.Xml.XmlNodeType]::Element) { continue } + if (-not $tagToKey.ContainsKey($child.LocalName)) { continue } + $key = $tagToKey[$child.LocalName] + $nm = $child.GetAttribute("name") + $o = [ordered]@{}; $o[$key] = $nm + Add-AdditionCore $o $child $nm + Add-Layout $o $child + $o.Remove($key) # имя авто + if ($o.Contains('source') -and $o['source'] -eq $tableName) { $o.Remove('source') } # source=таблица дефолт + if ($o.Count -gt 0) { $map[$key] = $o } + } + if ($map.Count -gt 0) { return $map } + return $null +} + function Decompile-Element { param($node) $tag = $node.LocalName @@ -1410,7 +1444,13 @@ function Decompile-Element { if ((Get-Child $node 'Header') -eq 'false') { $obj['header'] = $false } if ((Get-Child $node 'Footer') -eq 'true') { $obj['footer'] = $true } $htr = Get-Child $node 'HeightInTableRows'; if ($htr) { $obj['height'] = [int]$htr } - $cbl = Get-Child $node 'CommandBarLocation'; if ($cbl) { $obj['commandBarLocation'] = $cbl } + # CommandBarLocation: для дин-список-таблицы компилятор авто-инжектит "None" → инвертируем + # (нет тега → суппресс-маркер ""; "None" → опускаем = авто-дефолт; иначе → захват). + $cbl = Get-Child $node 'CommandBarLocation' + if (Has-Child $node 'UpdateOnDataChange') { + if ($null -eq $cbl) { $obj['commandBarLocation'] = '' } + elseif ($cbl -ne 'None') { $obj['commandBarLocation'] = $cbl } + } elseif ($cbl) { $obj['commandBarLocation'] = $cbl } $ssl = Get-Child $node 'SearchStringLocation'; if ($ssl) { $obj['searchStringLocation'] = $ssl } $vsl = Get-Child $node 'ViewStatusLocation'; if ($vsl) { $obj['viewStatusLocation'] = $vsl } $scl = Get-Child $node 'SearchControlLocation'; if ($scl) { $obj['searchControlLocation'] = $scl } @@ -1447,6 +1487,9 @@ function Decompile-Element { } $cols = Decompile-Children $node if ($cols) { $obj['columns'] = $cols } + # Стандартные дополнения уровня таблицы (прямые дети) → карта отклонений additions + $addMap = Decompile-TableAdditions $node $name + if ($addMap) { $obj['additions'] = $addMap } } 'Pages' { $obj[$key] = $name @@ -1510,6 +1553,9 @@ function Decompile-Element { $kids = Decompile-Children $node if ($kids) { $obj['children'] = $kids } } + 'SearchStringAddition' { $obj[$key] = $name; Add-AdditionCore $obj $node $name } + 'ViewStatusAddition' { $obj[$key] = $name; Add-AdditionCore $obj $node $name } + 'SearchControlAddition' { $obj[$key] = $name; Add-AdditionCore $obj $node $name } } # title: "" — подавление авто-вывода: для типов, где компилятор вывел бы # заголовок из имени, а в оригинале отсутствует. diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index 2fbb32d7..b47d6c37 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -511,6 +511,30 @@ companion-панели с собственным контентом. Оба не | `viewStatusLocation` | string | `None`, `Top`, `Bottom`, `Auto` | | `searchControlLocation` | string | `None`, `Top`, `Bottom`, `Auto` | | `excludedCommands` | string[] | Исключённые стандартные команды таблицы (`Add`, `Delete`, `MoveUp`, `SortListAsc`, …) → `<CommandSet>` | +| `additions` | object | Отклонения стандартных дополнений командной панели (см. ниже) | + +> `commandBarLocation` у **дин-список-таблицы** компилятор авто-подставляет `None`. Чтобы оставить тег пустым (платформа не написала его) — задайте `commandBarLocation: ""` (суппресс-маркер); декомпилятор так и делает. + +##### Дополнения командной панели (поиск / состояние / управление) + +Дополнения — «представления» встроенного поиска таблицы: `searchString` (отображение строки поиска), `viewStatus` (состояние просмотра), `searchControl` (управление поиском). Это полноценные элементы (полный набор свойств поля). Две позиции: + +**(1) Стандартные** (платформа авто-генерит на уровне таблицы) — указываются ТОЛЬКО отклонения, через карту `additions` (ключ = тип): +```json +{ "table": "Список", "additions": { "viewStatus": { "horizontalLocation": "left" } } } +``` + +**(2) Кастомные** (размещённые в командной панели) — обычные элементы в `commandBar`: +```json +{ "table": "Список", "commandBar": [ + { "searchString": "ПоискСписка", "source": "Список", "width": 15, "horizontalStretch": true } +]} +``` + +- Тип-ключ: `searchString` / `viewStatus` / `searchControl` (forgiving: XML-тег `SearchStringAddition`, `<Type>` `SearchStringRepresentation`, рус. `строкаПоиска`/«Отображение строки поиска»). +- `source` → `AdditionSource.Item`; **дефолт = имя родительской таблицы**. +- `horizontalLocation`: `auto` (дефолт) / `left` / `right` (+ рус. `слева`/`справа`). Применимо и к обычным элементам командных панелей. +- Прочие свойства (`title`, `visible`, `userVisible`, `enabled`, `tooltip`, оформление, `width`/`maxWidth`/`autoMaxWidth`/`horizontalStretch`/`groupHorizontalAlign`/…) — как у поля. ##### Таблица динамического списка diff --git a/tests/skills/cases/form-compile/dynamic-list-form.json b/tests/skills/cases/form-compile/dynamic-list-form.json index 5d80f9e1..f3e58d45 100644 --- a/tests/skills/cases/form-compile/dynamic-list-form.json +++ b/tests/skills/cases/form-compile/dynamic-list-form.json @@ -24,10 +24,15 @@ } } ], "elements": [ - { "table": "Список", "path": "Список", "columns": [ - { "input": "Код", "path": "Список.Code" }, - { "input": "Наименование", "path": "Список.Description" } - ]} + { "table": "Список", "path": "Список", + "additions": { "viewStatus": { "horizontalLocation": "left" } }, + "commandBar": [ + { "searchString": "ПоискСписка", "source": "Список", "width": 15, "horizontalStretch": true } + ], + "columns": [ + { "input": "Код", "path": "Список.Code" }, + { "input": "Наименование", "path": "Список.Description" } + ]} ] } } diff --git a/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml index 86620112..333ca92a 100644 --- a/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml +++ b/tests/skills/cases/form-compile/snapshots/dynamic-list-form/Catalogs/Товары/Forms/ФормаСписка/Ext/Form.xml @@ -29,49 +29,61 @@ <AllowGettingCurrentRowURL>true</AllowGettingCurrentRowURL> <ContextMenu name="СписокКонтекстноеМеню" id="2"/> <AutoCommandBar name="СписокКоманднаяПанель" id="3"> - <Autofill>false</Autofill> + <ChildItems> + <SearchStringAddition name="ПоискСписка" id="4"> + <AdditionSource> + <Item>Список</Item> + <Type>SearchStringRepresentation</Type> + </AdditionSource> + <Width>15</Width> + <HorizontalStretch>true</HorizontalStretch> + <ContextMenu name="ПоискСпискаКонтекстноеМеню" id="5"/> + <ExtendedTooltip name="ПоискСпискаРасширеннаяПодсказка" id="6"/> + </SearchStringAddition> + </ChildItems> </AutoCommandBar> - <ExtendedTooltip name="СписокРасширеннаяПодсказка" id="4"/> - <SearchStringAddition name="СписокСтрокаПоиска" id="5"> + <ExtendedTooltip name="СписокРасширеннаяПодсказка" id="7"/> + <SearchStringAddition name="СписокСтрокаПоиска" id="8"> <AdditionSource> <Item>Список</Item> <Type>SearchStringRepresentation</Type> </AdditionSource> - <ContextMenu name="СписокСтрокаПоискаКонтекстноеМеню" id="6"/> - <ExtendedTooltip name="СписокСтрокаПоискаРасширеннаяПодсказка" id="7"/> + <ContextMenu name="СписокСтрокаПоискаКонтекстноеМеню" id="9"/> + <ExtendedTooltip name="СписокСтрокаПоискаРасширеннаяПодсказка" id="10"/> </SearchStringAddition> - <ViewStatusAddition name="СписокСостояниеПросмотра" id="8"> + <ViewStatusAddition name="СписокСостояниеПросмотра" id="11"> <AdditionSource> <Item>Список</Item> <Type>ViewStatusRepresentation</Type> </AdditionSource> - <ContextMenu name="СписокСостояниеПросмотраКонтекстноеМеню" id="9"/> - <ExtendedTooltip name="СписокСостояниеПросмотраРасширеннаяПодсказка" id="10"/> + <HorizontalLocation>Left</HorizontalLocation> + <ContextMenu name="СписокСостояниеПросмотраКонтекстноеМеню" id="12"/> + <ExtendedTooltip name="СписокСостояниеПросмотраРасширеннаяПодсказка" id="13"/> </ViewStatusAddition> - <SearchControlAddition name="СписокУправлениеПоиском" id="11"> + <SearchControlAddition name="СписокУправлениеПоиском" id="14"> <AdditionSource> <Item>Список</Item> <Type>SearchControl</Type> </AdditionSource> - <ContextMenu name="СписокУправлениеПоискомКонтекстноеМеню" id="12"/> - <ExtendedTooltip name="СписокУправлениеПоискомРасширеннаяПодсказка" id="13"/> + <ContextMenu name="СписокУправлениеПоискомКонтекстноеМеню" id="15"/> + <ExtendedTooltip name="СписокУправлениеПоискомРасширеннаяПодсказка" id="16"/> </SearchControlAddition> <ChildItems> - <InputField name="Код" id="14"> + <InputField name="Код" id="17"> <DataPath>Список.Code</DataPath> - <ContextMenu name="КодКонтекстноеМеню" id="15"/> - <ExtendedTooltip name="КодРасширеннаяПодсказка" id="16"/> + <ContextMenu name="КодКонтекстноеМеню" id="18"/> + <ExtendedTooltip name="КодРасширеннаяПодсказка" id="19"/> </InputField> - <InputField name="Наименование" id="17"> + <InputField name="Наименование" id="20"> <DataPath>Список.Description</DataPath> - <ContextMenu name="НаименованиеКонтекстноеМеню" id="18"/> - <ExtendedTooltip name="НаименованиеРасширеннаяПодсказка" id="19"/> + <ContextMenu name="НаименованиеКонтекстноеМеню" id="21"/> + <ExtendedTooltip name="НаименованиеРасширеннаяПодсказка" id="22"/> </InputField> </ChildItems> </Table> </ChildItems> <Attributes> - <Attribute name="Список" id="20"> + <Attribute name="Список" id="23"> <Type> <v8:Type>cfg:DynamicList</v8:Type> </Type>