레이어 행을 항상 두 줄로 — 둘째 줄에 타입명을 둔다
목록에 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)",
|
Check("레이어: 컨테이너가 자식 수를 말한다", wrapped.LayerChildCountText == "(2)",
|
||||||
wrapped.LayerChildCountText);
|
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 를 두 번 겹치는 경로는 이 검사의 대상이 아니다).
|
// 중첩 구조는 모델로 직접 짠다(Ctrl+G 를 두 번 겹치는 경로는 이 검사의 대상이 아니다).
|
||||||
var nestDoc = new FormDocument();
|
var nestDoc = new FormDocument();
|
||||||
|
|||||||
@@ -199,6 +199,33 @@ public abstract class ControlViewModel : ViewModelBase, ILayerRow
|
|||||||
/// <summary>이름 칸을 그릴지 — 문구와 이름이 다를 때만</summary>
|
/// <summary>이름 칸을 그릴지 — 문구와 이름이 다를 때만</summary>
|
||||||
public bool HasLayerId => LayerId.Length > 0;
|
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>
|
/// <summary>레이어 잠금 토글 아이콘명</summary>
|
||||||
public string LockIcon => Model.Locked ? "lock" : "unlock";
|
public string LockIcon => Model.Locked ? "lock" : "unlock";
|
||||||
|
|
||||||
|
|||||||
@@ -349,10 +349,16 @@
|
|||||||
</Style>
|
</Style>
|
||||||
</TextBlock.Style>
|
</TextBlock.Style>
|
||||||
</TextBlock>
|
</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"
|
TextTrimming="CharacterEllipsis"
|
||||||
ToolTip="컨트롤 이름 — 다른 속성이 이 이름으로 참조합니다"
|
ToolTip="{Binding LayerSubText}">
|
||||||
Visibility="{Binding HasLayerId, Converter={StaticResource BoolToVisibility}}">
|
|
||||||
<TextBlock.Style>
|
<TextBlock.Style>
|
||||||
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource B.Muted}"/>
|
<Setter Property="Foreground" Value="{DynamicResource B.Muted}"/>
|
||||||
|
|||||||
Reference in New Issue
Block a user