미리보기에 태그 값이 흐를 관을 판다 — 값 아니면 사유

미리보기 레거시 호환 계획의 A1.

지금까지 미리보기는 태그를 <b>글자 그대로</b> 찍었다 — PAT_이름 이 종이에 그렇게 인쇄됐다.
값이 흐를 관이 아예 없었다.

<b>해석기를 인터페이스로 둔다.</b> 오늘 값이 나오는 것은 서버 시각·로그인 사용자 16종
(운영 사용 579건, 9.1%)뿐이고 나머지 368종은 환자·내원 문맥이 있어야 한다.
그 문맥이 생기면 <b>같은 자리로</b> 더 강한 해석기가 들어온다 — 관을 지금 파 두고 해석기만 갈아 끼운다.
A1 의 값어치는 9.1% 가 아니라 그 관이다.

<b>못 만든 값을 감추지 않는다.</b> 값이 나오면 값을, 안 나오면 사유를 대괄호로 감싸 그린다 —
[PAT_차트번호 — 환자·내원 정보가 있어야 값이 나오는 태그입니다].
빈칸으로 두면 서식이 잘못된 줄 알고, 태그 이름을 그대로 두면 값이 나온 줄 안다.
레거시도 같은 문제를 같은 이유로 다뤘다 — 실패한 컨트롤을 노란색으로 칠했다
(ucLoadSheetBase.vb:2300-2308). 그 장치가 있다는 것 자체가 현장 실패가 흔하다는 방증이다.

주입은 컨테이너 투영과 같은 방식이다 — 모델을 복제해 Text 만 갈아 끼우고 같은 타입의 VM 을 만든다.
<b>캔버스가 쓰는 VM 과 모델은 건드리지 않는다.</b>

DB 는 창당 한 번만 읽는다(재료 왕복 2회). 그리기마다 새로 만들면 다시 그릴 때마다 DB 를 친다 —
레거시가 태그마다 쿼리를 돌려 태그 40개 서식에 왕복 40회를 하는 것과 같은 실수다.

<b>단정은 종이에 찍힌 글자를 본다.</b> VM 속성만 보면 템플릿이 그 값을 쓰는지 알 수 없다 —
배선과 결과는 다른 문제이고, 이 저장소에서 그 둘이 여러 번 갈렸다.
검사용 해석기를 따로 둬 접속 없이도 같은 답이 나오게 했다.

게이트: 테스트 298/298, --edit-smoke 0실패(신규 3), --dialog-shots FAIL 0,
--modal-check 0실패, --cleartype 11/11, --scale-budget 5/5, 빌드 경고 0,
--db-smoke 1271건 diff 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Msystech
2026-08-18 10:04:49 +09:00
co-authored by Claude Opus 5
parent a67b6ee4b8
commit 26e93cae94
5 changed files with 216 additions and 6 deletions
+40 -5
View File
@@ -58,7 +58,8 @@ public static class PrintService
/// 두 눈이 필요해서 미리보기 창이 보기를 전환할 수 있게 열어 둔다.
/// 인쇄는 언제나 true 다 — 인쇄는 인쇄다.
/// </summary>
public static UIElement BuildPageVisual(PageViewModel page, bool printFilter = true)
public static UIElement BuildPageVisual(PageViewModel page, bool printFilter = true,
SheetMe.Core.Catalog.ITagValueResolver? tags = null)
{
var canvas = new Canvas
{
@@ -90,7 +91,7 @@ public static class PrintService
}
var presenter = new ContentPresenter
{
Content = PrintProjection(control, printFilter),
Content = PrintProjection(control, printFilter, tags),
Width = Math.Max(1, control.Width),
Height = Math.Max(1, control.Height),
};
@@ -119,11 +120,12 @@ public static class PrintService
/// 자식 VM 은 새로 만들지 않고 원본을 그대로 담는다 — 해석된 글꼴·색이 유지된다.
/// 캔버스가 쓰는 VM 은 <b>한 글자도 건드리지 않는다.</b>
/// </summary>
private static object PrintProjection(ControlViewModel control, bool printFilter)
private static object PrintProjection(ControlViewModel control, bool printFilter,
SheetMe.Core.Catalog.ITagValueResolver? tags)
{
if (control is not ContainerViewModel container)
{
return control;
return WithTagValue(control, tags);
}
ContainerViewModel? copy = container switch
{
@@ -143,7 +145,7 @@ public static class PrintService
{
continue;
}
if (PrintProjection(child, printFilter) is ControlViewModel projected)
if (PrintProjection(child, printFilter, tags) is ControlViewModel projected)
{
copy.Children.Add(projected);
}
@@ -153,5 +155,38 @@ public static class PrintService
copy.ResolveVisualContext(container.EffectiveFont, container.Foreground);
return copy;
}
/// <summary>
/// 데이터 태그가 붙은 컨트롤을 <b>값이 들어간 사본</b>으로 바꾼다. 태그가 없거나 해석기가 없으면 원본.
///
/// <b>왜 필요한가.</b> 지금 미리보기는 태그를 글자 그대로 찍는다 —
/// <c>PAT_이름</c> 이 종이에 그렇게 인쇄된다. 값이 흐를 관이 아예 없었다.
///
/// 컨테이너 투영과 같은 방식이다 — 모델을 복제해 Text 만 갈아 끼우고 같은 타입의 VM 을 새로 만든다.
/// 타입이 같으니 템플릿이 그대로 잡히고, <b>캔버스가 쓰는 VM 과 모델은 건드리지 않는다.</b>
///
/// <b>못 만든 값은 감추지 않는다.</b> 사유를 대괄호로 감싸 그린다 —
/// 빈칸으로 두면 서식이 잘못된 줄 알고, 태그 이름을 그대로 두면 값이 나온 줄 안다.
/// 레거시는 실패한 컨트롤을 노란색으로 칠했다(같은 문제를 같은 이유로 다뤘다).
/// </summary>
private static object WithTagValue(ControlViewModel control, SheetMe.Core.Catalog.ITagValueResolver? tags)
{
if (tags is null)
{
return control;
}
var tag = control.Model.Props.GetText("DataInterfaceTag");
if (tag is not { Length: > 0 } || tag == "None")
{
return control;
}
var value = tags.Resolve(tag);
var text = value.Resolved ? value.Text
: value.Text.Length > 0 ? $"[{tag} — {value.Text}]" : $"[{tag}]";
var model = control.Model.Clone();
model.Props.SetText("Text", text);
return DocumentMapper.CreateControl(model, control.EffectiveFont, control.Foreground);
}
#endregion
}