레이어 행을 항상 두 줄로 — 둘째 줄에 타입명을 둔다
목록에 1줄 행과 2줄 행이 섞여 있었다. 둘째 줄(이름)이 <b>표시명과 다를 때만</b> 나왔기 때문이다 — 문구가 없는 컨트롤은 표시명이 곧 이름이라 한 줄로 그려졌다. 훑을 때 눈이 매번 자리를 다시 잡아야 하고, 어느 행이 어디서 끝나는지 리듬이 없다. ## 둘째 줄에 무엇을 두는가 <b>타입명</b>이다. 아이콘만으로는 안 갈리는 짝이 실제로 있다 — 라벨과 마스크입력이 같은 글리프를 쓰고, 리스트박스와 체크리스트도 같다. 그래서 아이콘의 단순 중복이 아니다. 이름(Id)은 <b>더할 정보가 있을 때만</b> 붙인다. 세 갈래로 갈린다. - 문구가 없다(표시명 = 이름) → 타입명만. "TextBox1 / 텍스트박스" - 갓 놓았다(문구가 타입명 그대로) → 이름만. 윗줄이 이미 타입을 말했다. "라디오버튼 / RadioButton1" - 사람이 문구를 썼다 → 둘 다. "환자명 / 라벨 · Label1" 같은 글자가 두 줄에 두 번 나오는 경우가 하나도 없도록 셋을 다 검사로 고정했다. 이름을 계속 보여 주는 이유는 그것이 <b>외부 참조 키</b>이기 때문이다 — 수식(RadioButton1+CheckBox3)·액션 대상 컨트롤·이벤트 매핑이 이름 문자열로 서로를 가리킨다. ## 값을 치르는 것 행 높이가 일정해진 대신 문구 없는 컨트롤이 많은 서식에서 목록이 길어진다. 사용자가 리듬 쪽을 택했고, 타입명이 아이콘 모호성까지 함께 없애므로 값은 한다. ## 판정 - 단위 시험 388 · edit-smoke 400건 전건 통과 (레이어 둘째 줄 5건 추가) - --dialog-shots 69장 전건 통과 (레이어 4종을 눈으로 대조 — 행 높이 균일 확인) - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
8c76a978a9
commit
6a0331ec8a
@@ -1229,6 +1229,37 @@ public static class EditSmoke
|
||||
Check("레이어: 컨테이너가 자식 수를 말한다", wrapped.LayerChildCountText == "(2)",
|
||||
wrapped.LayerChildCountText);
|
||||
|
||||
// 둘째 줄은 <b>항상</b> 있어야 한다 — 없으면 1줄/2줄이 섞여 훑는 리듬이 깨진다.
|
||||
// 세 갈래를 다 본다: 문구 없음 / 문구가 타입명 그대로(갓 놓은 것) / 사람이 쓴 문구.
|
||||
var fresh = wrapped.Children[0]; // 갓 놓은 라디오 — 문구가 "라디오버튼"이다
|
||||
Check("레이어: 갓 놓은 것은 둘째 줄이 이름뿐이다(타입명 중복 없음)",
|
||||
fresh.LayerSubText == fresh.Id,
|
||||
$"'{fresh.LayerName}' / '{fresh.LayerSubText}'");
|
||||
|
||||
var bare = new ControlElement
|
||||
{
|
||||
Type = "TextBox", Id = "TextBox9",
|
||||
Bounds = new LayoutRect { X = 10, Y = 10, W = 100, H = 20 },
|
||||
};
|
||||
var bareDoc = new FormDocument();
|
||||
var barePage = new FormPage { Width = 720, Height = 856 };
|
||||
barePage.Controls.Add(bare);
|
||||
bareDoc.Pages.Add(barePage);
|
||||
var bareVm = new DesignerViewModel(bareDoc).Pages[0].Controls[0];
|
||||
Check("레이어: 문구가 없는 행도 둘째 줄이 있다", bareVm.LayerSubText.Length > 0,
|
||||
$"'{bareVm.LayerName}' / '{bareVm.LayerSubText}'");
|
||||
Check("레이어: 문구가 없으면 둘째 줄은 타입명이다", bareVm.LayerSubText == "텍스트박스",
|
||||
bareVm.LayerSubText);
|
||||
Check("레이어: 같은 글자를 두 줄에 두 번 쓰지 않는다",
|
||||
!bareVm.LayerSubText.Contains(bareVm.Id, StringComparison.Ordinal),
|
||||
$"Id={bareVm.Id} 둘째줄='{bareVm.LayerSubText}'");
|
||||
|
||||
bare.Props.SetText("Text", "환자명");
|
||||
var named = new DesignerViewModel(bareDoc).Pages[0].Controls[0];
|
||||
Check("레이어: 사람이 쓴 문구면 타입·이름을 함께 보여 준다",
|
||||
named.LayerSubText == "텍스트박스 · TextBox9",
|
||||
$"'{named.LayerName}' / '{named.LayerSubText}'");
|
||||
|
||||
// 중첩까지 센다 — "이걸 지우면 몇 개가 같이 지워지나"가 그 수다.
|
||||
// 중첩 구조는 모델로 직접 짠다(Ctrl+G 를 두 번 겹치는 경로는 이 검사의 대상이 아니다).
|
||||
var nestDoc = new FormDocument();
|
||||
|
||||
@@ -199,6 +199,33 @@ public abstract class ControlViewModel : ViewModelBase, ILayerRow
|
||||
/// <summary>이름 칸을 그릴지 — 문구와 이름이 다를 때만</summary>
|
||||
public bool HasLayerId => LayerId.Length > 0;
|
||||
|
||||
/// <summary>
|
||||
/// 레이어 행 둘째 줄 — <b>항상</b> 있다. 그래야 행 높이가 일정하다.
|
||||
///
|
||||
/// 전에는 표시명이 곧 Id 인 행(문구가 없는 컨트롤)에서 둘째 줄이 통째로 빠져
|
||||
/// 목록에 1줄과 2줄이 섞였다. 훑을 때 리듬이 깨지고, 어느 행이 무엇인지
|
||||
/// 눈이 매번 다시 자리를 잡아야 했다.
|
||||
///
|
||||
/// <b>타입명을 앞에 둔다.</b> 아이콘만으로는 타입이 안 갈리는 짝이 실제로 있다 —
|
||||
/// 라벨과 마스크입력이 같은 글리프를 쓰고, 리스트박스와 체크리스트도 같다.
|
||||
/// 이름(Id)은 표시명과 다를 때만 뒤에 붙인다 — 같으면 윗줄과 같은 글자를 두 번 쓰는 셈이다.
|
||||
/// 이름을 계속 보여 주는 이유는 그것이 <b>외부 참조 키</b>이기 때문이다(수식·액션 대상·이벤트 규약).
|
||||
/// </summary>
|
||||
public string LayerSubText
|
||||
{
|
||||
get
|
||||
{
|
||||
var typeName = SheetMe.Core.Catalog.ControlRegistry.Find(Type)?.DisplayName ?? Type;
|
||||
// 이름이 곧 표시명이면(문구 없는 컨트롤) 타입만 — 같은 글자를 두 번 쓰지 않는다
|
||||
if (!HasLayerId)
|
||||
{
|
||||
return typeName;
|
||||
}
|
||||
// 갓 놓은 컨트롤은 문구가 타입명 그대로다("라디오버튼") — 윗줄이 이미 타입을 말했으므로 이름만
|
||||
return LayerName == typeName ? LayerId : $"{typeName} · {LayerId}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>레이어 잠금 토글 아이콘명</summary>
|
||||
public string LockIcon => Model.Locked ? "lock" : "unlock";
|
||||
|
||||
|
||||
@@ -349,10 +349,16 @@
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
<TextBlock Text="{Binding LayerId}" FontSize="10.5" Margin="0,1,0,0"
|
||||
<!--
|
||||
둘째 줄은 <b>항상</b> 있다 — 없으면 목록에 1줄 행과 2줄 행이 섞여
|
||||
훑을 때 눈이 매번 자리를 다시 잡아야 한다.
|
||||
타입명을 앞에 두는 이유: 아이콘만으로 안 갈리는 짝이 실제로 있다
|
||||
(라벨·마스크입력이 같은 글리프, 리스트박스·체크리스트도 같다).
|
||||
이름(Id)은 표시명과 다를 때만 뒤에 붙는다 — 외부 참조 키라 계속 보여야 한다.
|
||||
-->
|
||||
<TextBlock Text="{Binding LayerSubText}" FontSize="10.5" Margin="0,1,0,0"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
ToolTip="컨트롤 이름 — 다른 속성이 이 이름으로 참조합니다"
|
||||
Visibility="{Binding HasLayerId, Converter={StaticResource BoolToVisibility}}">
|
||||
ToolTip="{Binding LayerSubText}">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
||||
<Setter Property="Foreground" Value="{DynamicResource B.Muted}"/>
|
||||
|
||||
Reference in New Issue
Block a user