592275fa97abb153e1a12221cffba12a6916ce51
9
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
592275fa97 |
미리보기 툴바를 아이콘으로 — 버튼 여덟 개가 글자 벽이었다
인쇄… / 새로 고침 / 인쇄될 것만 / 환자 선택… / 환자 해제 / 데이터소스… / 누른 것 초기화 / - / 100% / + 가 전부 글자로 한 줄에 늘어서 있었다. 무엇이 명령이고 무엇이 상태인지 구분되지 않고, 이름이 긴 것들이 자리를 다 먹어 종이 위 툴바가 화면의 한 조각을 차지했다. 셸 제목줄의 아이콘 줄과 같은 규범으로 맞춘다 — 이름은 툴팁이 받는다. <b>글자로 남긴 것은 값과 상태뿐이다.</b> 고른 환자 이름과 배율 — 둘 다 아이콘으로 대신할 수 없는 정보다. ## 버튼 두 개를 하나로 합쳤다 '환자 선택'과 '환자 해제'가 나란히 있었다. 셸 제목줄은 같은 일을 아이콘 하나로 한다 — 안 골랐으면 바로 선택 창, 이미 골랐으면 바꾸기·해제 메뉴다. 늘 보이는 자리에서 '누르면 해제'로 두면 실수로 지운다는 것이 그 설계의 이유였고, 여기도 같은 자리다. 고른 상태는 아이콘 색으로 알린다. 안 고른 상태의 색을 <b>B.Muted 로 명시</b>했다 — null 을 넘기면 하드코딩 검정으로 칠해져 어두운 툴바에서 혼자 묻힌다(제목줄에서 실제로 겪은 결함이라 같은 실수를 반복하지 않는다). ## 아이콘은 실제로 있는 것만 골랐다 카탈로그에 없는 이름을 쓰면 조용히 대체 글리프로 떨어진다 — 쓰려던 refresh-cw · user-x · database · eraser 는 없어서 rotate-cw · table · undo-2 로 바꿨다(90종 중 실재하는 것만 확인해 썼다). '인쇄될 것만'은 토글이라 눌린 상태가 곧 '인쇄 기준'이라는 뜻이 된다 — 툴팁이 양쪽을 설명한다. ## 값을 치르는 것 글자가 사라져 처음 쓰는 사람은 툴팁을 한 번 훑어야 한다. 이 도구를 며칠에 한 번 쓰는 사용자에게는 실제 비용이다 — 다만 제목줄이 이미 같은 방식이라 규범이 하나로 모이는 쪽이 낫다고 봤다. ## 판정 - 단위 시험 388 · edit-smoke 405건 전건 통과 - --dialog-shots 69장 전건 통과 — 미리보기 툴바를 잘라 2배로 키워 다크·라이트 양쪽을 눈으로 확인 - --modal-check · --maxrect · --scale-budget 전건 통과 - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
12e5ec6452 |
열리는 창들의 결을 통일한다 — 타이틀바와 강조 버튼
## 창 열둘 중 하나만 우리 옷을 입고 있었다 커스텀 크롬을 가진 것은 메인 셸과 MessageDialogView 둘뿐이었고, 나머지 열한 창(서식 이력·데이터소스 배선·글꼴 관리자·태그 선택·쿼리 편집기·마스크· 환자 선택·데이터소스 결과·레이어 필터·서식 등록·미리보기)은 <b>윈도우 기본 타이틀바</b>를 달고 떴다. 다크 테마에서 어두운 앱 위에 OS 바가 얹히고, 높이·글자·모서리·닫기 버튼 모양이 전부 달라 "다른 프로그램이 열렸다"로 보였다. 열한 창이 이미 전부 ThemedWindow 를 걸고 있었으므로, 그 옆에 템플릿을 가진 ThemedDialogWindow 를 만들고 각 창은 <b>스타일 이름 한 줄</b>만 바꿨다. 창마다 타이틀바 markup 을 복사했다면 다음에 또 갈라진다. ## WindowChrome 은 스타일로 줄 수 없었다 두 번 막혔고 둘 다 같은 뿌리다 — WindowChrome 은 Freezable 인데 창에 붙으면서 스스로 속성을 고친다. Setter.Value 에 두면 열한 창이 <b>한 인스턴스를 나눠 쓰다</b> 두 번째 창부터 "읽기 전용 상태라 속성을 설정할 수 없습니다"로 죽었다. x:Shared="False" 로도 안 됐다 — 공유되는 것은 리소스가 아니라 Setter 가 이미 붙든 값이다. 그래서 ctl:DialogChrome 첨부 속성이 창마다 새 인스턴스를 만들어 붙인다. 템플릿 안 닫기 버튼은 Click 핸들러를 가질 수 없으므로(템플릿에 코드비하인드가 없다) 표준 SystemCommands.CloseWindowCommand 를 쓰고 그 CommandBinding 도 여기서 단다. DialogResult 를 건드리지 않으므로 ShowDialog 는 false 를 돌려주고 호출부의 '취소' 경로가 그대로 탄다. 최대화 보정도 같이 건다. WindowStyle=None 인 창은 최대화하는 순간 작업표시줄을 덮는데 (메인 창에서 겪은 결함이다) 대화상자 열 개가 크기 조절 가능이라 타이틀바 더블클릭으로 그 상태에 들어갈 수 있다. ## 진단이 바로 그 부분에 눈이 없었다 --dialog-shots 는 window.Content 만 찍고 있었다. 그래서 이 결함을 <b>한 번도 보여 준 적이 없다</b> — MessageDialogView 만 타이틀바가 사진에 나왔는데, 그건 그 창의 바가 Content 안에 있어서였다. 창 전체를 찍도록 바꿨다(템플릿의 PART_Root). 고칠 대상이 사진에 안 나오는 진단은 있으나 마나였고, 실제로 이번에도 첫 캡처가 "고쳤는데 그대로"로 보여 한 번 헛짚게 만들었다. ## 강조 버튼 — 규칙은 이미 있었다 Primary 스타일을 열한 창 중 넷만 쓰고 있었다. 그런데 IsDefault="True" 는 대부분의 창이 이미 주 동작에 달아 두었다 — 규칙을 새로 만들 필요가 없었다. <b>기본 버튼 = 강조</b>로 맞춘다(서식 이력·서식 등록·마스크·레이어 필터·데이터소스 결과·환자 선택). 글꼴 관리자만 예외로 손으로 골랐다. IsDefault 가 없고 버튼이 셋인데, 강조는 <b>고른 것만</b> 바꾸는 '선택 조합에 적용'에 준다. '전체에 적용'은 문서 전체를 한 번에 바꾸므로 눈이 먼저 가는 자리에 두지 않았다 — 되돌리기가 있어도 되돌릴 생각을 하려면 먼저 알아채야 한다. 환자 선택의 '선택'에는 Primary 만 주고 IsDefault 는 건드리지 않았다 — 검색칸에서 Enter 는 '찾기'여야 한다. ## 판정 - 단위 시험 388 · edit-smoke 376건 전건 통과 - --dialog-shots 69장 전건 통과(창 전체 캡처로 바뀐 뒤에도) - --modal-check · --maxrect · --scale-budget 전건 통과 - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변 ## 남은 것 내용 여백은 아직 창마다 다르다 — 설명 문장이 창 위쪽 가장자리에 바짝 붙는 창이 여럿이다. 타이틀바가 생겨 덜 도드라지지만 통일된 것은 아니다. 별도로 잡을 것. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
8cc2d68ac1 |
미리보기를 눌러 볼 수 있게 하고, Ctrl+드래그를 복사로 바꾼다
사용자 지적 두 건. 둘 다 라디오 배타 그룹이 걸린 문제였다.
## 미리보기 클릭이 안 먹었다
레거시 미리보기(TK_PREVIEW)는 정적 그림이 아니라 런타임 모드라 눌러 보며 확인한다.
우리 미리보기는 그림이었다 — 그래서 <b>라디오가 배타로 묶였는지 확인할 방법이 없었다</b>.
패널로 묶었다고 믿고 저장했다가 임상 화면에서 두 개가 동시에 켜지는 것이
이 서식에서 가장 흔한 사고인데, 저장 전에 그걸 볼 수단이 없었던 것이다.
PreviewCheckState — 컨트롤 Id → 체크 상태 사전. 문서는 건드리지 않는다.
확인하려고 누른 것이 서식 수정이 되면 미리보기를 열었다 닫은 것만으로
저장할 내용이 생긴다. 렌더 시점(WithTagValue)에만 덮고, 창을 닫으면 사라진다.
배타는 직계 부모 안에서만. 레거시 RadioButton 은 WinForms 를 그대로 상속해
GroupName 이 없고(RadioButton.vb:7-8) 배타 판정을 부모 컨테이너에 맡긴다.
운영 실측도 라디오 15,184개 중 15,026개(98.96%)가 패널 직계 자식 — 패널 1개 = 문항 1개다.
- PreventEditing=True 는 안 눌린다(RadioButton.vb:271-279 — 값 대입만 되고 클릭은 무시).
Locked 는 편집 보호일 뿐이라 눌린다.
- 라디오는 다시 눌러도 안 꺼진다. 끄는 것은 형제를 누르는 것뿐이다.
- 손으로 누른 값이 태그 값을 이긴다 — 그 칸을 직접 눌러 보는 중이므로 사용자의 손이 마지막이다.
- 환자를 바꾸거나 서식을 갈아타면 지운다. 안 지우면 손으로 누른 값이
새 환자의 실제 값을 가려, 확인하려고 만든 창이 확인을 막는다.
- 이 창에서 인쇄하면 화면과 같은 상태로 나간다(같은 checks 를 Print 까지 넘긴다).
히트테스트는 WPF 가 아니라 모델 트리로 한다. 종이 비주얼은 템플릿이 만든 그림이라
컨트롤 하나가 여러 요소로 쪼개져 있고 일부는 히트테스트에서 빠져 있다.
캔버스의 HitTestControl 과 두 군데만 다르다 — Locked 를 보지 않고,
그려지지 않은 것(숨김·데이터소스·인쇄 제외)을 뺀다.
## Ctrl+드래그가 복사가 아니었다
예전에는 '선택에 더하고 이동'이었다(Ctrl 이 선택 추가 수정자였으니까).
그래서 같은 컨트롤을 여러 개 놓는 방법이 복사·붙여넣기뿐이었는데,
붙여넣기는 <b>항상 최상위 +12,+12</b> 에 떨어진다.
패널 안 라디오를 그렇게 복사하면 사본이 패널 밖으로 나가 배타 그룹이 깨진다 —
눈으로는 안 보이고 임상 화면에서만 드러나는 고장이다.
DuplicateSelectionInPlace — 제자리 복제. 부모를 유지하므로 사본이 같은 문항 안에 남는다.
드래그 문턱을 넘은 지점에서 복제한다(누름 시점에 하면 Ctrl+클릭만으로도 사본이 생긴다).
복제가 스냅샷을 이미 찍었으므로 이어지는 이동은 추가로 찍지 않는다 —
안 그러면 "복사 후 이동"이 Undo 두 번이 되고, 한 번만 누른 사용자는
원본 자리에 사본이 겹쳐 남은 상태를 본다.
Ctrl 은 이 제스처에서 더하기가 아니다. 합집합으로 두면 아까 선택해 둔 컨트롤까지
함께 복제돼 하나 집어 끌었는데 화면 다른 곳에 사본이 여럿 생긴다. Shift 는 그대로 더하기다.
선택 단위가 패널이므로 자식을 그냥 집으면 <b>문항이 통째로</b> 복사되고,
더블클릭으로 들어간 뒤 집으면 <b>그 선택지만</b> 복사돼 같은 패널에 남는다.
둘 다 필요한 동작이라 둘 다 시험한다.
## 판정
- 단위 시험 368 (PreviewCheckState 10건 추가)
- edit-smoke 320건 전건 통과 (Ctrl+드래그 복사 9건, 미리보기 클릭 5건 추가)
· 20-5f 의 옛 단언 2건은 의미가 바뀌어 교체했다("합집합으로 함께 움직인다" → "복사된다")
· 20-5c(빈 선택 Ctrl+드래그)가 남기는 사본을 되돌린다 — 안 하면 뒤따르는 개수 검사가 흔들린다
- --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변
- --db-patient "김" 39건 · --dialog-shots · --cleartype · --db-filecfg 전건 통과
시험을 처음 쓸 때 자식을 Children[0]/[1] 로 집었는데 자식 VM 은 z 순서로 온다.
이미 켜진 라디오를 누르는 시험이 되어 "문서가 바뀌었다"는 거짓 실패가 났다 — Id 로 집는다.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
9bff3dd5f6 |
MDataTable 을 미리보기에서 실제로 돌린다 — 태그만 채우면 반쯤 빈 것을 못 본다
"태그와 MDataTable도 환자 선택하면 해당 정보로 조회되는지 확인가능해야" 한다는 요구.
확인해 보니 미리보기가 DataTableViewModel 을 아예 건너뛰고 있었다(PrintService:87,143).
서식의 값 상당수가 태그가 아니라 이 관으로 오는데(운영 실측 Rows 형 1,624건)
그쪽은 미리보기에 존재하지 않았다.
## 레거시 구조를 먼저 확인했다
TK_PREVIEW 는 meLoadMode 를 Runtime 으로 바꾸고 TestPatientSetting() 으로
환자 선택 창을 띄운다(frmSheetDesigner.vb:452-462). 고르는 것만으로는 화면이 안 바뀐다 —
moPatInfoBiz 는 필드에 담기기만 하고(:634-674), 서식을 다시 열어야
ucLoadSheetBase(moWrkInfoBiz, moPatInfoBiz, …, EN_LoadType.Edit) 로 로드되면서
그때 태그와 MDataTable 이 실행된다(:216). 탭마다 별도 인스턴스라
환자를 바꿔도 이미 열린 탭은 옛 환자를 계속 들고 있다.
SheetMe 는 1단계다. UsePatient 가 해석기를 갈고 즉시 다시 그린다.
창이 하나뿐이라 잔상도 없다. 이 차이는 의도한 것이다.
## 치환 엔진(QuerySubstitution)
clsMDataTable.ConvertQuery 를 옮겼다. 한 칸이라도 다르면 미리보기가 운영과
다른 SQL 을 돌린다 — "미리보기에서는 나왔는데 실제로는 안 나온다"가 되고
사람이 확인했다고 믿고 넘어가므로 미리보기가 없는 것보다 나쁘다.
처음에 갈래 하나를 반대로 만들었다. 대문자 Item 처럼 정규식이 안 맞는 경우를
"토큰이 남는다"로 단정했는데, GetPropertyInfo 는 정규식 실패에 ""를 돌려주고(:118)
호출부가 그걸 빈 문자열로 치환한다(:66-70) — 즉 지워진다.
토큰이 남는 갈래는 <b>접두어 불일치</b>뿐이다(oBaseObj 가 Nothing 이라 Replace 를 안 한다).
소스를 읽어 고쳤다. 두 갈래를 섞으면 안 되는 이유는 하나는 ORA 구문오류가 되고
다른 하나는 조건이 사라진 SQL 이 조용히 도는 것이라서다.
SQL 에서는 같아지는 것들도 사람에게는 갈라서 말한다 —
Unknown(아직 안 옮긴 속성) / Empty(값이 빔) / NotAVariable(접두어 틀림).
셋은 고칠 곳이 전부 다르다.
## 짐작하지 않는 변수원(PatientQueryVariableSource)
DataRow 접근형이 이 기능의 대부분을 실어 준다 — PatInfDR.item("아무컬럼") 은
SELECT * 결과 사전을 그대로 조회하면 되므로 <b>내가 컬럼을 알 필요가 없다.</b>
짐작할 것이 없으니 조용히 틀릴 일도 없다.
스칼라도 대부분 그 다섯 행의 컬럼 하나라, 컬럼 이름만 적고 있으면 값·없으면 모른다고
답한다. 존재 여부는 DB 가 판정한다. UDF 산출값(Age·Sex)은 넣지 않았다.
## 값이 안 나올 때를 위한 창
종이에는 "[MDataTable1.ALGYON — 조회 결과가 0행입니다]" 한 줄만 나온다.
그것으로는 쿼리가 틀렸는가·치환이 빈 값이 됐는가·이 환자에게 자료가 없는가를 못 가른다.
그래서 데이터소스 창이 <b>치환을 마친 SQL</b>을 그대로 보여 준다.
값이 안 나왔을 때 봐야 하는 것은 결과가 아니라 무엇을 물었는가다.
레거시에는 이걸 볼 수단이 없었다 — 런타임이 빈 catch 로 삼켜 "빈칸"만 남았다.
진단 화면 표본도 <b>실패 상태</b>로 찍는다. 성공 화면만 회귀 대상으로 두면
정작 사람이 오래 들여다보는 화면이 검사에서 빠진다.
## 안전
- 실행은 OracleQueryWorkbench.Trial 을 그대로 쓴다 — SELECT/WITH 문이 이미 거기 있다.
문을 두 군데 두면 한쪽이 느슨해진다.
- 치환 값은 레거시처럼 원문 그대로 박힌다(그래야 같은 SQL 이다). 따옴표가 섞인 값은
QuotedValues 로 드러내고 실행은 SELECT/WITH 문이 막는다.
- 데이터소스당 한 번만 실행하고 캐시한다 — 배선 40개면 왕복 40회가 된다.
- 환자를 바꾸면 러너를 새로 만든다. 재사용하면 태그만 바뀌고 표는 옛 환자가 남는데
그건 아무도 눈치채지 못한다. 서식을 갈아탈 때도 다시 만든다(옛 서식의 쿼리를 쓰게 된다).
## 아직 안 되는 것
Select 형의 필터(DataTable.Select 메모리 문법)는 옮기지 않았다.
무시하고 행 번호만 쓰면 다른 행의 값이 조용히 찍히므로, 값을 내지 않고 사유를 말한다.
운영 다수파인 Rows 형(76%)은 된다.
## 게이트
- dotnet test 323/323 (치환 판정 10건 신규)
- --edit-smoke 실패 0 (배선 판정 7건 추가, 대조군 포함)
- --db-patient ①~⑱ 전건 통과. ⑯ 치환한 SQL 이 실제로 1행을 뽑고,
⑱ 대조군은 환자 없이 같은 쿼리가 "WHERE ComNum = AND ... = ''" 로 깨진다 —
이 대조가 없으면 ⑯ 은 "쿼리가 원래 환자와 무관했다"와 구분되지 않는다
- --dialog-shots FAIL 0 (08c-datasource-result 추가)
- --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 불변
- --db-smoke 1,271건 diff 0
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
||
|
|
88dab2edcf |
환자를 골라 태그에 값이 들어간다 — 데이터 계층만 있던 것을 화면에 붙인다
전 커밋까지 환자 조회·시각 판정·권한 규칙은 다 있었지만 화면에 붙은 것이 하나도 없었다. 미리보기를 열면 환자 선택이 없고, 태그는 전부 사유만 찍혔다. ## 만든 사슬 PatientPickerDialogView(모달) → PatientContextStore(문맥 5행) → PatientTagResolver(태그 → 컬럼) → PreviewWindow.UsePatient → 종이 모달로 둔 이유: 30초 안에 끝나는 자족적인 일이고 권한 문이 걸린 동작이다. 사이드 패널로 두면 실제 환자 정보를 꺼내는 창이 항상 열려 있게 되는데 이 창은 열려 있는 것 자체가 비용이다. 환자와 내원을 한 화면에 둔다. 고르는 대상은 환자가 아니라 내원이다 — 문맥 5행이 전부 ComNum + AdpDtm 으로 읽히므로 환자만 골라서는 아무것도 못 읽는다. 기준 시점(마지막/처음)을 화면에 노출한다. 입원 내원의 진료과·병실·자격 값을 실제로 바꾸는 값이라 숨기면 값이 왜 다른지 설명할 수 없다. 문맥 읽기를 창 안에서 한다. 닫고 나서 읽으면 실패를 미리보기 창에서 알려야 하고 그때는 이미 고른 것이 사라진 뒤다. ## 매핑은 확인된 6종만 PAT_이름 / PAT_차트번호 / PAT_주민번호 / PAT_휴대전화 / PAT_전화번호 / PAT_주소. 전부 레거시 조회 SQL 의 SELECT 목록에서 컬럼을 직접 확인한 것이다. PAT_나이·PAT_성별은 넣지 않았다 — UDF_GETAGE·UDF_GETSEX 를 거치는 값이라 컬럼을 짐작해 넣으면 값이 조용히 틀린다. 종이에 그럴듯한 값이 찍히면 아무도 의심하지 않으므로 빈칸보다 나쁘다. 안 옮긴 환자 태그는 "아직 옮기지 않았습니다"라고 말한다. "DB 접속이 없습니다"로 뭉개면 환자를 골랐는데도 그 사유가 나와 접속을 의심하게 된다. ## 문맥 조회를 한 번에 다섯 번 읽는다 레거시는 5행을 프로퍼티 접근 시점에 하나씩 지연 로딩한다(각각 별도 왕복). 태그마다 다시 읽으면 태그 40개짜리 서식에 왕복 40회가 된다. ## 개인정보 - 감사 로그는 고른 직후 남긴다 — 종이에 값이 찍히는 것과 무관하게 조회는 이미 일어났다. - 로그에 환자 이름을 남기지 않는다(내원번호로 추적 가능하고, 로그가 개인정보를 들고 있으면 로그 자체가 위험물이 된다). - 진단 리포트도 값 대신 길이만 적는다. - 권한 문은 수정(TK_MODIFY)과 같은 범위다. 넓히면 서식생성기가 환자 조회 도구가 된다. - 화면에서 감사 기록 사실을 말한다. ## 게이트가 잡은 것 셋 ① --db-patient 가 "전건 통과"인데 ⑧~⑬ 이 통째로 SKIP 이었다. 첫 환자에게 내원이 0건이라 문맥 조회를 한 번도 안 돌린 채 초록불이었다. 내원 있는 환자를 30명까지 훑고, 못 찾으면 SKIP 이 아니라 FAIL 로 바꿨다. ② 그렇게 찾은 내원에서 CodInf·CoiInf·CowInf 가 셋 다 0행이었다. 0 을 적어 두는 것으로는 "조건이 어긋났다"와 "행이 없다"를 못 가른다. 조건 없는 원본 행을 함께 찍게 하니 후자였다(1988년 내원, 행 자체가 없음). ③ 그러면 기간 조회 세 갈래는 아직 한 번도 행을 돌려준 적이 없다. 안 돌아본 갈래는 통과한 갈래가 아니므로, 각 표에서 직접 내원을 찾아 들어가 BETWEEN·MtiSeq 조건이 실제로 행을 뽑는 것까지 확인하게 했다(⑮). --edit-smoke 판정 7건 추가. 전부 대조군이 있다 — 환자 없이 같은 종이를 찍어 사유가 나오는 것을 먼저 확인한 뒤 값으로 바뀌는 것을 본다. 미리보기 창 배선도 따로 본다(붙이면 값, 떼면 사라짐). 그래서 고르는 일과 붙이는 일을 나눠 두었다 — 모달에 묻어 두면 "골랐는데 종이가 그대로"를 자동으로 못 잡는다. ## 게이트 - dotnet test 312/312 - --edit-smoke 실패 0 (환자·미리보기 판정 7건 추가) - --dialog-shots FAIL 0 (08b-patient-picker 추가) - --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 (변화 없음) - --db-smoke 1,271건 diff 0 - --db-patient ①~⑮ 전건 통과 (기간 조회 3갈래 실제 통과 확인) - --db-modify-smoke S999 8/8 (⑤ 는 E_SctMst 0행으로 여전히 SKIP) Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
a67b6ee4b8 |
미리보기에 보기 전환을 둔다 — 인쇄될 것만 / 화면 그대로
미리보기 레거시 호환 계획의 P0-3. P0 세 항목이 이걸로 끝난다. 레거시 미리보기와 레거시 인쇄가 서로 다르다 — 미리보기는 PrintOutPut=False 컨트롤을 <b>그대로 보여 주고</b>(그 속성은 PrintMe 안에만 있다, Label.vb:454-457) 인쇄만 뺀다. SheetMe 는 인쇄 쪽을 골라 테스트로 못 박아 뒀었다. 둘 다 확인해야 하므로 미리보기 창이 보기를 가른다. 기본은 인쇄 기준 — 저장 전에 확인하려는 것이 대개 종이 결과다. Hidden(디자이너 임시 숨김)과 MDataTable(런타임 비가시)은 보기와 무관하게 항상 뺀다. 레거시 미리보기에서도 안 보이는 것들이다 — 보기가 가르는 것은 Visible/PrintOutPut 뿐이다. 인쇄 경로는 언제나 필터를 건다. 인쇄는 인쇄다. <b>단정은 "돌아오는가"를 본다.</b> 필터를 켜서 뺀 것이 끄면 다시 나와야 한다 — 안 나오면 전환이 배선만 된 것이다. 컨테이너 안까지 세므로 P0-1 의 투영도 함께 검증된다. <b>XAML 파싱 중에 이벤트가 발생했다.</b> 토글의 IsChecked="True" 가 파스 시점에 Checked 를 쏘는데, 토글이 트리에서 앞에 있어 그때 PagesHost 는 아직 null 이다 → InitializeComponent 안에서 NullReferenceException. 가드를 넣고 이유를 적었다. --edit-smoke 가 잡았다. 없었으면 미리보기를 여는 순간 앱이 죽었을 것이다. 게이트: 테스트 298/298, --edit-smoke 0실패(미리보기 7건), --dialog-shots 글자 2,653개 FAIL 0 대조군 4/4, --modal-check 0실패, --cleartype 11/11, --maxrect 0실패, --scale-budget 5/5, 빌드 경고 0, --db-smoke 1271건 diff 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
9e3cd088e2 |
미리보기가 편집을 따라오고, 창이 하나만 뜬다
미리보기 레거시 호환 계획의 P0-2. 환자 값이 들어가기 <b>전에</b> 반드시 고쳐야 하는 항목이다. <b>① 창이 여러 장 쌓였다.</b> 모덜리스인데 누를 때마다 새로 만들어서, 각각이 서로 다른 시점의 서식을 들고 겹쳐 있었고 어느 것이 지금 것인지 화면으로 구분할 수 없었다. 환자 데이터가 들어가면 그건 개인정보 사고가 된다 — 환자를 B 로 바꿔도 옛 창이 A 를 계속 띄운다. 이제 하나만 뜨고, 이미 있으면 지금 문서로 갈아타 앞으로 온다. <b>② 생성자에서 한 번만 그렸다.</b> 컨트롤을 추가·삭제하거나 숨김·인쇄출력을 토글해도 창은 옛 그림을 계속 보여 줬다 — 저장 전에 결과를 확인하려고 여는 창이 <b>구조적으로 거짓말</b>을 하고 있었다. 페이지·컨트롤 추가/삭제는 즉시(CollectionChanged), 그 밖의 변경은 창을 누르는 순간(Activated) 다시 그린다. 즉시 갱신이 안 되는 변경이 남아 있으므로 새로 고침 버튼도 함께 뒀다 — 자동에 기대게 하지 않는다. 제목에 서식명을 넣는다. 창이 하나뿐이라 무엇을 보고 있는지 제목이 말해야 한다. <b>같은 함정에 세 번째로 걸렸다.</b> 단정이 52 → 41 로 나왔다 — 재빌드는 됐는데 새 자식이 아직 실체화되지 않아 요소 수가 오히려 줄어 보인 것이다. UpdateLayout 을 돌리고 세니 통과했다. WPF 시각 트리를 세는 검사는 <b>반드시</b> 레이아웃을 먼저 돌려야 한다. 진단(--dialog-shots)은 생성자를 직접 부른다 — 단일 인스턴스 등록을 건너뛰어야 샷마다 새 창을 찍을 수 있다. 앱 코드는 ShowFor 만 쓴다는 것을 주석에 못 박았다. 게이트: 테스트 298/298, --edit-smoke 0실패(신규 1), --dialog-shots 글자 2,651개 FAIL 0 대조군 4/4, --modal-check 0실패, --cleartype 11/11, --maxrect 0실패, --scale-budget 5/5, 빌드 경고 0, --db-smoke 1271건 diff 0, --db-render P062 md5 8d683835f5d81e7bb41c79071d6bf954 동일. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
308197c15e |
별도 창 전수 점검 — 암시 Window 스타일이 파생 클래스에 적용된 적이 없었다
사용자 지적: "다른 창으로(새창으로 열리는) 실행하는 항목들도 모두 점검해줘". [근본 원인 — 대화상자 전체가 다크에서 흰 창이었다] WPF 는 암시 스타일을 요소의 **정확한 런타임 타입**으로만 찾는다. 저장소의 모든 창이 Window 를 상속한 클래스(SheetOpenDialogView : Window, QueryEditorWindow : Window …)라 DesignerTheme.xaml 의 <Style TargetType="Window"> 는 **단 한 번도 적용된 적이 없다**. 결과: 창 배경이 WPF 기본 흰색으로 남고, 그 위 글자는 암시 TextBlock 스타일(B.Ink #EDEDED)을 정상적으로 받는다 → **다크 테마에서 흰 바탕에 흰 글자**. 쿼리 편집기의 변수 목록처럼 라벨이 통째로 사라지는 화면이 나왔다. 라이트에서 눈에 덜 띈 이유는 우연이다 — 기본 흰색(#FFFFFF)이 의도값 B.AppBg(#F5F5F5)와 거의 같아서다. 그래서 지금까지 라이트만 보고는 발견되지 않았다. 수정: 스타일에 x:Key="ThemedWindow" 를 주고 창 10종에 직접 걸었다(코드로 짓는 ColorPickerWindow 는 생성자에서 TryFindResource). 순수 Window 인스턴스용 암시 스타일은 BasedOn 으로 남겼다. 앞으로 창을 추가할 때 잊지 않도록 스타일 위에 경고 주석을 붙였다. [신규 진단 --dialog-shots <출력폴더>] 이 결함은 정적 분석으로는 못 잡았다(앞선 감사에서 "대화상자들은 암시 Window 스타일을 그대로 받는다"고 잘못 결론냈다). 실입력 주입은 화면 잠금·세션 격리 상태에서 OS 가 거부한다 (SetCursorPos 무시, SendKeys "Access is denied" — 이번에도 중간부터 막혔다). 그래서 창을 화면 밖(-10000)에 띄워 RenderTargetBitmap 으로 찍는 진단을 만들었다. 창 8종 × 2테마 = 16장을 한 번에 남기고, 각 창의 **해석된 Background 와 Style 적용 여부를 텍스트로 함께 보고**한다 — 픽셀만 보면 원인을 못 가린다(실제로 이 한 줄이 원인을 확정했다). 표본 데이터는 실제 사용 시와 같은 형태로 넣었다(빈 껍데기를 찍으면 의미가 없다). 함정 2개를 코드에 남겼다. · 기본 ShutdownMode 가 OnLastWindowClose 라 찍고 닫는 순간 앱이 종료된다 → OnExplicitShutdown. · Window.Content 만 렌더하면 창 배경이 빠져 투명(=PNG 검정)이 되고, 다크처럼 보이는 착시로 라이트 결함이 가려진다 → 배경을 먼저 칠하고 그 위에 콘텐츠를 그린다. [함께 고친 것 — 여러 줄 입력이 세로 가운데 정렬] 쿼리 편집기의 SQL 이 큰 상자 한가운데 떠 있었다. 템플릿 트리거가 ScrollViewer 의 VerticalContentAlignment 만 Stretch 로 바꿨는데, 텍스트를 배치하는 건 TextBox 자신의 VerticalContentAlignment 이라 아무 효과가 없었다. Style.Triggers 로 옮겨 Top 으로 두고 여러 줄일 때 Padding 도 넉넉히 준다. 인스펙터의 여러 줄 속성 행에도 함께 적용된다. 검증: 창 8종 × 2테마 전부 재렌더해 배경 확인(다크 #0E0E0E / 라이트 #F5F5F5, 미리보기만 의도대로 B.CanvasBg). 테스트 124/124, edit-smoke 실패 0, **종이 렌더 P062 픽셀 대조 차이 0**. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> |
||
|
|
16c07f48dc |
초기 커밋: SheetMe 서식생성기 (P0~P5 완료 상태)
레거시 서식생성기(VB.NET WinForms) 대체용 C#/.NET 10 WPF 디자이너. 기준선: 실DB 활성 디자인 1,271건 왕복 의미론 diff 0 / 예외 0, 단위 테스트 49/49. 이 커밋에 함께 포함된 자격증명 분리: - appsettings.json 을 __HOST__/__PASSWORD__ 플레이스홀더로 전환 - 실접속 정보는 appsettings.Development.json 으로 분리(.gitignore 제외, csproj Debug 조건부 복사라 Release 산출물에 실리지 않음) - ConfigLoader 를 환경변수 > Development > appsettings 순 레이어링으로 변경, 미치환 플레이스홀더는 '미설정'으로 간주 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |