From d72ab3ce1e76751359cfc060eec6021dfd30d0f1 Mon Sep 17 00:00:00 2001 From: Msystech Date: Fri, 14 Aug 2026 17:30:11 +0900 Subject: [PATCH] =?UTF-8?q?=EC=9D=B8=EC=8A=A4=ED=8E=99=ED=84=B0=EA=B0=80?= =?UTF-8?q?=20=EC=86=90=EC=9D=84=20=EB=86=93=EC=A7=80=20=EC=95=8A=EB=8A=94?= =?UTF-8?q?=EB=8B=A4,=20=EA=B7=B8=EB=A6=AC=EA=B3=A0=20=EC=A0=80=EC=9E=A5?= =?UTF-8?q?=20=ED=99=95=EC=9D=B8=EC=9D=B4=20=EC=82=AC=EB=9E=8C=20=EB=A7=90?= =?UTF-8?q?=EC=9D=84=20=ED=95=9C=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 3단계 계속. ① 선택이 바뀌면 편집하던 칸과 스크롤이 사라졌다. 선택 집합이 바뀔 때마다 Rows.Clear() 로 행을 통째로 다시 만들기 때문이다. 하루 수백 건을 다루는 사람에게 그건 "다음 컨트롤로 넘어가면 손이 처음으로 돌아간다"는 뜻이다 — 라벨 20개의 글꼴을 차례로 고치는 일이 20번의 스크롤·클릭이 된다. 행을 키 기준 갱신으로 바꾸는 쪽이 더 근본적이지만 이번에는 하지 않는다. 이 패널은 회귀 기록이 가장 많은 곳이고(MainView.xaml:321-322, LayerPanelView.xaml:127-129), 실제 아픔은 재구성 비용이 아니라 포커스·스크롤 소실이다 (--scale-budget 이 뷰모델 작업은 마이크로초 단위임을 보여 준다). 그래서 재구성은 그대로 두고 포커스와 스크롤만 되돌린다. 행은 라벨로 찾는다 — 타입이 달라도 같은 이름의 행(글꼴·정렬·표시)은 같은 일을 한다. Rebuild 를 감쌌다. 본문에 이른 return 이 여러 갈래 있어서 끝에 이벤트를 두면 도는 경로와 안 도는 경로가 갈리고, 그러면 어떤 선택 변경에서만 포커스가 안 돌아온다 — 그런 결함은 재현 조건을 찾기 전까지 "가끔 그런다"로만 보인다. 복원은 DispatcherPriority.Loaded 로 미룬다. 즉시 부르면 컨테이너가 아직 없어 빈 트리를 뒤진다 (이 세션에서 같은 함정을 두 번 밟았다). 사용자가 그 사이 다른 칸을 눌렀으면 포커스를 빼앗지 않는다. ② F4 로 인스펙터에 들어간다. 인스펙터로 포커스를 보내는 키가 저장소에 하나도 없었다. 캔버스에서 Tab 을 누르면 좌측 패널·문서 탭·플로팅 바를 다 지나야 인스펙터에 닿았다. 커맨드로 만들지 않는다 — 그러면 뷰모델이 뷰의 포커스를 알아야 한다. ③ 저장 확인 문면을 두 층으로 갈랐다. 이 대화상자는 세 부류가 다 보는 유일한 위험 지점인데(사내 인력·병원 전산팀·의료진), 본문에 E_SdgMst/E_SctMst, SdgDelYon='Y', ShtCneYon='Y' 가 그대로 노출되어 있었다. 사내 인력에게는 정확한 정보이고, 전산팀에게는 읽을 수 없는 문장이고, 간호부에게는 공포다. 위층은 사람 말("이 서식의 새 버전을 만듭니다. 지금 쓰이는 버전은 이력으로 남습니다"), 테이블·컬럼은 접힌 상세로 내렸다. 게이트: 테스트 285/285, --edit-smoke 0실패, --dialog-shots 글자 2,465개 검사 넘침 0, --modal-check 0실패, --scale-budget 5/5, --maxrect 0실패, --cleartype 11/11, 빌드 경고 0, --db-smoke 1271건 diff 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일. Co-Authored-By: Claude Opus 5 --- .../Inspector/InspectorViewModel.cs | 30 ++++ .../ViewModels/MainViewModel.cs | 18 ++- src/SheetMe.Designer/Views/InspectorView.xaml | 4 +- .../Views/InspectorView.xaml.cs | 146 +++++++++++++++++- src/SheetMe.Designer/Views/MainView.xaml | 6 +- src/SheetMe.Designer/Views/MainView.xaml.cs | 17 ++ 6 files changed, 214 insertions(+), 7 deletions(-) diff --git a/src/SheetMe.Designer/ViewModels/Inspector/InspectorViewModel.cs b/src/SheetMe.Designer/ViewModels/Inspector/InspectorViewModel.cs index bb75faa..c77f4bb 100644 --- a/src/SheetMe.Designer/ViewModels/Inspector/InspectorViewModel.cs +++ b/src/SheetMe.Designer/ViewModels/Inspector/InspectorViewModel.cs @@ -298,8 +298,38 @@ public sealed class InspectorViewModel : ViewModelBase } } + /// + /// 행이 통째로 다시 만들어지려는 순간 / 다 만들어진 순간. + /// + /// 뷰가 포커스와 스크롤을 되돌려 놓는 데 쓴다. 선택이 바뀌면 를 비우고 + /// 새로 만들기 때문에, 그대로 두면 컨트롤을 옮길 때마다 편집하던 칸과 스크롤 위치가 사라진다. + /// 하루 수백 건을 다루는 사람에게 그건 "다음 것으로 넘어가면 손이 처음으로 돌아간다"는 뜻이다. + /// + /// 행 컬렉션을 키 기준 갱신으로 바꾸는 쪽이 더 근본적이지만, 이 패널은 회귀 기록이 가장 많은 곳이라 + /// 이번에는 손대지 않는다. 실제 아픔은 재구성 비용이 아니라 포커스·스크롤 소실이고 + /// (--scale-budget 이 뷰모델 작업은 마이크로초 단위임을 보여 준다) 그것만 되돌려도 손이 이어진다. + /// + public event Action? Rebuilding; + + public event Action? Rebuilt; + /// 행 재구성 — 선택 집합 변경 시 public void Rebuild() + { + // 감싸는 이유: 본문에 이른 return 이 여러 갈래 있어, 끝에 이벤트를 두면 + // 도는 경로와 안 도는 경로가 갈린다. 그러면 어떤 선택 변경에서는 포커스가 안 돌아온다. + Rebuilding?.Invoke(); + try + { + RebuildCore(); + } + finally + { + Rebuilt?.Invoke(); + } + } + + private void RebuildCore() { Rows.Clear(); boundsRows.Clear(); diff --git a/src/SheetMe.Designer/ViewModels/MainViewModel.cs b/src/SheetMe.Designer/ViewModels/MainViewModel.cs index b8f86da..308e61d 100644 --- a/src/SheetMe.Designer/ViewModels/MainViewModel.cs +++ b/src/SheetMe.Designer/ViewModels/MainViewModel.cs @@ -679,10 +679,22 @@ internal sealed class MainViewModel : ViewModelBase document.Title = register.SheetName; } + // 문면을 두 층으로 가른다. + // + // 이 대화상자는 세 부류가 다 보는 유일한 위험 지점이다 — + // 사내 개발·지원, 병원 전산팀, 의료진·간호부. 그런데 본문에 + // E_SdgMst/E_SctMst, SdgDelYon='Y', ShtCneYon='Y' 가 그대로 노출되어 있었다. + // 사내 인력에게는 정확한 정보이고, 전산팀에게는 읽을 수 없는 문장이고, + // 간호부에게는 공포다. 위층은 사람 말로, 테이블·컬럼은 접힌 아래층에 둔다 + // (상세는 접혀 있고 사내 인력이 펼쳐 본다). + var inPlace = "제자리 갱신 서식이면 지금 버전이 바로 갱신됩니다."; var confirm = DialogService.Confirm("DB 저장 확인", - $"서식 [{document.FormId}] {document.Title} 을(를) DB(E_SdgMst/E_SctMst)에 저장할까요?", - "기존 활성 디자인은 이력(SdgDelYon='Y')으로 보존되고 새 버전이 생성됩니다.\n" + - "(제자리 갱신 서식(ShtCneYon='Y')은 기존 버전이 갱신됩니다)", + $"[{document.FormId}] {document.Title} — 이 서식의 새 버전을 만듭니다.", + "지금 쓰이는 버전은 이력으로 남고, 앞으로는 새 버전이 열립니다.\n" + + inPlace + "\n\n" + + "기술 정보 — E_SdgMst/E_SctMst 에 기록합니다. " + + "기존 활성 디자인은 SdgDelYon='Y' 로 이력 전환되고 새 SdgKey 가 생성됩니다. " + + "ShtCneYon='Y' 서식은 기존 버전을 갱신합니다.", yes: "저장", no: "취소"); if (!confirm) { diff --git a/src/SheetMe.Designer/Views/InspectorView.xaml b/src/SheetMe.Designer/Views/InspectorView.xaml index d27706f..28bb921 100644 --- a/src/SheetMe.Designer/Views/InspectorView.xaml +++ b/src/SheetMe.Designer/Views/InspectorView.xaml @@ -892,8 +892,8 @@ ToolTip="{Binding PageScopeTip}"/> - - + +