마스크 편집기 — 프리셋 목록 + 실시간 미리보기
레거시 MaskedTextBox 는 System.Windows.Forms.MaskedTextBox 를 상속하고 Mask 를 재정의하지 않아 WinForms 기본 마스크 디자이너(프리셋 목록 + 시험 입력)를 그대로 물려받는다. SheetMe 인스펙터는 평범한 텍스트 상자뿐이라 마스크 문법을 외워야 했다. [프리셋] LegacyMaskCatalog — .NET 문화권 기본값(짧은 날짜/전화번호 등) 대신 운영 활성 디자인 전수 census 에서 실제로 쓰이는 마스크를 사용 건수와 함께 제공한다. 기존 서식과 같은 표기를 그대로 고를 수 있어 표기 흔들림이 줄어든다. 날짜/시간/날짜+시간/번호 그룹 + 표준 3종. [미리보기] 두 줄로 보여준다. 빈 값 표시 — 마스크만으로 화면에 어떻게 보이는지(ToPromptDisplay) 시험 입력 — 값을 쳐 보면 어떻게 채워지는지(Apply, 신규) 인스펙터 행에도 '빈 값 표시'를 상시 노출해 편집기를 열지 않아도 확인된다. [Apply 규칙] 구현 중 모호한 경우가 드러나 규칙을 단순하게 확정했다. 1) 리터럴은 항상 그대로 출력되고 입력을 소비하지 않는다. 2) 지시자는 입력에서 자기에게 맞는 첫 문자를 가져오며, 맞지 않는 문자와 공백은 건너뛴다. 값만 치든(20260812) 구분자를 같이 치든(2026-08-12, 2026년 08월 12일) 결과가 같아진다. 공백을 건너뛰는 이유는 '9' 가 공백도 받아들이기 때문이다 — 그대로 두면 구분자 공백이 데이터 자리를 먹어 한 칸씩 밀린다. '9' 의 공백 허용은 빈 자리를 위한 것이고 그건 프롬프트 문자가 이미 표현한다. 한계를 코드에 명시했다: 리터럴이 숫자인 마스크(2\000년 — 운영 460건 중 1건)는 사용자가 리터럴까지 치면 어디까지가 데이터인지 원리적으로 가릴 수 없다. 편집 가능한 자리만 치면 된다. 미리보기용이므로 휴리스틱을 쌓기보다 규칙을 단순하게 두는 편이 낫다고 판단했다. 안내문에서 백슬래시를 글리프로 보여주지 않는다 — 한글 글꼴에서 원화 기호로 렌더되어 오해를 부른다. 검증: 테스트 124/124(마스크 26건 추가 — Apply 자리 채움/구분자 무시/유효성 거부/대소문자 변환자/ 이스케이프/공백 처리, 프리셋 형식·중복·운영 다빈도 포함 검사). edit-smoke 실패 0, 왕복 1,271건 diff 0/예외 0. 실제 UI 로 대화상자 열어 프리셋 그룹·건수·두 줄 미리보기 확인. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
a749e18e7b
commit
68f0fbd5a3
@@ -167,6 +167,40 @@ public sealed class TagPickerRowViewModel : PropertyRowViewModel
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 마스크 행 — 값과 표시 미리보기를 함께 보여주고, 찾아보기로 프리셋 편집기를 연다.
|
||||
/// 레거시는 WinForms 기본 마스크 디자이너(프리셋 + 시험 입력)를 제공했다.
|
||||
/// </summary>
|
||||
public sealed class MaskRowViewModel : PropertyRowViewModel
|
||||
{
|
||||
/// <summary>이 마스크가 화면에 어떻게 보이는지 — 인스펙터에서 바로 확인</summary>
|
||||
public string Preview => ValueText.Length == 0
|
||||
? "(마스크 없음)"
|
||||
: SheetMe.Core.Serialization.LegacyMask.ToPromptDisplay(ValueText);
|
||||
|
||||
/// <summary>마스크 편집기 열기</summary>
|
||||
public M.Framework.WPF.ICustomCommand? BrowseCommand { get; set; }
|
||||
|
||||
public MaskRowViewModel(string label) : base(label)
|
||||
{
|
||||
BrowseCommand = new M.Framework.WPF.Command((sender, e) => OnBrowse());
|
||||
}
|
||||
|
||||
protected override void OnValueApplied() => OnPropertyChanged(nameof(Preview));
|
||||
|
||||
private void OnBrowse()
|
||||
{
|
||||
var dialog = new Views.MaskPickerDialogView(ValueText)
|
||||
{
|
||||
Owner = System.Windows.Application.Current.MainWindow,
|
||||
};
|
||||
if (dialog.ShowDialog() == true)
|
||||
{
|
||||
ValueText = dialog.Mask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>SQL 쿼리 행 — 요약 표시 + 전용 편집기 창(치환 변수 삽입)</summary>
|
||||
public sealed class QueryRowViewModel : PropertyRowViewModel
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user