diff --git a/.claude/skills/form-compile/scripts/form-compile.ps1 b/.claude/skills/form-compile/scripts/form-compile.ps1 index d2981494..44f1c497 100644 --- a/.claude/skills/form-compile/scripts/form-compile.ps1 +++ b/.claude/skills/form-compile/scripts/form-compile.ps1 @@ -1,4 +1,4 @@ -# form-compile v1.23 — Compile 1C managed form from JSON or object metadata +# form-compile v1.24 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills param( [string]$JsonPath, @@ -1878,7 +1878,7 @@ function Emit-Element { $typeKey = $null $xmlTag = $null - foreach ($key in @("columnGroup","group","input","check","radio","label","labelField","table","pages","page","button","picture","picField","calendar","cmdBar","popup")) { + foreach ($key in @("columnGroup","buttonGroup","group","input","check","radio","label","labelField","table","pages","page","button","picture","picField","calendar","cmdBar","popup")) { if ($el.$key -ne $null) { $typeKey = $key break @@ -1893,7 +1893,7 @@ function Emit-Element { # Validate known keys — warn about typos and unknown properties $knownKeys = @{ # type keys - "group"=1;"columnGroup"=1;"input"=1;"check"=1;"radio"=1;"label"=1;"labelField"=1;"table"=1;"pages"=1;"page"=1 + "group"=1;"columnGroup"=1;"buttonGroup"=1;"input"=1;"check"=1;"radio"=1;"label"=1;"labelField"=1;"table"=1;"pages"=1;"page"=1 "button"=1;"picture"=1;"picField"=1;"calendar"=1;"cmdBar"=1;"popup"=1 # columnGroup-specific "showInHeader"=1 @@ -1945,6 +1945,7 @@ function Emit-Element { switch ($typeKey) { "group" { Emit-Group -el $el -name $name -id $id -indent $indent } "columnGroup" { Emit-ColumnGroup -el $el -name $name -id $id -indent $indent } + "buttonGroup" { Emit-ButtonGroup -el $el -name $name -id $id -indent $indent } "input" { Emit-Input -el $el -name $name -id $id -indent $indent } "check" { Emit-Check -el $el -name $name -id $id -indent $indent } "radio" { Emit-Radio -el $el -name $name -id $id -indent $indent } @@ -2787,6 +2788,35 @@ function Emit-CommandBar { X "$indent" } +function Emit-ButtonGroup { + param($el, [string]$name, [int]$id, [string]$indent) + + X "$indent" + $inner = "$indent`t" + + Emit-Title -el $el -name $name -indent $inner + + if ($el.representation) { + X "$inner$($el.representation)" + } + + Emit-CommonFlags -el $el -indent $inner + + # Companion: ExtendedTooltip + Emit-Companion -tag "ExtendedTooltip" -name "${name}РасширеннаяПодсказка" -indent $inner + + # Children (кнопки в контексте командной панели) + if ($el.children -and $el.children.Count -gt 0) { + X "$inner" + foreach ($child in $el.children) { + Emit-Element -el $child -indent "$inner`t" -inCmdBar $true + } + X "$inner" + } + + X "$indent" +} + function Emit-Popup { param($el, [string]$name, [int]$id, [string]$indent) @@ -2933,10 +2963,18 @@ function Emit-Commands { Emit-MLText -tag "Title" -text "$cmdTitle" -indent $inner } + if ($cmd.tooltip) { + Emit-MLText -tag "ToolTip" -text "$($cmd.tooltip)" -indent $inner + } + if ($cmd.action) { X "$inner$($cmd.action)" } + if ($cmd.currentRowUse) { + X "$inner$($cmd.currentRowUse)" + } + if ($cmd.shortcut) { X "$inner$($cmd.shortcut)" } diff --git a/.claude/skills/form-compile/scripts/form-compile.py b/.claude/skills/form-compile/scripts/form-compile.py index 9910f9b7..b4fc7ea1 100644 --- a/.claude/skills/form-compile/scripts/form-compile.py +++ b/.claude/skills/form-compile/scripts/form-compile.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -# form-compile v1.23 — Compile 1C managed form from JSON or object metadata +# form-compile v1.24 — Compile 1C managed form from JSON or object metadata # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills import argparse import copy @@ -1338,7 +1338,7 @@ KNOWN_FORM_EVENTS = [ ] KNOWN_KEYS = { - "group", "columnGroup", "input", "check", "radio", "label", "labelField", "table", "pages", "page", + "group", "columnGroup", "buttonGroup", "input", "check", "radio", "label", "labelField", "table", "pages", "page", "button", "picture", "picField", "calendar", "cmdBar", "popup", "showInHeader", "radioButtonType", "choiceList", "columnsCount", @@ -1364,7 +1364,7 @@ KNOWN_KEYS = { "rowPictureDataPath", "tableAutofill", } -TYPE_KEYS = ["columnGroup", "group", "input", "check", "radio", "label", "labelField", "table", "pages", "page", +TYPE_KEYS = ["columnGroup", "buttonGroup", "group", "input", "check", "radio", "label", "labelField", "table", "pages", "page", "button", "picture", "picField", "calendar", "cmdBar", "popup"] # Synonyms: model often writes XML name or Russian (ПолеПереключателя/RadioButtonField → radio) @@ -1792,6 +1792,7 @@ def emit_element(lines, el, indent, in_cmd_bar=False): emitters = { 'group': emit_group, 'columnGroup': emit_column_group, + 'buttonGroup': emit_button_group, 'input': emit_input, 'check': emit_check, 'radio': emit_radio_button_field, @@ -2452,6 +2453,30 @@ def emit_popup(lines, el, name, eid, indent): lines.append(f'{indent}') +def emit_button_group(lines, el, name, eid, indent): + lines.append(f'{indent}') + inner = f'{indent}\t' + + emit_title(lines, el, name, inner) + + if el.get('representation'): + lines.append(f'{inner}{el["representation"]}') + + emit_common_flags(lines, el, inner) + + # Companion: ExtendedTooltip + emit_companion(lines, 'ExtendedTooltip', f'{name}РасширеннаяПодсказка', inner) + + # Children (кнопки в контексте командной панели) + if el.get('children') and len(el['children']) > 0: + lines.append(f'{inner}') + for child in el['children']: + emit_element(lines, child, f'{inner}\t', in_cmd_bar=True) + lines.append(f'{inner}') + + lines.append(f'{indent}') + + # --- Attribute emitter --- def emit_attributes(lines, attrs, indent): @@ -2554,9 +2579,15 @@ def emit_commands(lines, cmds, indent): if cmd_title: emit_mltext(lines, inner, 'Title', str(cmd_title)) + if cmd.get('tooltip'): + emit_mltext(lines, inner, 'ToolTip', str(cmd['tooltip'])) + if cmd.get('action'): lines.append(f'{inner}{cmd["action"]}') + if cmd.get('currentRowUse'): + lines.append(f'{inner}{cmd["currentRowUse"]}') + if cmd.get('shortcut'): lines.append(f'{inner}{cmd["shortcut"]}') diff --git a/.claude/skills/form-decompile/scripts/form-decompile.ps1 b/.claude/skills/form-decompile/scripts/form-decompile.ps1 index e36bf66d..205dacb2 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.2 — Decompile 1C managed Form.xml to JSON DSL (draft) +# form-decompile v0.3 — Decompile 1C managed Form.xml to JSON DSL (draft) # Source: https://github.com/Nikolay-Shirokov/cc-1c-skills # ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью. param( @@ -280,7 +280,7 @@ function Decompile-Type { # --- 4. Element dispatch --- $ELEMENT_KEY = @{ - 'UsualGroup'='group'; 'ColumnGroup'='columnGroup'; 'InputField'='input'; 'CheckBoxField'='check'; + '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' @@ -455,6 +455,13 @@ function Decompile-Element { $rep = Get-Child $node 'Representation'; if ($rep) { $obj['representation'] = $rep } $lic = Get-Child $node 'LocationInCommandBar'; if ($lic) { $obj['locationInCommandBar'] = $lic } } + 'ButtonGroup' { + $obj[$key] = $name + Add-CommonProps $obj $node $name + $rep = Get-Child $node 'Representation'; if ($rep) { $obj['representation'] = $rep } + $kids = Decompile-Children $node + if ($kids) { $obj['children'] = $kids } + } 'CommandBar' { $obj[$key] = $name Add-CommonProps $obj $node $name @@ -507,9 +514,25 @@ if ($evForm) { if ($evMap.Count -gt 0) { $dsl['events'] = $evMap } } -# elements +# elements (+ форменный AutoCommandBar как autoCmdBar-элемент, если у него есть содержимое) +$elemList = New-Object System.Collections.ArrayList +$acb = $root.SelectSingleNode("lf:AutoCommandBar", $ns) +if ($acb) { + $haln = Get-Child $acb 'HorizontalAlign' + $acbAutofill = Get-Child $acb 'Autofill' + $acbKids = Decompile-Children $acb + if ($haln -or ($acbAutofill -eq 'false') -or $acbKids) { + $acbObj = [ordered]@{} + $acbObj['autoCmdBar'] = $acb.GetAttribute("name") + if ($haln) { $acbObj['horizontalAlign'] = $haln } + if ($acbAutofill -eq 'false') { $acbObj['autofill'] = $false } + if ($acbKids) { $acbObj['children'] = $acbKids } + [void]$elemList.Add($acbObj) + } +} $elements = Decompile-Children $root -if ($elements) { $dsl['elements'] = $elements } +if ($elements) { foreach ($e in $elements) { [void]$elemList.Add($e) } } +if ($elemList.Count -gt 0) { $dsl['elements'] = @($elemList) } # attributes $attrsNode = $root.SelectSingleNode("lf:Attributes", $ns) @@ -560,6 +583,8 @@ if ($cmdsNode) { $co = [ordered]@{}; $co['name'] = $c.GetAttribute("name") $act = Get-Child $c 'Action'; if ($act) { $co['action'] = $act } $tNode = $c.SelectSingleNode("lf:Title", $ns); if ($tNode) { $t = Get-LangText $tNode; if ($null -ne $t) { $co['title'] = $t } } + $ttNode = $c.SelectSingleNode("lf:ToolTip", $ns); if ($ttNode) { $t = Get-LangText $ttNode; if ($null -ne $t) { $co['tooltip'] = $t } } + $cru = Get-Child $c 'CurrentRowUse'; if ($cru) { $co['currentRowUse'] = $cru } $sc = Get-Child $c 'Shortcut'; if ($sc) { $co['shortcut'] = $sc } $ref = $c.SelectSingleNode("lf:Picture/xr:Ref", $ns); if ($ref) { $co['picture'] = $ref.InnerText } $rep = Get-Child $c 'Representation'; if ($rep) { $co['representation'] = $rep } diff --git a/docs/form-dsl-spec.md b/docs/form-dsl-spec.md index f2dc2378..6aa63707 100644 --- a/docs/form-dsl-spec.md +++ b/docs/form-dsl-spec.md @@ -385,6 +385,42 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs { "popup": "Печать", "picture": "StdPicture.Print", "children": [ ... ] } ``` +#### buttonGroup — ButtonGroup + +Группа кнопок внутри командной панели (`autoCmdBar`/`cmdBar`/`popup`). Значение ключа — имя элемента. + +```json +{ "buttonGroup": "ГруппаПереместить", "title": "Переместить", "children": [ + { "button": "ПереместитьВверх", "command": "ПереместитьВверх" }, + { "button": "ПереместитьВниз", "command": "ПереместитьВниз" } +] } +``` + +| Свойство | Тип | Описание | +|----------|-----|----------| +| `buttonGroup` | string | Имя элемента | +| `title` | string/object | Заголовок группы | +| `representation` | string | `Auto`, `Picture`, `Text`, `PictureAndText` | +| `children` | array | Кнопки (`button`) внутри группы | + +#### autoCmdBar — командная панель формы + +Командная панель самой формы (``). Задаётся как элемент в `elements`; компилятор автоматически вынимает его из дерева. Нужен только если в панель помещаются **явные** кнопки/группы или меняется выравнивание/автозаполнение — иначе панель формируется автоматически. + +```json +{ "autoCmdBar": "ФормаКоманднаяПанель", "horizontalAlign": "Right", "autofill": false, "children": [ + { "button": "ОК", "command": "ОК", "defaultButton": true }, + { "button": "Отмена", "command": "Отмена" } +] } +``` + +| Свойство | Тип | Описание | +|----------|-----|----------| +| `autoCmdBar` | string | Имя панели (обычно `ФормаКоманднаяПанель`) | +| `horizontalAlign` | string | `Right`, `Left`, `Center` | +| `autofill` | bool | `false` — отключить автозаполнение стандартными командами | +| `children` | array | Кнопки/группы кнопок панели | + --- ## 5. Attributes — реквизиты формы @@ -443,6 +479,8 @@ Pages поддерживает `pagesRepresentation`: `None`, `TabsOnTop`, `Tabs | `name` | string | Имя команды (обязательно) | | `action` | string | Имя процедуры-обработчика | | `title` | string | Заголовок | +| `tooltip` | string/object | Всплывающая подсказка команды (``) | +| `currentRowUse` | string | Использование текущей строки: `Auto`, `DontUse`, `Use` | | `shortcut` | string | Клавиатурное сочетание | | `picture` | string | Ссылка на картинку | | `representation` | string | `Auto`, `Picture`, `Text`, `PictureAndText` | diff --git a/tests/skills/cases/form-compile/button-group.json b/tests/skills/cases/form-compile/button-group.json new file mode 100644 index 00000000..f15c09fb --- /dev/null +++ b/tests/skills/cases/form-compile/button-group.json @@ -0,0 +1,36 @@ +{ + "name": "ButtonGroup в командной панели + команды с tooltip/currentRowUse", + "preRun": [ + { + "script": "meta-compile/scripts/meta-compile", + "input": { "type": "DataProcessor", "name": "ГруппыКнопок" }, + "args": { "-JsonPath": "{inputFile}", "-OutputDir": "{workDir}" } + }, + { + "script": "form-add/scripts/form-add", + "args": { "-ObjectPath": "{workDir}/DataProcessors/ГруппыКнопок.xml", "-FormName": "Форма" } + } + ], + "params": { "outputPath": "DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form.xml" }, + "validatePath": "DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form.xml", + "input": { + "title": "Группы кнопок", + "elements": [ + { "cmdBar": "Панель", "children": [ + { "button": "Выполнить", "command": "Выполнить", "defaultButton": true }, + { "buttonGroup": "ГруппаПереместить", "title": "Переместить", "children": [ + { "button": "Вверх", "command": "Вверх" }, + { "button": "Вниз", "command": "Вниз" } + ]} + ]} + ], + "attributes": [ + { "name": "Объект", "type": "DataProcessorObject.ГруппыКнопок", "main": true } + ], + "commands": [ + { "name": "Выполнить", "action": "ВыполнитьОбработка", "tooltip": "Запустить обработку", "shortcut": "Ctrl+Enter" }, + { "name": "Вверх", "action": "ВверхОбработка", "currentRowUse": "DontUse" }, + { "name": "Вниз", "action": "ВнизОбработка", "currentRowUse": "DontUse" } + ] + } +} diff --git a/tests/skills/cases/form-compile/snapshots/button-group/Configuration.xml b/tests/skills/cases/form-compile/snapshots/button-group/Configuration.xml new file mode 100644 index 00000000..dec13ea8 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/Configuration.xml @@ -0,0 +1,252 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + UUID-006 + UUID-007 + + + UUID-008 + UUID-009 + + + UUID-010 + UUID-011 + + + UUID-012 + UUID-013 + + + UUID-014 + UUID-015 + + + + TestConfig + + + ru + TestConfig + + + + + Version8_3_24 + ManagedApplication + + PlatformApplication + + Russian + + + + + false + false + false + + + + + + + + + + + + + + + + + + + + + + Biometrics + true + + + Location + false + + + BackgroundLocation + false + + + BluetoothPrinters + false + + + WiFiPrinters + false + + + Contacts + false + + + Calendars + false + + + PushNotifications + false + + + LocalNotifications + false + + + InAppPurchases + false + + + PersonalComputerFileExchange + false + + + Ads + false + + + NumberDialing + false + + + CallProcessing + false + + + CallLog + false + + + AutoSendSMS + false + + + ReceiveSMS + false + + + SMSLog + false + + + Camera + false + + + Microphone + false + + + MusicLibrary + false + + + PictureAndVideoLibraries + false + + + AudioPlaybackAndVibration + false + + + BackgroundAudioPlaybackAndVibration + false + + + InstallPackages + false + + + OSBackup + true + + + ApplicationUsageStatistics + false + + + BarcodeScanning + false + + + BackgroundAudioRecording + false + + + AllFilesAccess + false + + + Videoconferences + false + + + NFC + false + + + DocumentScanning + false + + + SpeechToText + false + + + Geofences + false + + + IncomingShareRequests + false + + + AllIncomingShareRequestsTypesProcessing + false + + + + + + Normal + + + Language.Русский + + + + + + Managed + NotAutoFree + DontUse + DontUse + TaxiEnableVersion8_2 + DontUse + Version8_3_24 + + + + Русский + ГруппыКнопок + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок.xml b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок.xml new file mode 100644 index 00000000..f4859f98 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок.xml @@ -0,0 +1,34 @@ + + + + + + UUID-002 + UUID-003 + + + UUID-004 + UUID-005 + + + + ГруппыКнопок + + + ru + Группы кнопок + + + + false + DataProcessor.ГруппыКнопок.Form.Форма + + false + + + + +
Форма
+
+
+
diff --git a/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Ext/ManagerModule.bsl b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Ext/ManagerModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Ext/ObjectModule.bsl b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Ext/ObjectModule.bsl new file mode 100644 index 00000000..e69de29b diff --git a/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма.xml b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма.xml new file mode 100644 index 00000000..dffeea01 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма.xml @@ -0,0 +1,22 @@ + + +
+ + Форма + + + ru + Форма + + + + Managed + false + + PlatformApplication + MobilePlatformApplication + + + +
+
\ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form.xml b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form.xml new file mode 100644 index 00000000..3e4f7617 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form.xml @@ -0,0 +1,92 @@ + +
+ + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Группы кнопок</v8:content> + </v8:item> + + false + + false + + + + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Переместить</v8:content> + </v8:item> + + + + + + + + + + + + + + cfg:DataProcessorObject.ГруппыКнопок + + true + + + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Выполнить</v8:content> + </v8:item> + + + + ru + Запустить обработку + + + ВыполнитьОбработка + Ctrl+Enter + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Вверх</v8:content> + </v8:item> + + ВверхОбработка + DontUse + + + + <v8:item> + <v8:lang>ru</v8:lang> + <v8:content>Вниз</v8:content> + </v8:item> + + ВнизОбработка + DontUse + + +
diff --git a/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form/Module.bsl b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form/Module.bsl new file mode 100644 index 00000000..8ead4cec --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/DataProcessors/ГруппыКнопок/Forms/Форма/Ext/Form/Module.bsl @@ -0,0 +1,19 @@ +#Область ОбработчикиСобытийФормы + +#КонецОбласти + +#Область ОбработчикиСобытийЭлементовФормы + +#КонецОбласти + +#Область ОбработчикиКомандФормы + +#КонецОбласти + +#Область ОбработчикиОповещений + +#КонецОбласти + +#Область СлужебныеПроцедурыИФункции + +#КонецОбласти \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/button-group/Ext/ClientApplicationInterface.xml b/tests/skills/cases/form-compile/snapshots/button-group/Ext/ClientApplicationInterface.xml new file mode 100644 index 00000000..3c1161b2 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/Ext/ClientApplicationInterface.xml @@ -0,0 +1,18 @@ + + + + + UUID-002 + + + + + UUID-004 + + + + + + + + \ No newline at end of file diff --git a/tests/skills/cases/form-compile/snapshots/button-group/Languages/Русский.xml b/tests/skills/cases/form-compile/snapshots/button-group/Languages/Русский.xml new file mode 100644 index 00000000..37c60d78 --- /dev/null +++ b/tests/skills/cases/form-compile/snapshots/button-group/Languages/Русский.xml @@ -0,0 +1,16 @@ + + + + + Русский + + + ru + Русский + + + + ru + + + \ No newline at end of file