mirror of
https://github.com/Nikolay-Shirokov/cc-1c-skills.git
synced 2026-06-15 02:14:57 +03:00
feat(form-decompile,form-compile): Planner design-time Settings из ring-3 (Фаза 1 кластера Chart-Settings)
Реквизит planner-типа несёт <Settings xsi:type="pl:Planner"> — встроенный конфиг
поля-планировщика (элементы расписания + оформление/поведение + шкала времени).
Раньше декомпилятор делал fail-ring3 (третий вид Settings после TypeDescription/
DynamicList). Корпус 8.3.24: Planner Settings = 1 реальная форма (КонтактныеЛица/
ФормаЛиды), всё chart-семейство = 38 форм. Решение (с пользователем): структурный
DSL ради возможности модели СОЗДАВАТЬ дашборды/планировщики, не только раундтрипить.
DSL: ключ planner:{…} на реквизите (docs/form-dsl-spec.md):
- items[] (элементы расписания) + appearance/поведение-скаляры + timeScale
(placement/levels[]/colors) + period;
- цвета verbatim, шрифт {kind:AutoFont}/ref, граница {width,style}, ML-форматы;
- компилятор подставляет дефолты для пропущенных ключей (краткий авторинг),
декомпилятор — полный захват (раундтрип бит-в-бит).
Снят fail-ring3 для pl:Planner (Chart/GanttChart остаются — Фазы 2/3).
Заодно фикс: d5p1:Dendrogram отсутствовал в specialTypeNs (эмитился без
xmlns-префикса) — добавлен в карту (ps1+py).
Раундтрип бит-в-бит: синтетика upload/epf/Диаграммы (с items+period) +
реальная ФормаЛиды (без items/period, иные значения скаляров). Зеркало py
(ps1==py байт-в-байт). Кейс chart-fields расширен (+planner +dendrogram),
сертифицирован загрузкой в 1С. Регресс 41/41 (ps1+py).
Ограничение Phase 1: dimensions/item.dimensionValues пока всегда пустые.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# form-compile v1.103 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.104 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
param(
|
||||
[string]$JsonPath,
|
||||
@@ -2168,6 +2168,7 @@ function Emit-SingleType {
|
||||
"d5p1:TextDocument" = "http://v8.1c.ru/8.1/data/txtedt"
|
||||
"d5p1:Chart" = "http://v8.1c.ru/8.2/data/chart"
|
||||
"d5p1:GanttChart" = "http://v8.1c.ru/8.2/data/chart"
|
||||
"d5p1:Dendrogram" = "http://v8.1c.ru/8.2/data/chart"
|
||||
"d5p1:FlowchartContextType" = "http://v8.1c.ru/8.2/data/graphscheme"
|
||||
"d5p1:DataAnalysisTimeIntervalUnitType" = "http://v8.1c.ru/8.2/data/data-analysis"
|
||||
"d5p1:GeographicalSchema" = "http://v8.1c.ru/8.2/data/geo"
|
||||
@@ -3022,6 +3023,164 @@ function Emit-BorderTag {
|
||||
X "$indent</Border>"
|
||||
}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Planner design-time <Settings xsi:type="pl:Planner"> — встроенный конфиг планировщика
|
||||
# на реквизите planner-типа. Структурный DSL: items[] + appearance/поведение-скаляры +
|
||||
# timeScale (уровни шкалы времени) + period. Каждое присутствующее поле → каноничный
|
||||
# порядок; пропущенное → дефолт (планировщик всегда несёт полный блок). Декомпилятор
|
||||
# делает полный захват → раундтрип бит-в-бит; ручной авторинг может быть кратким.
|
||||
$script:PLANNER_NS = 'http://v8.1c.ru/8.3/data/planner'
|
||||
$script:CHART_NS = 'http://v8.1c.ru/8.2/data/chart'
|
||||
|
||||
function PL-Get {
|
||||
param($o, [string]$k, $def = $null)
|
||||
if ($null -ne $o -and $o.PSObject.Properties[$k] -and $null -ne $o.$k) { return $o.$k }
|
||||
return $def
|
||||
}
|
||||
function PL-Bool {
|
||||
param($v)
|
||||
if ($v -is [bool]) { if ($v) { 'true' } else { 'false' } }
|
||||
elseif ("$v" -eq 'True') { 'true' }
|
||||
elseif ("$v" -eq 'False') { 'false' }
|
||||
else { "$v" }
|
||||
}
|
||||
function Emit-PlannerColor {
|
||||
param([string]$tag, $o, [string]$key, [string]$ind)
|
||||
X "$ind<pl:$tag>$(Esc-Xml "$(PL-Get $o $key 'auto')")</pl:$tag>"
|
||||
}
|
||||
function Emit-PlannerFont {
|
||||
param($o, [string]$ind)
|
||||
$f = PL-Get $o 'font' $null
|
||||
if ($null -eq $f) { X "$ind<pl:font kind=`"AutoFont`"/>"; return }
|
||||
Emit-FontTag -tag 'pl:font' -val $f -indent $ind
|
||||
}
|
||||
function Emit-PlannerBorder {
|
||||
param($o, [string]$ind, [string]$key = 'border')
|
||||
$b = PL-Get $o $key $null
|
||||
$bw = if ($b) { PL-Get $b 'width' 1 } else { 1 }
|
||||
$bs = if ($b) { PL-Get $b 'style' 'Single' } else { 'Single' }
|
||||
X "$ind<pl:border width=`"$bw`">"
|
||||
X "$ind`t<v8ui:style xsi:type=`"v8ui:ControlBorderType`">$(Esc-Xml "$bs")</v8ui:style>"
|
||||
X "$ind</pl:border>"
|
||||
}
|
||||
function Emit-PlannerLevel {
|
||||
param($lv, [string]$cns, [string]$ind)
|
||||
$li = "$ind`t"
|
||||
X "$ind<level xmlns=`"$cns`">"
|
||||
X "$li<measure>$(Esc-Xml "$(PL-Get $lv 'measure' 'Hour')")</measure>"
|
||||
X "$li<interval>$(PL-Get $lv 'interval' 1)</interval>"
|
||||
X "$li<show>$(PL-Bool (PL-Get $lv 'show' $true))</show>"
|
||||
$line = PL-Get $lv 'line' $null
|
||||
$lw = if ($line) { PL-Get $line 'width' 1 } else { 1 }
|
||||
$lg = if ($line) { PL-Get $line 'gap' $false } else { $false }
|
||||
$lst = if ($line) { PL-Get $line 'style' 'Solid' } else { 'Solid' }
|
||||
X "$li<line width=`"$lw`" gap=`"$(PL-Bool $lg)`">"
|
||||
X "$li`t<v8ui:style xsi:type=`"v8ui:ChartLineType`">$(Esc-Xml "$lst")</v8ui:style>"
|
||||
X "$li</line>"
|
||||
X "$li<scaleColor>$(Esc-Xml "$(PL-Get $lv 'scaleColor' 'auto')")</scaleColor>"
|
||||
X "$li<dayFormatRule>$(Esc-Xml "$(PL-Get $lv 'dayFormatRule' 'MonthDayWeekDay')")</dayFormatRule>"
|
||||
$fmt = PL-Get $lv 'format' $null
|
||||
if ($null -eq $fmt) { $fmt = [ordered]@{ '#' = 'DF="HH:mm"'; 'ru' = 'DF="HH:mm"' } }
|
||||
X "$li<format>"
|
||||
Emit-MLItems -val $fmt -indent "$li`t"
|
||||
X "$li</format>"
|
||||
$labels = PL-Get $lv 'labels' $null
|
||||
$ticks = if ($labels) { PL-Get $labels 'ticks' 0 } else { 0 }
|
||||
X "$li<labels>"
|
||||
X "$li`t<ticks>$ticks</ticks>"
|
||||
X "$li</labels>"
|
||||
X "$li<backColor>$(Esc-Xml "$(PL-Get $lv 'backColor' 'auto')")</backColor>"
|
||||
X "$li<textColor>$(Esc-Xml "$(PL-Get $lv 'textColor' 'auto')")</textColor>"
|
||||
X "$li<showPereodicalLabels>$(PL-Bool (PL-Get $lv 'showPereodicalLabels' $true))</showPereodicalLabels>"
|
||||
X "$ind</level>"
|
||||
}
|
||||
function Emit-PlannerTimeScale {
|
||||
param($ts, [string]$ind)
|
||||
$cns = $script:CHART_NS
|
||||
$ci = "$ind`t"
|
||||
X "$ind<pl:timeScale>"
|
||||
X "$ci<placement xmlns=`"$cns`">$(Esc-Xml "$(if ($ts) { PL-Get $ts 'placement' 'Left' } else { 'Left' })")</placement>"
|
||||
$levels = if ($ts) { @(PL-Get $ts 'levels' @()) } else { @() }
|
||||
if (@($levels).Count -eq 0) { $levels = @($null) } # один уровень-дефолт
|
||||
foreach ($lv in $levels) { Emit-PlannerLevel $lv $cns $ci }
|
||||
$transp = if ($ts) { PL-Get $ts 'transparent' $false } else { $false }
|
||||
X "$ci<transparent xmlns=`"$cns`">$(PL-Bool $transp)</transparent>"
|
||||
X "$ci<backColor xmlns=`"$cns`">$(Esc-Xml "$(if ($ts) { PL-Get $ts 'backColor' 'auto' } else { 'auto' })")</backColor>"
|
||||
X "$ci<textColor xmlns=`"$cns`">$(Esc-Xml "$(if ($ts) { PL-Get $ts 'textColor' 'auto' } else { 'auto' })")</textColor>"
|
||||
X "$ci<currentLevel xmlns=`"$cns`">$(if ($ts) { PL-Get $ts 'currentLevel' 0 } else { 0 })</currentLevel>"
|
||||
X "$ind</pl:timeScale>"
|
||||
}
|
||||
function Emit-PlannerItem {
|
||||
param($it, [string]$ind)
|
||||
X "$ind<pl:item>"
|
||||
$ii = "$ind`t"
|
||||
$val = PL-Get $it 'value' $null
|
||||
if ($null -eq $val) { X "$ii<pl:value xsi:nil=`"true`"/>" }
|
||||
else { X "$ii<pl:value xsi:type=`"xs:string`">$(Esc-Xml "$val")</pl:value>" }
|
||||
X "$ii<pl:text>$(Esc-Xml "$(PL-Get $it 'text' '')")</pl:text>"
|
||||
$tt = PL-Get $it 'tooltip' ''
|
||||
if ("$tt" -eq '') { X "$ii<pl:tooltip/>" } else { X "$ii<pl:tooltip>$(Esc-Xml "$tt")</pl:tooltip>" }
|
||||
X "$ii<pl:begin>$(PL-Get $it 'begin' '0001-01-01T00:00:00')</pl:begin>"
|
||||
X "$ii<pl:end>$(PL-Get $it 'end' '0001-01-01T00:00:00')</pl:end>"
|
||||
Emit-PlannerColor 'borderColor' $it 'borderColor' $ii
|
||||
Emit-PlannerColor 'backColor' $it 'backColor' $ii
|
||||
Emit-PlannerColor 'textColor' $it 'textColor' $ii
|
||||
Emit-PlannerFont $it $ii
|
||||
X "$ii<pl:dimensionValues/>"
|
||||
X "$ii<pl:replacementDate>$(PL-Get $it 'replacementDate' '0001-01-01T00:00:00')</pl:replacementDate>"
|
||||
X "$ii<pl:deleted>$(PL-Bool (PL-Get $it 'deleted' $false))</pl:deleted>"
|
||||
$id = PL-Get $it 'id' $null
|
||||
if ($null -eq $id) { $id = [guid]::NewGuid().ToString() }
|
||||
X "$ii<pl:id>$id</pl:id>"
|
||||
X "$ii<pl:textFormatted>$(PL-Bool (PL-Get $it 'textFormatted' $false))</pl:textFormatted>"
|
||||
Emit-PlannerBorder $it $ii 'border'
|
||||
X "$ii<pl:editMode>$(Esc-Xml "$(PL-Get $it 'editMode' 'EnableEdit')")</pl:editMode>"
|
||||
X "$ind</pl:item>"
|
||||
}
|
||||
function Emit-PlannerSettings {
|
||||
param($pl, [string]$ind)
|
||||
X "$ind<Settings xmlns:pl=`"$($script:PLANNER_NS)`" xsi:type=`"pl:Planner`">"
|
||||
$si = "$ind`t"
|
||||
foreach ($it in @(PL-Get $pl 'items' @())) { Emit-PlannerItem $it $si }
|
||||
Emit-PlannerColor 'borderColor' $pl 'borderColor' $si
|
||||
Emit-PlannerColor 'backColor' $pl 'backColor' $si
|
||||
Emit-PlannerColor 'textColor' $pl 'textColor' $si
|
||||
Emit-PlannerColor 'lineColor' $pl 'lineColor' $si
|
||||
Emit-PlannerFont $pl $si
|
||||
X "$si<pl:beginOfRepresentationPeriod>$(PL-Get $pl 'beginOfRepresentationPeriod' '0001-01-01T00:00:00')</pl:beginOfRepresentationPeriod>"
|
||||
X "$si<pl:endOfRepresentationPeriod>$(PL-Get $pl 'endOfRepresentationPeriod' '0001-01-01T00:00:00')</pl:endOfRepresentationPeriod>"
|
||||
X "$si<pl:alignElementsOfTimeScale>$(PL-Bool (PL-Get $pl 'alignElementsOfTimeScale' $true))</pl:alignElementsOfTimeScale>"
|
||||
X "$si<pl:displayTimeScaleWrapHeaders>$(PL-Bool (PL-Get $pl 'displayTimeScaleWrapHeaders' $true))</pl:displayTimeScaleWrapHeaders>"
|
||||
X "$si<pl:displayWrapHeaders>$(PL-Bool (PL-Get $pl 'displayWrapHeaders' $true))</pl:displayWrapHeaders>"
|
||||
$wfmt = PL-Get $pl 'timeScaleWrapHeadersFormat' $null
|
||||
if ($null -eq $wfmt) { $wfmt = [ordered]@{ '#' = 'DLF="DD"'; 'ru' = 'DLF="DD"' } }
|
||||
Emit-MLText -tag 'pl:timeScaleWrapHeadersFormat' -text $wfmt -indent $si
|
||||
X "$si<pl:periodicVariantUnit>$(Esc-Xml "$(PL-Get $pl 'periodicVariantUnit' 'Day')")</pl:periodicVariantUnit>"
|
||||
X "$si<pl:periodicVariantRepetition>$(PL-Get $pl 'periodicVariantRepetition' 1)</pl:periodicVariantRepetition>"
|
||||
X "$si<pl:timeScaleWrapBeginIndent>$(PL-Get $pl 'timeScaleWrapBeginIndent' 0)</pl:timeScaleWrapBeginIndent>"
|
||||
X "$si<pl:timeScaleWrapEndIndent>$(PL-Get $pl 'timeScaleWrapEndIndent' 0)</pl:timeScaleWrapEndIndent>"
|
||||
Emit-PlannerTimeScale (PL-Get $pl 'timeScale' $null) $si
|
||||
$period = PL-Get $pl 'period' $null
|
||||
if ($period) {
|
||||
X "$si<pl:period>"
|
||||
X "$si`t<pl:begin>$(PL-Get $period 'begin' '0001-01-01T00:00:00')</pl:begin>"
|
||||
X "$si`t<pl:end>$(PL-Get $period 'end' '0001-01-01T00:00:00')</pl:end>"
|
||||
X "$si</pl:period>"
|
||||
}
|
||||
X "$si<pl:displayCurrentDate>$(PL-Bool (PL-Get $pl 'displayCurrentDate' $true))</pl:displayCurrentDate>"
|
||||
X "$si<pl:itemsTimeRepresentation>$(Esc-Xml "$(PL-Get $pl 'itemsTimeRepresentation' 'BeginTime')")</pl:itemsTimeRepresentation>"
|
||||
X "$si<pl:itemsBehaviorWhenSpaceInsufficient>$(Esc-Xml "$(PL-Get $pl 'itemsBehaviorWhenSpaceInsufficient' 'CollapseItems')")</pl:itemsBehaviorWhenSpaceInsufficient>"
|
||||
X "$si<pl:autoMinColumnWidth>$(PL-Bool (PL-Get $pl 'autoMinColumnWidth' $true))</pl:autoMinColumnWidth>"
|
||||
X "$si<pl:autoMinRowHeight>$(PL-Bool (PL-Get $pl 'autoMinRowHeight' $true))</pl:autoMinRowHeight>"
|
||||
X "$si<pl:minColumnWidth>$(PL-Get $pl 'minColumnWidth' 0)</pl:minColumnWidth>"
|
||||
X "$si<pl:minRowHeight>$(PL-Get $pl 'minRowHeight' 0)</pl:minRowHeight>"
|
||||
X "$si<pl:fixDimensionsHeader>$(Esc-Xml "$(PL-Get $pl 'fixDimensionsHeader' 'auto')")</pl:fixDimensionsHeader>"
|
||||
X "$si<pl:fixTimeScaleHeader>$(Esc-Xml "$(PL-Get $pl 'fixTimeScaleHeader' 'auto')")</pl:fixTimeScaleHeader>"
|
||||
Emit-PlannerBorder $pl $si 'border'
|
||||
X "$si<pl:newItemsTextType>$(Esc-Xml "$(PL-Get $pl 'newItemsTextType' 'String')")</pl:newItemsTextType>"
|
||||
X "$ind</Settings>"
|
||||
}
|
||||
|
||||
function Emit-Appearance {
|
||||
param($el, [string]$indent, [string]$profile = 'field')
|
||||
if ($null -eq $el) { return }
|
||||
@@ -4766,6 +4925,11 @@ function Emit-Attributes {
|
||||
if ($hasVt) {
|
||||
Emit-Type -typeStr "$vtSpec" -indent $inner -tag "Settings" -tagAttrs ' xsi:type="v8:TypeDescription"'
|
||||
}
|
||||
# Planner design-time <Settings xsi:type="pl:Planner"> (встроенный конфиг планировщика).
|
||||
# Идёт сразу после <Type> (как valueType/DynamicList Settings — взаимоисключающи).
|
||||
if ($attr.PSObject.Properties['planner'] -and $null -ne $attr.planner) {
|
||||
Emit-PlannerSettings -pl $attr.planner -ind $inner
|
||||
}
|
||||
|
||||
if ($attr.main -eq $true) {
|
||||
X "$inner<MainAttribute>true</MainAttribute>"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env python3
|
||||
# form-compile v1.103 — Compile 1C managed form from JSON or object metadata
|
||||
# form-compile v1.104 — Compile 1C managed form from JSON or object metadata
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
import argparse
|
||||
import copy
|
||||
@@ -2714,6 +2714,181 @@ def emit_border_tag(lines, val, indent):
|
||||
lines.append(f'{indent}</Border>')
|
||||
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Planner design-time <Settings xsi:type="pl:Planner"> — зеркало Emit-PlannerSettings (ps1).
|
||||
PLANNER_NS = 'http://v8.1c.ru/8.3/data/planner'
|
||||
CHART_NS = 'http://v8.1c.ru/8.2/data/chart'
|
||||
|
||||
|
||||
def _pl_get(o, k, default=None):
|
||||
if isinstance(o, dict) and o.get(k) is not None:
|
||||
return o[k]
|
||||
return default
|
||||
|
||||
|
||||
def _pl_bool(v):
|
||||
if isinstance(v, bool):
|
||||
return 'true' if v else 'false'
|
||||
if str(v) == 'True':
|
||||
return 'true'
|
||||
if str(v) == 'False':
|
||||
return 'false'
|
||||
return str(v)
|
||||
|
||||
|
||||
def emit_planner_color(lines, tag, o, key, ind):
|
||||
lines.append(f'{ind}<pl:{tag}>{esc_xml(str(_pl_get(o, key, "auto")))}</pl:{tag}>')
|
||||
|
||||
|
||||
def emit_planner_font(lines, o, ind):
|
||||
f = _pl_get(o, 'font')
|
||||
if f is None:
|
||||
lines.append(f'{ind}<pl:font kind="AutoFont"/>')
|
||||
return
|
||||
emit_font_tag(lines, 'pl:font', f, ind)
|
||||
|
||||
|
||||
def emit_planner_border(lines, o, ind, key='border'):
|
||||
b = _pl_get(o, key)
|
||||
bw = _pl_get(b, 'width', 1) if b else 1
|
||||
bs = _pl_get(b, 'style', 'Single') if b else 'Single'
|
||||
lines.append(f'{ind}<pl:border width="{bw}">')
|
||||
lines.append(f'{ind}\t<v8ui:style xsi:type="v8ui:ControlBorderType">{esc_xml(str(bs))}</v8ui:style>')
|
||||
lines.append(f'{ind}</pl:border>')
|
||||
|
||||
|
||||
def emit_planner_level(lines, lv, cns, ind):
|
||||
li = f'{ind}\t'
|
||||
lines.append(f'{ind}<level xmlns="{cns}">')
|
||||
lines.append(f'{li}<measure>{esc_xml(str(_pl_get(lv, "measure", "Hour")))}</measure>')
|
||||
lines.append(f'{li}<interval>{_pl_get(lv, "interval", 1)}</interval>')
|
||||
lines.append(f'{li}<show>{_pl_bool(_pl_get(lv, "show", True))}</show>')
|
||||
line = _pl_get(lv, 'line')
|
||||
lw = _pl_get(line, 'width', 1) if line else 1
|
||||
lg = _pl_get(line, 'gap', False) if line else False
|
||||
lst = _pl_get(line, 'style', 'Solid') if line else 'Solid'
|
||||
lines.append(f'{li}<line width="{lw}" gap="{_pl_bool(lg)}">')
|
||||
lines.append(f'{li}\t<v8ui:style xsi:type="v8ui:ChartLineType">{esc_xml(str(lst))}</v8ui:style>')
|
||||
lines.append(f'{li}</line>')
|
||||
lines.append(f'{li}<scaleColor>{esc_xml(str(_pl_get(lv, "scaleColor", "auto")))}</scaleColor>')
|
||||
lines.append(f'{li}<dayFormatRule>{esc_xml(str(_pl_get(lv, "dayFormatRule", "MonthDayWeekDay")))}</dayFormatRule>')
|
||||
fmt = _pl_get(lv, 'format')
|
||||
if fmt is None:
|
||||
fmt = {'#': 'DF="HH:mm"', 'ru': 'DF="HH:mm"'}
|
||||
lines.append(f'{li}<format>')
|
||||
emit_ml_items(lines, f'{li}\t', fmt)
|
||||
lines.append(f'{li}</format>')
|
||||
labels = _pl_get(lv, 'labels')
|
||||
ticks = _pl_get(labels, 'ticks', 0) if labels else 0
|
||||
lines.append(f'{li}<labels>')
|
||||
lines.append(f'{li}\t<ticks>{ticks}</ticks>')
|
||||
lines.append(f'{li}</labels>')
|
||||
lines.append(f'{li}<backColor>{esc_xml(str(_pl_get(lv, "backColor", "auto")))}</backColor>')
|
||||
lines.append(f'{li}<textColor>{esc_xml(str(_pl_get(lv, "textColor", "auto")))}</textColor>')
|
||||
lines.append(f'{li}<showPereodicalLabels>{_pl_bool(_pl_get(lv, "showPereodicalLabels", True))}</showPereodicalLabels>')
|
||||
lines.append(f'{ind}</level>')
|
||||
|
||||
|
||||
def emit_planner_timescale(lines, ts, ind):
|
||||
cns = CHART_NS
|
||||
ci = f'{ind}\t'
|
||||
lines.append(f'{ind}<pl:timeScale>')
|
||||
placement = _pl_get(ts, 'placement', 'Left') if ts else 'Left'
|
||||
lines.append(f'{ci}<placement xmlns="{cns}">{esc_xml(str(placement))}</placement>')
|
||||
levels = _pl_get(ts, 'levels', []) if ts else []
|
||||
if not levels:
|
||||
levels = [None]
|
||||
for lv in levels:
|
||||
emit_planner_level(lines, lv, cns, ci)
|
||||
transp = _pl_get(ts, 'transparent', False) if ts else False
|
||||
lines.append(f'{ci}<transparent xmlns="{cns}">{_pl_bool(transp)}</transparent>')
|
||||
tbc = _pl_get(ts, 'backColor', 'auto') if ts else 'auto'
|
||||
ttc = _pl_get(ts, 'textColor', 'auto') if ts else 'auto'
|
||||
tcl = _pl_get(ts, 'currentLevel', 0) if ts else 0
|
||||
lines.append(f'{ci}<backColor xmlns="{cns}">{esc_xml(str(tbc))}</backColor>')
|
||||
lines.append(f'{ci}<textColor xmlns="{cns}">{esc_xml(str(ttc))}</textColor>')
|
||||
lines.append(f'{ci}<currentLevel xmlns="{cns}">{tcl}</currentLevel>')
|
||||
lines.append(f'{ind}</pl:timeScale>')
|
||||
|
||||
|
||||
def emit_planner_item(lines, it, ind):
|
||||
lines.append(f'{ind}<pl:item>')
|
||||
ii = f'{ind}\t'
|
||||
val = _pl_get(it, 'value')
|
||||
if val is None:
|
||||
lines.append(f'{ii}<pl:value xsi:nil="true"/>')
|
||||
else:
|
||||
lines.append(f'{ii}<pl:value xsi:type="xs:string">{esc_xml(str(val))}</pl:value>')
|
||||
lines.append(f'{ii}<pl:text>{esc_xml(str(_pl_get(it, "text", "")))}</pl:text>')
|
||||
tt = _pl_get(it, 'tooltip', '')
|
||||
if str(tt) == '':
|
||||
lines.append(f'{ii}<pl:tooltip/>')
|
||||
else:
|
||||
lines.append(f'{ii}<pl:tooltip>{esc_xml(str(tt))}</pl:tooltip>')
|
||||
lines.append(f'{ii}<pl:begin>{_pl_get(it, "begin", "0001-01-01T00:00:00")}</pl:begin>')
|
||||
lines.append(f'{ii}<pl:end>{_pl_get(it, "end", "0001-01-01T00:00:00")}</pl:end>')
|
||||
emit_planner_color(lines, 'borderColor', it, 'borderColor', ii)
|
||||
emit_planner_color(lines, 'backColor', it, 'backColor', ii)
|
||||
emit_planner_color(lines, 'textColor', it, 'textColor', ii)
|
||||
emit_planner_font(lines, it, ii)
|
||||
lines.append(f'{ii}<pl:dimensionValues/>')
|
||||
lines.append(f'{ii}<pl:replacementDate>{_pl_get(it, "replacementDate", "0001-01-01T00:00:00")}</pl:replacementDate>')
|
||||
lines.append(f'{ii}<pl:deleted>{_pl_bool(_pl_get(it, "deleted", False))}</pl:deleted>')
|
||||
iid = _pl_get(it, 'id')
|
||||
if iid is None:
|
||||
import uuid
|
||||
iid = str(uuid.uuid4())
|
||||
lines.append(f'{ii}<pl:id>{iid}</pl:id>')
|
||||
lines.append(f'{ii}<pl:textFormatted>{_pl_bool(_pl_get(it, "textFormatted", False))}</pl:textFormatted>')
|
||||
emit_planner_border(lines, it, ii, 'border')
|
||||
lines.append(f'{ii}<pl:editMode>{esc_xml(str(_pl_get(it, "editMode", "EnableEdit")))}</pl:editMode>')
|
||||
lines.append(f'{ind}</pl:item>')
|
||||
|
||||
|
||||
def emit_planner_settings(lines, pl, ind):
|
||||
lines.append(f'{ind}<Settings xmlns:pl="{PLANNER_NS}" xsi:type="pl:Planner">')
|
||||
si = f'{ind}\t'
|
||||
for it in _pl_get(pl, 'items', []):
|
||||
emit_planner_item(lines, it, si)
|
||||
emit_planner_color(lines, 'borderColor', pl, 'borderColor', si)
|
||||
emit_planner_color(lines, 'backColor', pl, 'backColor', si)
|
||||
emit_planner_color(lines, 'textColor', pl, 'textColor', si)
|
||||
emit_planner_color(lines, 'lineColor', pl, 'lineColor', si)
|
||||
emit_planner_font(lines, pl, si)
|
||||
lines.append(f'{si}<pl:beginOfRepresentationPeriod>{_pl_get(pl, "beginOfRepresentationPeriod", "0001-01-01T00:00:00")}</pl:beginOfRepresentationPeriod>')
|
||||
lines.append(f'{si}<pl:endOfRepresentationPeriod>{_pl_get(pl, "endOfRepresentationPeriod", "0001-01-01T00:00:00")}</pl:endOfRepresentationPeriod>')
|
||||
lines.append(f'{si}<pl:alignElementsOfTimeScale>{_pl_bool(_pl_get(pl, "alignElementsOfTimeScale", True))}</pl:alignElementsOfTimeScale>')
|
||||
lines.append(f'{si}<pl:displayTimeScaleWrapHeaders>{_pl_bool(_pl_get(pl, "displayTimeScaleWrapHeaders", True))}</pl:displayTimeScaleWrapHeaders>')
|
||||
lines.append(f'{si}<pl:displayWrapHeaders>{_pl_bool(_pl_get(pl, "displayWrapHeaders", True))}</pl:displayWrapHeaders>')
|
||||
wfmt = _pl_get(pl, 'timeScaleWrapHeadersFormat')
|
||||
if wfmt is None:
|
||||
wfmt = {'#': 'DLF="DD"', 'ru': 'DLF="DD"'}
|
||||
emit_mltext(lines, si, 'pl:timeScaleWrapHeadersFormat', wfmt)
|
||||
lines.append(f'{si}<pl:periodicVariantUnit>{esc_xml(str(_pl_get(pl, "periodicVariantUnit", "Day")))}</pl:periodicVariantUnit>')
|
||||
lines.append(f'{si}<pl:periodicVariantRepetition>{_pl_get(pl, "periodicVariantRepetition", 1)}</pl:periodicVariantRepetition>')
|
||||
lines.append(f'{si}<pl:timeScaleWrapBeginIndent>{_pl_get(pl, "timeScaleWrapBeginIndent", 0)}</pl:timeScaleWrapBeginIndent>')
|
||||
lines.append(f'{si}<pl:timeScaleWrapEndIndent>{_pl_get(pl, "timeScaleWrapEndIndent", 0)}</pl:timeScaleWrapEndIndent>')
|
||||
emit_planner_timescale(lines, _pl_get(pl, 'timeScale'), si)
|
||||
period = _pl_get(pl, 'period')
|
||||
if period:
|
||||
lines.append(f'{si}<pl:period>')
|
||||
lines.append(f'{si}\t<pl:begin>{_pl_get(period, "begin", "0001-01-01T00:00:00")}</pl:begin>')
|
||||
lines.append(f'{si}\t<pl:end>{_pl_get(period, "end", "0001-01-01T00:00:00")}</pl:end>')
|
||||
lines.append(f'{si}</pl:period>')
|
||||
lines.append(f'{si}<pl:displayCurrentDate>{_pl_bool(_pl_get(pl, "displayCurrentDate", True))}</pl:displayCurrentDate>')
|
||||
lines.append(f'{si}<pl:itemsTimeRepresentation>{esc_xml(str(_pl_get(pl, "itemsTimeRepresentation", "BeginTime")))}</pl:itemsTimeRepresentation>')
|
||||
lines.append(f'{si}<pl:itemsBehaviorWhenSpaceInsufficient>{esc_xml(str(_pl_get(pl, "itemsBehaviorWhenSpaceInsufficient", "CollapseItems")))}</pl:itemsBehaviorWhenSpaceInsufficient>')
|
||||
lines.append(f'{si}<pl:autoMinColumnWidth>{_pl_bool(_pl_get(pl, "autoMinColumnWidth", True))}</pl:autoMinColumnWidth>')
|
||||
lines.append(f'{si}<pl:autoMinRowHeight>{_pl_bool(_pl_get(pl, "autoMinRowHeight", True))}</pl:autoMinRowHeight>')
|
||||
lines.append(f'{si}<pl:minColumnWidth>{_pl_get(pl, "minColumnWidth", 0)}</pl:minColumnWidth>')
|
||||
lines.append(f'{si}<pl:minRowHeight>{_pl_get(pl, "minRowHeight", 0)}</pl:minRowHeight>')
|
||||
lines.append(f'{si}<pl:fixDimensionsHeader>{esc_xml(str(_pl_get(pl, "fixDimensionsHeader", "auto")))}</pl:fixDimensionsHeader>')
|
||||
lines.append(f'{si}<pl:fixTimeScaleHeader>{esc_xml(str(_pl_get(pl, "fixTimeScaleHeader", "auto")))}</pl:fixTimeScaleHeader>')
|
||||
emit_planner_border(lines, pl, si, 'border')
|
||||
lines.append(f'{si}<pl:newItemsTextType>{esc_xml(str(_pl_get(pl, "newItemsTextType", "String")))}</pl:newItemsTextType>')
|
||||
lines.append(f'{ind}</Settings>')
|
||||
|
||||
|
||||
def emit_appearance(lines, el, indent, profile='field'):
|
||||
if not isinstance(el, dict):
|
||||
return
|
||||
@@ -3063,6 +3238,7 @@ def emit_single_type(lines, type_str, indent):
|
||||
"d5p1:TextDocument": "http://v8.1c.ru/8.1/data/txtedt",
|
||||
"d5p1:Chart": "http://v8.1c.ru/8.2/data/chart",
|
||||
"d5p1:GanttChart": "http://v8.1c.ru/8.2/data/chart",
|
||||
"d5p1:Dendrogram": "http://v8.1c.ru/8.2/data/chart",
|
||||
"d5p1:FlowchartContextType": "http://v8.1c.ru/8.2/data/graphscheme",
|
||||
"d5p1:DataAnalysisTimeIntervalUnitType": "http://v8.1c.ru/8.2/data/data-analysis",
|
||||
"d5p1:GeographicalSchema": "http://v8.1c.ru/8.2/data/geo",
|
||||
@@ -4480,6 +4656,9 @@ def emit_attributes(lines, attrs, indent, conditional_appearance=None):
|
||||
break
|
||||
if has_vt:
|
||||
emit_type(lines, '' if vt_spec is None else str(vt_spec), inner, tag="Settings", tag_attrs=' xsi:type="v8:TypeDescription"')
|
||||
# Planner design-time <Settings xsi:type="pl:Planner"> (встроенный конфиг планировщика).
|
||||
if attr.get('planner') is not None:
|
||||
emit_planner_settings(lines, attr['planner'], inner)
|
||||
|
||||
if attr.get('main') is True:
|
||||
lines.append(f'{inner}<MainAttribute>true</MainAttribute>')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# form-decompile v0.79 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# form-decompile v0.80 — Decompile 1C managed Form.xml to JSON DSL (draft)
|
||||
# Source: https://github.com/Nikolay-Shirokov/cc-1c-skills
|
||||
# ВНИМАНИЕ: раундтрип не гарантируется. Навык исключён из авто-использования моделью.
|
||||
param(
|
||||
@@ -152,7 +152,7 @@ foreach ($el in $xmlDoc.SelectNodes("//*[local-name()='ConditionalAppearance']/*
|
||||
# (встроенная конфигурация диаграммы) пока НЕ воспроизводим → честный скип, чтобы не потерять молча.
|
||||
foreach ($s in $xmlDoc.SelectNodes("//*[local-name()='Attribute']/*[local-name()='Settings']")) {
|
||||
$st = $s.GetAttribute("type", $NS_XSI)
|
||||
if ($st -and $st -notmatch 'TypeDescription$' -and $st -notmatch 'DynamicList$') {
|
||||
if ($st -and $st -notmatch 'TypeDescription$' -and $st -notmatch 'DynamicList$' -and $st -notmatch 'Planner$') {
|
||||
Fail-Ring3 -kind "Attribute>Settings типа '$st' (design-time конфигурация, напр. диаграмма)" -loc "Attribute/Settings"
|
||||
}
|
||||
}
|
||||
@@ -1833,6 +1833,131 @@ function Decompile-Element {
|
||||
return $obj
|
||||
}
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# Planner design-time <Settings xsi:type="pl:Planner"> → объект planner на реквизите.
|
||||
# Полный захват каждого поля (раундтрип бит-в-бит); зеркало Emit-PlannerSettings.
|
||||
function PLD-Bool { param($v) if ($null -eq $v) { return $null } return ($v -eq 'true') }
|
||||
function PLD-Int { param($v) if ($null -eq $v) { return $null } return [int]$v }
|
||||
function Build-PlannerFont {
|
||||
param($node)
|
||||
if (-not $node) { return $null }
|
||||
$o = [ordered]@{}
|
||||
foreach ($a in @('ref','faceName','height','bold','italic','underline','strikeout','kind','scale')) {
|
||||
$av = $node.GetAttribute($a); if ($av -ne '') { $o[$a] = $av }
|
||||
}
|
||||
if ($o.Count -eq 0) { return $null }
|
||||
return $o
|
||||
}
|
||||
function Build-PlannerBorder {
|
||||
param($node)
|
||||
if (-not $node) { return $null }
|
||||
$o = [ordered]@{}
|
||||
$w = $node.GetAttribute('width'); if ($w -ne '') { $o['width'] = [int]$w }
|
||||
$st = $node.SelectSingleNode("*[local-name()='style']"); if ($st) { $o['style'] = $st.InnerText }
|
||||
return $o
|
||||
}
|
||||
function Build-PlannerItem {
|
||||
param($itn)
|
||||
$o = [ordered]@{}
|
||||
$valNode = $itn.SelectSingleNode("*[local-name()='value']")
|
||||
if ($valNode -and $valNode.GetAttribute('nil', $NS_XSI) -ne 'true' -and $valNode.InnerText) { $o['value'] = $valNode.InnerText }
|
||||
$o['text'] = (Get-Child $itn 'text')
|
||||
$tt = Get-Child $itn 'tooltip'; if ($tt) { $o['tooltip'] = $tt }
|
||||
$o['begin'] = (Get-Child $itn 'begin')
|
||||
$o['end'] = (Get-Child $itn 'end')
|
||||
$o['borderColor'] = (Get-Child $itn 'borderColor')
|
||||
$o['backColor'] = (Get-Child $itn 'backColor')
|
||||
$o['textColor'] = (Get-Child $itn 'textColor')
|
||||
$fnt = Build-PlannerFont ($itn.SelectSingleNode("*[local-name()='font']")); if ($fnt) { $o['font'] = $fnt }
|
||||
$o['replacementDate'] = (Get-Child $itn 'replacementDate')
|
||||
$o['deleted'] = (PLD-Bool (Get-Child $itn 'deleted'))
|
||||
$o['id'] = (Get-Child $itn 'id')
|
||||
$o['textFormatted'] = (PLD-Bool (Get-Child $itn 'textFormatted'))
|
||||
$brd = Build-PlannerBorder ($itn.SelectSingleNode("*[local-name()='border']")); if ($brd) { $o['border'] = $brd }
|
||||
$o['editMode'] = (Get-Child $itn 'editMode')
|
||||
return $o
|
||||
}
|
||||
function Build-PlannerLevel {
|
||||
param($lvn)
|
||||
$o = [ordered]@{}
|
||||
$o['measure'] = (Get-Child $lvn 'measure')
|
||||
$o['interval'] = (PLD-Int (Get-Child $lvn 'interval'))
|
||||
$o['show'] = (PLD-Bool (Get-Child $lvn 'show'))
|
||||
$lineNode = $lvn.SelectSingleNode("*[local-name()='line']")
|
||||
if ($lineNode) {
|
||||
$ln = [ordered]@{}
|
||||
$w = $lineNode.GetAttribute('width'); if ($w -ne '') { $ln['width'] = [int]$w }
|
||||
$g = $lineNode.GetAttribute('gap'); if ($g -ne '') { $ln['gap'] = ($g -eq 'true') }
|
||||
$st = $lineNode.SelectSingleNode("*[local-name()='style']"); if ($st) { $ln['style'] = $st.InnerText }
|
||||
$o['line'] = $ln
|
||||
}
|
||||
$o['scaleColor'] = (Get-Child $lvn 'scaleColor')
|
||||
$o['dayFormatRule'] = (Get-Child $lvn 'dayFormatRule')
|
||||
$fmtNode = $lvn.SelectSingleNode("*[local-name()='format']")
|
||||
if ($fmtNode) { $f = Get-LangText $fmtNode; if ($null -ne $f) { $o['format'] = $f } }
|
||||
$labelsNode = $lvn.SelectSingleNode("*[local-name()='labels']")
|
||||
if ($labelsNode) { $o['labels'] = [ordered]@{ ticks = (PLD-Int (Get-Child $labelsNode 'ticks')) } }
|
||||
$o['backColor'] = (Get-Child $lvn 'backColor')
|
||||
$o['textColor'] = (Get-Child $lvn 'textColor')
|
||||
$o['showPereodicalLabels'] = (PLD-Bool (Get-Child $lvn 'showPereodicalLabels'))
|
||||
return $o
|
||||
}
|
||||
function Build-PlannerTimeScale {
|
||||
param($tsn)
|
||||
$o = [ordered]@{}
|
||||
$o['placement'] = (Get-Child $tsn 'placement')
|
||||
$levels = New-Object System.Collections.ArrayList
|
||||
foreach ($lvn in @($tsn.SelectNodes("*[local-name()='level']"))) { [void]$levels.Add((Build-PlannerLevel $lvn)) }
|
||||
$o['levels'] = @($levels)
|
||||
$o['transparent'] = (PLD-Bool (Get-Child $tsn 'transparent'))
|
||||
$o['backColor'] = (Get-Child $tsn 'backColor')
|
||||
$o['textColor'] = (Get-Child $tsn 'textColor')
|
||||
$o['currentLevel'] = (PLD-Int (Get-Child $tsn 'currentLevel'))
|
||||
return $o
|
||||
}
|
||||
function Build-PlannerSettings {
|
||||
param($setNode)
|
||||
$pl = [ordered]@{}
|
||||
$itemNodes = @($setNode.SelectNodes("*[local-name()='item']"))
|
||||
if ($itemNodes.Count -gt 0) {
|
||||
$items = New-Object System.Collections.ArrayList
|
||||
foreach ($itn in $itemNodes) { [void]$items.Add((Build-PlannerItem $itn)) }
|
||||
$pl['items'] = @($items)
|
||||
}
|
||||
$pl['borderColor'] = (Get-Child $setNode 'borderColor')
|
||||
$pl['backColor'] = (Get-Child $setNode 'backColor')
|
||||
$pl['textColor'] = (Get-Child $setNode 'textColor')
|
||||
$pl['lineColor'] = (Get-Child $setNode 'lineColor')
|
||||
$fnt = Build-PlannerFont ($setNode.SelectSingleNode("*[local-name()='font']")); if ($fnt) { $pl['font'] = $fnt }
|
||||
$pl['beginOfRepresentationPeriod'] = (Get-Child $setNode 'beginOfRepresentationPeriod')
|
||||
$pl['endOfRepresentationPeriod'] = (Get-Child $setNode 'endOfRepresentationPeriod')
|
||||
$pl['alignElementsOfTimeScale'] = (PLD-Bool (Get-Child $setNode 'alignElementsOfTimeScale'))
|
||||
$pl['displayTimeScaleWrapHeaders'] = (PLD-Bool (Get-Child $setNode 'displayTimeScaleWrapHeaders'))
|
||||
$pl['displayWrapHeaders'] = (PLD-Bool (Get-Child $setNode 'displayWrapHeaders'))
|
||||
$wfNode = $setNode.SelectSingleNode("*[local-name()='timeScaleWrapHeadersFormat']")
|
||||
if ($wfNode) { $wf = Get-LangText $wfNode; if ($null -ne $wf) { $pl['timeScaleWrapHeadersFormat'] = $wf } }
|
||||
$pl['periodicVariantUnit'] = (Get-Child $setNode 'periodicVariantUnit')
|
||||
$pl['periodicVariantRepetition'] = (PLD-Int (Get-Child $setNode 'periodicVariantRepetition'))
|
||||
$pl['timeScaleWrapBeginIndent'] = (PLD-Int (Get-Child $setNode 'timeScaleWrapBeginIndent'))
|
||||
$pl['timeScaleWrapEndIndent'] = (PLD-Int (Get-Child $setNode 'timeScaleWrapEndIndent'))
|
||||
$tsNode = $setNode.SelectSingleNode("*[local-name()='timeScale']")
|
||||
if ($tsNode) { $pl['timeScale'] = (Build-PlannerTimeScale $tsNode) }
|
||||
$perNode = $setNode.SelectSingleNode("*[local-name()='period']")
|
||||
if ($perNode) { $pl['period'] = [ordered]@{ begin = (Get-Child $perNode 'begin'); end = (Get-Child $perNode 'end') } }
|
||||
$pl['displayCurrentDate'] = (PLD-Bool (Get-Child $setNode 'displayCurrentDate'))
|
||||
$pl['itemsTimeRepresentation'] = (Get-Child $setNode 'itemsTimeRepresentation')
|
||||
$pl['itemsBehaviorWhenSpaceInsufficient'] = (Get-Child $setNode 'itemsBehaviorWhenSpaceInsufficient')
|
||||
$pl['autoMinColumnWidth'] = (PLD-Bool (Get-Child $setNode 'autoMinColumnWidth'))
|
||||
$pl['autoMinRowHeight'] = (PLD-Bool (Get-Child $setNode 'autoMinRowHeight'))
|
||||
$pl['minColumnWidth'] = (PLD-Int (Get-Child $setNode 'minColumnWidth'))
|
||||
$pl['minRowHeight'] = (PLD-Int (Get-Child $setNode 'minRowHeight'))
|
||||
$pl['fixDimensionsHeader'] = (Get-Child $setNode 'fixDimensionsHeader')
|
||||
$pl['fixTimeScaleHeader'] = (Get-Child $setNode 'fixTimeScaleHeader')
|
||||
$brd = Build-PlannerBorder ($setNode.SelectSingleNode("*[local-name()='border']")); if ($brd) { $pl['border'] = $brd }
|
||||
$pl['newItemsTextType'] = (Get-Child $setNode 'newItemsTextType')
|
||||
return $pl
|
||||
}
|
||||
|
||||
# --- 5. Form-level assembly ---
|
||||
$dsl = [ordered]@{}
|
||||
|
||||
@@ -1964,6 +2089,10 @@ if ($attrsNode) {
|
||||
$vt = Decompile-Type $setNode
|
||||
$ao['valueType'] = if ($vt) { $vt } else { '' } # пустой Settings → маркер ""
|
||||
}
|
||||
# Planner design-time <Settings xsi:type="pl:Planner"> → объект planner (полный захват).
|
||||
elseif ($setNode -and $setNode.GetAttribute("type", $NS_XSI) -match 'Planner$') {
|
||||
$ao['planner'] = Build-PlannerSettings $setNode
|
||||
}
|
||||
if ((Get-Child $a 'MainAttribute') -eq 'true') { $ao['main'] = $true }
|
||||
elseif ($suppressMainName -and $ao['name'] -eq $suppressMainName) { $ao['main'] = $false }
|
||||
$vw = Decompile-XrFlag $a 'View'; if ($null -ne $vw) { $ao['view'] = $vw }
|
||||
@@ -2053,9 +2182,9 @@ if ($attrsNode) {
|
||||
$ao['useAlways'] = @($shorts)
|
||||
}
|
||||
}
|
||||
# Settings динамического списка
|
||||
# Settings динамического списка (только xsi:type=DynamicList; Planner/TypeDescription — выше)
|
||||
$setNode = $a.SelectSingleNode("lf:Settings", $ns)
|
||||
if ($setNode) {
|
||||
if ($setNode -and $setNode.GetAttribute("type", $NS_XSI) -match 'DynamicList$') {
|
||||
$so = [ordered]@{}
|
||||
# AutoFillAvailableFields — дефолт true, платформа эмитит только отклонение (false). Захват «как есть».
|
||||
$afaf = Get-Child $setNode 'AutoFillAvailableFields'; if ($null -ne $afaf) { $so['autoFillAvailableFields'] = ($afaf -eq 'true') }
|
||||
|
||||
+39
-5
@@ -777,11 +777,11 @@ flags/layout/оформление/companions/события общий), плю
|
||||
Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и рус. (`ПолеТабличногоДокумента`, `ПолеИндикатора`, `ПолеДиаграммы`, `ПолеДиаграммыГанта`, …).
|
||||
Скаляры `output`/`protection`/… — generic pass-through; bool как `true`/`false`, enum verbatim.
|
||||
|
||||
> **Ограничение — design-time конфигурация диаграмм/планировщика.** Реквизит chart-типа может нести
|
||||
> `<Settings xsi:type="d4p1:GanttChart"/"pl:Planner"/…>` — встроенный конфиг диаграммы (серии/оси/цвета/планировщик).
|
||||
> Planner несёт Settings ВСЕГДА (даже дефолтный), Chart/Gantt — при design-time настройке. Этот блок пока НЕ
|
||||
> воспроизводится → декомпилятор делает честный fail-ring3 (не теряет молча). Поля без Settings (диаграмма,
|
||||
> заполняемая в коде; график-схема; период) роундтрипятся полностью.
|
||||
> **Design-time конфигурация диаграмм/планировщика.** Реквизит chart-типа может нести
|
||||
> `<Settings xsi:type="d4p1:GanttChart"/"pl:Planner"/…>` — встроенный конфиг (серии/оси/цвета/планировщик).
|
||||
> **Planner** (`pl:Planner`) — поддержан, см. ключ `planner` ниже. **Chart/GanttChart** (`d4p1:Chart`/`GanttChart`)
|
||||
> при design-time настройке — пока НЕ воспроизводятся → декомпилятор делает честный fail-ring3 (не теряет молча).
|
||||
> Поля без Settings (диаграмма, заполняемая в коде; график-схема; период; дендрограмма) роундтрипятся полностью.
|
||||
|
||||
#### autoCmdBar — командная панель формы
|
||||
|
||||
@@ -833,6 +833,40 @@ Forgiving-синонимы типа: XML-имя (`SpreadSheetDocumentField`) и
|
||||
| `columns` | array | Колонки для ValueTable/ValueTree (`{ name, type, title?, functionalOptions?, useAlways? }`) |
|
||||
| `additionalColumns` | array | Доп. колонки табличных частей объекта: `[{ table: "Объект.ТабЧасть", columns: [<col>] }]`. У главного реквизита-объекта; `<col>` — та же грамматика, что у `columns`. Эмитятся в `<Columns>` после прямых колонок |
|
||||
| `settings` | object | Настройки динамического списка (только `type: "DynamicList"`) |
|
||||
| `planner` | object | Design-time конфигурация планировщика (только `type: "pl:Planner"`, `<Settings xsi:type="pl:Planner">`). См. ниже |
|
||||
|
||||
### planner — design-time конфигурация планировщика
|
||||
|
||||
Для реквизита `type: "pl:Planner"` объект `planner` описывает встроенный конфиг поля-планировщика (элементы расписания + оформление/поведение + шкала времени). Платформа эмитит блок **всегда** (даже дефолтный); компилятор подставляет умолчания для пропущенных ключей — авторинг может быть кратким (`{ "items": [{ "text": "Встреча", "begin": "...", "end": "..." }] }`), декомпилятор делает полный захват (раундтрип бит-в-бит). Цвета verbatim (`auto`/`style:X`/`web:Red`/`#hex`); шрифт `{ kind: "AutoFont" }` или ref-строка; граница `{ width, style }`; ML-форматы — строка или `{ "#": ..., "ru": ... }`.
|
||||
|
||||
```json
|
||||
{ "name": "Планировщик", "type": "pl:Planner", "planner": {
|
||||
"items": [{ "text": "Встреча", "begin": "2026-06-09T01:00:00", "end": "2026-06-09T04:00:00",
|
||||
"borderColor": "auto", "backColor": "auto", "deleted": false, "editMode": "EnableEdit" }],
|
||||
"period": { "begin": "2026-06-09T00:00:00", "end": "2026-06-09T23:59:59" },
|
||||
"displayCurrentDate": true, "itemsTimeRepresentation": "BeginTime",
|
||||
"timeScale": { "placement": "Left", "levels": [{ "measure": "Hour", "interval": 1 }] }
|
||||
} }
|
||||
```
|
||||
|
||||
| Ключ planner | Тип | Назначение |
|
||||
|---|---|---|
|
||||
| `items` | array | Элементы планировщика (`<pl:item>`): `value`(nil по умолч.)/`text`/`tooltip`/`begin`/`end`/`borderColor`/`backColor`/`textColor`/`font`/`replacementDate`/`deleted`/`id`(авто-GUID)/`textFormatted`/`border`/`editMode` |
|
||||
| `borderColor`/`backColor`/`textColor`/`lineColor` | color | Цвета планировщика (умолч. `auto`) |
|
||||
| `font` | font | Шрифт (умолч. `{kind:"AutoFont"}`) |
|
||||
| `beginOfRepresentationPeriod`/`endOfRepresentationPeriod` | dateTime | Период представления |
|
||||
| `alignElementsOfTimeScale`/`displayTimeScaleWrapHeaders`/`displayWrapHeaders`/`displayCurrentDate` | bool | Флаги отображения |
|
||||
| `timeScaleWrapHeadersFormat` | ML | Формат перенесённых заголовков шкалы |
|
||||
| `periodicVariantUnit`/`periodicVariantRepetition` | value/int | Единица/кратность периодического варианта |
|
||||
| `timeScaleWrapBeginIndent`/`timeScaleWrapEndIndent` | int | Отступы переноса шкалы |
|
||||
| `timeScale` | object | Шкала времени: `placement`, `levels:[{measure,interval,show,line:{width,gap,style},scaleColor,dayFormatRule,format(ML),labels:{ticks},backColor,textColor,showPereodicalLabels}]`, `transparent`, `backColor`, `textColor`, `currentLevel` |
|
||||
| `period` | object | `{ begin, end }` — отображаемый период (опционально) |
|
||||
| `itemsTimeRepresentation`/`itemsBehaviorWhenSpaceInsufficient`/`newItemsTextType`/`fixDimensionsHeader`/`fixTimeScaleHeader` | value | Поведение элементов/заголовков |
|
||||
| `autoMinColumnWidth`/`autoMinRowHeight` | bool | Авто-минимум размеров |
|
||||
| `minColumnWidth`/`minRowHeight` | int | Минимальные размеры |
|
||||
| `border` | border | Рамка планировщика (`{ width, style }`) |
|
||||
|
||||
> **Ограничение Phase 1:** `dimensions` (измерения планировщика) и `item.dimensionValues` пока всегда пустые (захват только пустого блока). Конфиг Chart/GanttChart (`d4p1:*`) — отдельная фаза.
|
||||
|
||||
### settings — динамический список
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"name": "Форма с полями диаграмм (без design-time Settings)",
|
||||
"name": "Форма с полями диаграмм + design-time Settings планировщика",
|
||||
"preRun": [
|
||||
{
|
||||
"script": "meta-compile/scripts/meta-compile",
|
||||
@@ -20,14 +20,23 @@
|
||||
{ "graphicalSchema": "Схема", "path": "Схема", "titleLocation": "none", "edit": false },
|
||||
{ "periodField": "Период", "path": "Период", "titleLocation": "none" },
|
||||
{ "ganttChart": "Ганта", "path": "Ганта", "titleLocation": "none",
|
||||
"ganttTable": { "table": "ТаблицаГанта", "path": "Ганта", "height": 3 } }
|
||||
"ganttTable": { "table": "ТаблицаГанта", "path": "Ганта", "height": 3 } },
|
||||
{ "dendrogram": "Дендро", "path": "Дендро", "titleLocation": "none" },
|
||||
{ "planner": "Планировщик", "path": "Планировщик", "titleLocation": "none" }
|
||||
],
|
||||
"attributes": [
|
||||
{ "name": "Объект", "type": "DataProcessorObject.Диаграммы", "main": true },
|
||||
{ "name": "Диаграмма", "type": "d5p1:Chart" },
|
||||
{ "name": "Схема", "type": "d5p1:FlowchartContextType" },
|
||||
{ "name": "Период", "type": "v8:StandardPeriod" },
|
||||
{ "name": "Ганта", "type": "d5p1:GanttChart" }
|
||||
{ "name": "Ганта", "type": "d5p1:GanttChart" },
|
||||
{ "name": "Дендро", "type": "d5p1:Dendrogram" },
|
||||
{ "name": "Планировщик", "type": "pl:Planner", "planner": {
|
||||
"items": [
|
||||
{ "text": "Встреча", "begin": "2026-06-09T01:00:00", "end": "2026-06-09T04:00:00" }
|
||||
],
|
||||
"period": { "begin": "2026-06-09T00:00:00", "end": "2026-06-09T23:59:59" }
|
||||
} }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
+135
-5
@@ -65,15 +65,27 @@
|
||||
</SearchControlAddition>
|
||||
</Table>
|
||||
</GanttChartField>
|
||||
<DendrogramField name="Дендро" id="26">
|
||||
<DataPath>Дендро</DataPath>
|
||||
<TitleLocation>None</TitleLocation>
|
||||
<ContextMenu name="ДендроКонтекстноеМеню" id="27"/>
|
||||
<ExtendedTooltip name="ДендроРасширеннаяПодсказка" id="28"/>
|
||||
</DendrogramField>
|
||||
<PlannerField name="Планировщик" id="29">
|
||||
<DataPath>Планировщик</DataPath>
|
||||
<TitleLocation>None</TitleLocation>
|
||||
<ContextMenu name="ПланировщикКонтекстноеМеню" id="30"/>
|
||||
<ExtendedTooltip name="ПланировщикРасширеннаяПодсказка" id="31"/>
|
||||
</PlannerField>
|
||||
</ChildItems>
|
||||
<Attributes>
|
||||
<Attribute name="Объект" id="26">
|
||||
<Attribute name="Объект" id="32">
|
||||
<Type>
|
||||
<v8:Type>cfg:DataProcessorObject.Диаграммы</v8:Type>
|
||||
</Type>
|
||||
<MainAttribute>true</MainAttribute>
|
||||
</Attribute>
|
||||
<Attribute name="Диаграмма" id="27">
|
||||
<Attribute name="Диаграмма" id="33">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
@@ -84,7 +96,7 @@
|
||||
<v8:Type xmlns:d5p1="http://v8.1c.ru/8.2/data/chart">d5p1:Chart</v8:Type>
|
||||
</Type>
|
||||
</Attribute>
|
||||
<Attribute name="Схема" id="28">
|
||||
<Attribute name="Схема" id="34">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
@@ -95,7 +107,7 @@
|
||||
<v8:Type xmlns:d5p1="http://v8.1c.ru/8.2/data/graphscheme">d5p1:FlowchartContextType</v8:Type>
|
||||
</Type>
|
||||
</Attribute>
|
||||
<Attribute name="Период" id="29">
|
||||
<Attribute name="Период" id="35">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
@@ -106,7 +118,7 @@
|
||||
<v8:Type>v8:StandardPeriod</v8:Type>
|
||||
</Type>
|
||||
</Attribute>
|
||||
<Attribute name="Ганта" id="30">
|
||||
<Attribute name="Ганта" id="36">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
@@ -117,5 +129,123 @@
|
||||
<v8:Type xmlns:d5p1="http://v8.1c.ru/8.2/data/chart">d5p1:GanttChart</v8:Type>
|
||||
</Type>
|
||||
</Attribute>
|
||||
<Attribute name="Дендро" id="37">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Дендро</v8:content>
|
||||
</v8:item>
|
||||
</Title>
|
||||
<Type>
|
||||
<v8:Type xmlns:d5p1="http://v8.1c.ru/8.2/data/chart">d5p1:Dendrogram</v8:Type>
|
||||
</Type>
|
||||
</Attribute>
|
||||
<Attribute name="Планировщик" id="38">
|
||||
<Title>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>Планировщик</v8:content>
|
||||
</v8:item>
|
||||
</Title>
|
||||
<Type>
|
||||
<v8:Type xmlns:pl="http://v8.1c.ru/8.3/data/planner">pl:Planner</v8:Type>
|
||||
</Type>
|
||||
<Settings xmlns:pl="http://v8.1c.ru/8.3/data/planner" xsi:type="pl:Planner">
|
||||
<pl:item>
|
||||
<pl:value xsi:nil="true"/>
|
||||
<pl:text>Встреча</pl:text>
|
||||
<pl:tooltip/>
|
||||
<pl:begin>2026-06-09T01:00:00</pl:begin>
|
||||
<pl:end>2026-06-09T04:00:00</pl:end>
|
||||
<pl:borderColor>auto</pl:borderColor>
|
||||
<pl:backColor>auto</pl:backColor>
|
||||
<pl:textColor>auto</pl:textColor>
|
||||
<pl:font kind="AutoFont"/>
|
||||
<pl:dimensionValues/>
|
||||
<pl:replacementDate>0001-01-01T00:00:00</pl:replacementDate>
|
||||
<pl:deleted>false</pl:deleted>
|
||||
<pl:id>UUID-001</pl:id>
|
||||
<pl:textFormatted>false</pl:textFormatted>
|
||||
<pl:border width="1">
|
||||
<v8ui:style xsi:type="v8ui:ControlBorderType">Single</v8ui:style>
|
||||
</pl:border>
|
||||
<pl:editMode>EnableEdit</pl:editMode>
|
||||
</pl:item>
|
||||
<pl:borderColor>auto</pl:borderColor>
|
||||
<pl:backColor>auto</pl:backColor>
|
||||
<pl:textColor>auto</pl:textColor>
|
||||
<pl:lineColor>auto</pl:lineColor>
|
||||
<pl:font kind="AutoFont"/>
|
||||
<pl:beginOfRepresentationPeriod>0001-01-01T00:00:00</pl:beginOfRepresentationPeriod>
|
||||
<pl:endOfRepresentationPeriod>0001-01-01T00:00:00</pl:endOfRepresentationPeriod>
|
||||
<pl:alignElementsOfTimeScale>true</pl:alignElementsOfTimeScale>
|
||||
<pl:displayTimeScaleWrapHeaders>true</pl:displayTimeScaleWrapHeaders>
|
||||
<pl:displayWrapHeaders>true</pl:displayWrapHeaders>
|
||||
<pl:timeScaleWrapHeadersFormat>
|
||||
<v8:item>
|
||||
<v8:lang>#</v8:lang>
|
||||
<v8:content>DLF="DD"</v8:content>
|
||||
</v8:item>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>DLF="DD"</v8:content>
|
||||
</v8:item>
|
||||
</pl:timeScaleWrapHeadersFormat>
|
||||
<pl:periodicVariantUnit>Day</pl:periodicVariantUnit>
|
||||
<pl:periodicVariantRepetition>1</pl:periodicVariantRepetition>
|
||||
<pl:timeScaleWrapBeginIndent>0</pl:timeScaleWrapBeginIndent>
|
||||
<pl:timeScaleWrapEndIndent>0</pl:timeScaleWrapEndIndent>
|
||||
<pl:timeScale>
|
||||
<placement xmlns="http://v8.1c.ru/8.2/data/chart">Left</placement>
|
||||
<level xmlns="http://v8.1c.ru/8.2/data/chart">
|
||||
<measure>Hour</measure>
|
||||
<interval>1</interval>
|
||||
<show>true</show>
|
||||
<line width="1" gap="false">
|
||||
<v8ui:style xsi:type="v8ui:ChartLineType">Solid</v8ui:style>
|
||||
</line>
|
||||
<scaleColor>auto</scaleColor>
|
||||
<dayFormatRule>MonthDayWeekDay</dayFormatRule>
|
||||
<format>
|
||||
<v8:item>
|
||||
<v8:lang>#</v8:lang>
|
||||
<v8:content>DF="HH:mm"</v8:content>
|
||||
</v8:item>
|
||||
<v8:item>
|
||||
<v8:lang>ru</v8:lang>
|
||||
<v8:content>DF="HH:mm"</v8:content>
|
||||
</v8:item>
|
||||
</format>
|
||||
<labels>
|
||||
<ticks>0</ticks>
|
||||
</labels>
|
||||
<backColor>auto</backColor>
|
||||
<textColor>auto</textColor>
|
||||
<showPereodicalLabels>true</showPereodicalLabels>
|
||||
</level>
|
||||
<transparent xmlns="http://v8.1c.ru/8.2/data/chart">false</transparent>
|
||||
<backColor xmlns="http://v8.1c.ru/8.2/data/chart">auto</backColor>
|
||||
<textColor xmlns="http://v8.1c.ru/8.2/data/chart">auto</textColor>
|
||||
<currentLevel xmlns="http://v8.1c.ru/8.2/data/chart">0</currentLevel>
|
||||
</pl:timeScale>
|
||||
<pl:period>
|
||||
<pl:begin>2026-06-09T00:00:00</pl:begin>
|
||||
<pl:end>2026-06-09T23:59:59</pl:end>
|
||||
</pl:period>
|
||||
<pl:displayCurrentDate>true</pl:displayCurrentDate>
|
||||
<pl:itemsTimeRepresentation>BeginTime</pl:itemsTimeRepresentation>
|
||||
<pl:itemsBehaviorWhenSpaceInsufficient>CollapseItems</pl:itemsBehaviorWhenSpaceInsufficient>
|
||||
<pl:autoMinColumnWidth>true</pl:autoMinColumnWidth>
|
||||
<pl:autoMinRowHeight>true</pl:autoMinRowHeight>
|
||||
<pl:minColumnWidth>0</pl:minColumnWidth>
|
||||
<pl:minRowHeight>0</pl:minRowHeight>
|
||||
<pl:fixDimensionsHeader>auto</pl:fixDimensionsHeader>
|
||||
<pl:fixTimeScaleHeader>auto</pl:fixTimeScaleHeader>
|
||||
<pl:border width="1">
|
||||
<v8ui:style xsi:type="v8ui:ControlBorderType">Single</v8ui:style>
|
||||
</pl:border>
|
||||
<pl:newItemsTextType>String</pl:newItemsTextType>
|
||||
</Settings>
|
||||
</Attribute>
|
||||
</Attributes>
|
||||
</Form>
|
||||
|
||||
Reference in New Issue
Block a user