From 06d78e2fc735b57fecb780ed6bf2165de592e337 Mon Sep 17 00:00:00 2001 From: ksj09406 Date: Mon, 28 Sep 2026 14:09:52 +0900 Subject: [PATCH] =?UTF-8?q?[<]=20=EB=8B=A8=EC=B6=94=EA=B0=80=20=EC=9E=88?= =?UTF-8?q?=EB=8A=94=20=EC=A4=84=EB=A7=8C=20=EA=B8=80=EC=9D=B4=20=EB=B0=80?= =?UTF-8?q?=EB=A6=AC=EB=8D=98=20=EA=B2=83=20-=20=EB=8B=A8=EC=B6=94=20?= =?UTF-8?q?=EC=9E=90=EB=A6=AC=EB=A5=BC=20=EB=8A=98=20=EC=9E=A1=EC=95=84=20?= =?UTF-8?q?=EB=91=94=EB=8B=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 사용자가 그림으로 짚어 준 것. 12차 B-1 로 넣은 [<] 단추가 든 칸의 폭이 Auto 여서, 단추가 보이는 줄에서만 칸이 벌어져 뒤 칸이 통째로 오른쪽으로 밀렸다. 같은 칸 안에서도 줄마다 글이 시작하는 자리가 달랐다. BASE LOCAL 01 class Axis 01 class Axis < 03 int speed = 100; 03 > int speed = 200; <- 밀림 < 04 // left only line 05 > < void Stop() { } <- 더 밀림 05 void Home() { } 06 } BASE 는 [<] 가 맨 앞 칸이라 번호까지, LOCAL 은 번호 뒤 칸이라 코드가 밀렸고, 단추가 하나 늘 때마다 한 칸씩 더 밀렸다. Visibility="Collapsed" 은 자리까지 없애므로, 자리를 지키려면 칸 폭이 고정이어야 한다. - GutterBothWaysWidth 를 두어 BASE · LOCAL 이 같은 자리를 늘 잡아 둔다 - 화면이 모드에 따라 갈아 끼운다(ApplyGutterReserve) - 두 파일 비교는 단추 폭, Git 모드와 네 칸은 0(그 단추가 아예 없다 - 여백이 예전 그대로) - 투명한 편집기가 아래 표시층과 어긋나면 캐럿이 글자와 다른 자리에 선다 - EditorGutterMargin 도 같은 값만큼 민다 - 글자 크기(11차 F-5)를 바꾸면 단추 폭이 따라 바뀌므로, 잡아 두는 자리도 CodeFontMetrics 한 벌에서 나온다 화면으로 확인: 한 칸의 모든 줄이 같은 x(BASE 137 · LOCAL 1283), 글자 크기를 키워도 한 x(147), Git 모드도 한 x(459). 오류 글 0. E-2 화면 세 벌 · 왼쪽 번호 한 벌 모두 그대로 통과. 빌드 경고 0 · 오류 0. 남겨 둔 것: BASE 줄 끝의 [>](11차 F-10)는 아직 Auto 다. 왼쪽 가장자리를 밀지 않고 오른쪽에서 코드 칸을 조금 좁힐 뿐이라 눈에 띄지 않는다. 워드랩을 켜면 그 줄만 접히는 자리가 달라질 수 있다 - 워드랩은 기본이 꺼짐이라 이번에는 두었다. Co-Authored-By: Claude Opus 5 --- doc/history/2026-09-23-12차.md | 54 +++++++++++++++++++++++++++++ doc/history/changelog.md | 1 + doc/진행상황.md | 3 +- src/MergeHub/Views/HomeView.xaml | 10 ++++-- src/MergeHub/Views/HomeView.xaml.cs | 34 +++++++++++++++++- 5 files changed, 98 insertions(+), 4 deletions(-) diff --git a/doc/history/2026-09-23-12차.md b/doc/history/2026-09-23-12차.md index 8ca3ba4..a334434 100644 --- a/doc/history/2026-09-23-12차.md +++ b/doc/history/2026-09-23-12차.md @@ -285,6 +285,60 @@ BASE 칸 자신은 견줄 것이 없어 `4줄 · 기준` 이라고만 적는다. 실제로 켜서 잰 하단 탭 줄이 **111px · 항목 109px**(배율 150% 기준 72.7 DIP)로 "후" 값과 맞았다. 앞서 적었던 "지금 배포 폴더에는 예전 것이 그대로" 는 그 뒤 빌드로 낡은 글이 되어 고쳤다. +## B-1 을 쓰다 나온 것 (2) - [<] 단추가 있는 줄만 글이 밀린다 (2026-09-28, 사용자 보고) + +사용자가 그림으로 짚어 준 것이 이것이었다. 아래 "왼쪽 줄 번호" 건은 이것을 쫓다 따로 찾은 다른 흠이다. + +### 먼저 재현 (화면, 값) + +`[<]` 단추가 보이는 줄만 코드가 오른쪽으로 밀려, 같은 칸 안에서도 줄마다 글 시작 자리가 달랐다. + +``` +BASE LOCAL + 01 class Axis 01 class Axis + 02 { 02 { +< 03 int speed = 100; 03 > int speed = 200; ← 밀림 +< 04 // left only line 04 void Home() { } + 05 void Home() { } 05 > < void Stop() { } ← 더 밀림 + 06 } 06 } +``` + +오른쪽 칸은 단추가 하나 늘 때마다 한 칸씩 더 밀렸다. + +### 까닭 + +단추가 든 칸의 폭이 `Auto` 였다. 단추가 안 보이는 줄에서는 0 이 되고 보이는 줄에서는 단추 폭만큼 벌어지니, +그 줄만 뒤 칸이 통째로 오른쪽으로 밀린다. `Visibility="Collapsed"` 는 자리까지 없앤다 - +자리를 지키려면 칸 폭이 고정이어야 한다. + +- BASE 는 `[<]` 가 맨 앞 칸(`Auto`)이라 **번호까지 함께** 밀렸다. +- LOCAL 은 `[<]` 가 번호 뒤 칸(`Auto`)이라 **코드만** 밀렸다. + +### 고친 것 + +`GutterBothWaysWidth` 를 두고 두 칸이 같은 값을 쓴다. 화면이 모드에 따라 0 ↔ 단추 폭으로 갈아 끼운다(`ApplyGutterReserve`). + +- **두 파일 비교**: 단추 폭만큼 늘 잡아 둔다 - 단추가 없는 줄도 같은 자리에서 글이 시작한다. +- **Git 모드 · 네 칸**: `[<]` 가 아예 없으므로 0 - 여백이 예전 그대로라 코드 칸이 좁아지지 않는다. +- **편집기 여백**(`EditorGutterMargin`)도 같은 값만큼 민다. 투명한 편집기와 아래 표시층이 어긋나면 + 캐럿이 글자와 다른 자리에 선다. +- 글자 크기(11차 F-5)를 바꾸면 단추 폭도 따라 바뀌므로, 잡아 두는 자리도 `CodeFontMetrics` 한 벌에서 나온다. + +### 화면으로 확인 (값) + +| 확인 | 값 | +|---|---| +| 두 파일 비교 BASE | 여섯 줄 모두 `x=137` (전에는 단추 줄만 달랐다) | +| 두 파일 비교 LOCAL | 여섯 줄 모두 `x=1283` | +| 글자 크기 키운 뒤 | 모두 한 x(`147`) | +| Git 모드(회귀) | 모두 한 x(`459`) · 여백 예전 그대로 | + +### 남겨 둔 것 + +BASE 줄 끝의 `[>]`(LOCAL 에서 지운 줄 되살리기, 11차 F-10)는 아직 `Auto` 다. 이것은 왼쪽 가장자리를 +밀지 않고 오른쪽에서 코드 칸을 조금 좁힐 뿐이라 눈에 띄지 않는다. 워드랩을 켜면 그 줄만 접히는 자리가 +달라질 수 있다 - 워드랩은 기본이 꺼짐이고, 손대면 네 칸 폭을 다시 맞춰야 해서 이번에는 두었다. + ## B-1 을 쓰다 나온 것 - 왼쪽 줄 번호가 밀린다 (2026-09-28, 사용자 보고) ### 먼저 재현 (화면, 값) diff --git a/doc/history/changelog.md b/doc/history/changelog.md index 5cf9592..e1b842c 100644 --- a/doc/history/changelog.md +++ b/doc/history/changelog.md @@ -8,6 +8,7 @@ | 날짜 | 항목 | 커밋 | |---|---|---| +| 2026-09-28 | **`[<]` 단추가 있는 줄만 글이 밀리던 것**(사용자 보고 — 그림으로 짚어 준 것이 이것이다). 12차 B-1 로 넣은 `[<]` 단추가 든 칸의 폭이 `Auto` 여서, 단추가 보이는 줄에서만 칸이 벌어져 뒤 칸이 통째로 오른쪽으로 밀렸다 — BASE 는 맨 앞 칸이라 번호까지, LOCAL 은 번호 뒤 칸이라 코드가 밀렸고 단추가 하나 늘 때마다 더 밀렸다. `Visibility="Collapsed"` 는 자리까지 없애므로 칸 폭이 고정이어야 한다. `GutterBothWaysWidth` 를 두어 두 칸이 같은 자리를 늘 잡아 두고, 두 파일 비교에서는 단추 폭 · Git 모드와 네 칸에서는 0 으로 화면이 갈아 끼운다(`ApplyGutterReserve`). 투명한 편집기가 아래 표시층과 어긋나지 않도록 `EditorGutterMargin` 도 같은 값만큼 민다. 글자 크기(11차 F-5)를 바꾸면 단추 폭이 따라 바뀌므로 잡아 두는 자리도 `CodeFontMetrics` 한 벌에서 나온다. 값으로 확인: 한 칸의 모든 줄이 같은 x(BASE 137 · LOCAL 1283), 글자 크기 · Git 모드도 그대로. BASE 줄 끝의 `[>]`(11차 F-10)는 왼쪽 가장자리를 밀지 않아 이번에는 `Auto` 로 두었다 | 아래 | | 2026-09-28 | **왼쪽 줄 번호가 밀리던 것**(사용자 보고) — 12차 B-1 로 왼쪽에도 반영할 수 있게 되면서 왼쪽 줄이 늘고 주는데, 번호는 정렬기가 처음 준 것 그대로였다. 오른쪽에만 있던 줄을 왼쪽에 넣으면 그 줄은 번호가 비고 뒤 줄은 옛 번호를 달아 `01 02 · 03 04 05 · 06` 으로 보였다 — 왼쪽 파일은 8줄인데 번호는 6까지라 어느 줄을 고쳤는지 짚을 수 없었다. `RenumberBase` 를 `RenumberMerged`(8차 B-3) 옆에 두고 두 파일 비교에서만 왼쪽 줄을 1부터 다시 맨다. Git 모드 · 네 칸의 BASE 는 고칠 수 없는 쪽이라 건드리지 않는다. "머지 반영함" 표시가 BASE 줄 번호를 열쇠로 붙들고 있어 번호가 실제로 달라질 때만 그 열쇠도 옛 번호 → 새 번호로 옮긴다. 화면으로 넣기 · 빼기 · 되돌리기 · 저장 · Git 회귀 확인, 하네스 27벌 1,787건 · 실패 0. **왼쪽에만 있는 줄을 뺄 때 줄 수가 주는지는 값으로 확정하지 못했다**(시험 도구가 낡은 줄 칸을 집는 한계) | 아래 | | 2026-09-28 | **12차 E-2** — 파일 비교가 짝 여러 개를 동시에 든다(문서 탭). 지금까지는 한 짝만 들어서 짝을 바꾸면 "저장하지 않은 편집이 있습니다" 를 묻고 버리면 고친 글이 사라졌다(재현: 16줄 → 15줄). 이제 떠 있던 탭이 그 글을 맡아 두므로 **묻지 않는다**. 탭마다 `HomeViewModel` 을 따로 만들지 않고(GitWorkspace 의 한 자리짜리 약속 때문) 화면은 하나로 두고 탭이 **파일에 없는 것만** 맡는다 — 고친 글 · 왼쪽 글(B-1) · 되돌리기 이력 · 두 기준점 · 캐럿 · 스크롤 · 저장 형식. 탭 이름은 파일 이름(다르면 `왼 ↔ 오`, 겹치면 위 폴더를 갈릴 때까지 덧붙임), 저장 안 한 탭은 `•`. 탭 줄은 둘 이상일 때만 보인다. `◀ 이전 · 다음 ▶` 은 지금 탭의 짝만 바꾸고(탭이 늘지 않음), 폴더 비교에서 두 번 누르면 새 탭(사용자 결정). Ctrl+Tab · Ctrl+Shift+Tab · Ctrl+W · 가운데 단추 닫기. 탭이 사라져도 고친 글은 **보관함**(짝 50개)에 남아 다시 열면 되살아난다 — E-1 은 이 보관함을 파일로 옮겨 적으면 된다. 원본이 그 사이 바뀌면 되살리고 알린다("연 시점"은 새로 읽은 글로 둔다). 탭 줄은 ItemsControl 이 아니라 ListBox 다(ItemsControl 은 UIA 에 컨트롤로 안 보여 화면 시험이 못 읽는다). 켤 때 저절로 열리는 짝만 탭이 없어 편집이 사라지던 것을 화면에서 찾아 `EnsureTabForCurrentPair` 로 고쳤다. 켜 놓고 눈으로 보다 두 가지를 더 고쳤다(사용자가 고름) — 중괄호 맞춤으로만 바뀐 것에는 점을 붙이지 않고(묻는 자리와 같은 기준), 탭 이름은 양쪽이 같은 부분을 한 번만 적는다(`WeldController_기준.cs ↔ WeldController_내작...` → `WeldController_기준 ↔ 내작업.cs`, 421 → 288px). 뒤쪽은 확장자일 때만 접는다 — 글자 단위로 세면 `a-lef ↔ right.cs` 처럼 낱말 가운데서 잘린다(하네스에서 걸렸다). 하네스 `DocTabTest` 106건, 화면 34건 · 회귀 19건 통과, 전체 27벌 1,787건 · 실패 0. **커밋 안 함**(사용자 지시) | 아래 | | 2026-09-28 | **시험 도구를 런처에 맞춤** — 새 플랫폼은 `UbisamBase.Launcher.exe` 가 셸을 같은 프로세스에 올려 창 주인 프로세스 이름이 바뀌었고, 예전 이름만 찾던 화면 시험 도구가 전부 "창이 안 뜬다" 로 멈춰 있었다. `a2lib.ps1` 에 `Shell-Procs` · `Shell-Proc` · `Stop-App` 을 두고 `Start-App` · `Get-Win` 이 그것을 쓰게 했다(런처가 제목 없는 진행 창을 먼저 띄우는 경우를 대비해 제목 있는 창을 먼저 고름). 스크립트 76개 · 156곳을 함께 고침. 문법 187개 통과, 끄기 → 켜기 → 창 찾기 → 네 탭 → 단추 → 끄기까지 실제로 돌았고 설정 · 창 자리 네 파일 해시 그대로 되돌림. **제품 코드 변경 없음** | 없음 | diff --git a/doc/진행상황.md b/doc/진행상황.md index ef1673f..b45f8e3 100644 --- a/doc/진행상황.md +++ b/doc/진행상황.md @@ -430,7 +430,8 @@ | 상태 | 항목 | |---|---| -| **완료** | 왼쪽 줄 번호가 밀린다(사용자 보고) — 12차 B-1 로 왼쪽에도 반영할 수 있게 됐는데 왼쪽 번호를 다시 매기는 자리가 없었다. 줄을 넣으면 그 줄은 번호가 비고 뒤 줄은 옛 번호(`01 02 · 03 04 05 · 06`), 저장하면 8줄인데 번호는 6까지. `RenumberBase` 를 두어 두 파일 비교에서만 왼쪽 줄을 1부터 다시 맨다. "머지 반영함" 표시가 BASE 번호를 열쇠로 쓰므로 그 열쇠도 함께 옮긴다. Git · 네 칸은 손대지 않는다 | +| **완료** | `[<]` 단추가 있는 줄만 글이 밀린다(사용자 보고, 그림으로 짚어 줌) — 단추 칸 폭이 `Auto` 라 단추가 보이는 줄만 뒤 칸이 밀렸다(BASE 는 번호까지, LOCAL 은 코드가). `GutterBothWaysWidth` 로 두 칸이 같은 자리를 늘 잡아 두고, 모드에 따라 0 ↔ 단추 폭으로 갈아 끼운다. 편집기 여백도 같이 민다. 값으로 확인: 한 칸의 모든 줄이 같은 x(BASE 137 · LOCAL 1283), 글자 크기 · Git 모드도 그대로 | +| **완료** | 왼쪽 줄 번호가 밀린다(위를 쫓다 따로 찾음) — 12차 B-1 로 왼쪽에도 반영할 수 있게 됐는데 왼쪽 번호를 다시 매기는 자리가 없었다. 줄을 넣으면 그 줄은 번호가 비고 뒤 줄은 옛 번호(`01 02 · 03 04 05 · 06`), 저장하면 8줄인데 번호는 6까지. `RenumberBase` 를 두어 두 파일 비교에서만 왼쪽 줄을 1부터 다시 맨다. "머지 반영함" 표시가 BASE 번호를 열쇠로 쓰므로 그 열쇠도 함께 옮긴다. Git · 네 칸은 손대지 않는다 | | 볼 것 | 왼쪽에만 있는 줄을 `[<]` 로 뺄 때 줄 수가 실제로 주는지 — 따로 열면 되는데 다른 반영 뒤에는 시험 도구가 낡은 줄 칸을 집어 값이 흔들렸다. 번호 불변식은 지켜짐 | ### 시험 도구 diff --git a/src/MergeHub/Views/HomeView.xaml b/src/MergeHub/Views/HomeView.xaml index 1dbe51c..5a8918e 100644 --- a/src/MergeHub/Views/HomeView.xaml +++ b/src/MergeHub/Views/HomeView.xaml @@ -34,6 +34,10 @@ 40 6 20 + + 0 14 9 10 @@ -160,7 +164,8 @@ 66 인 까닭은 LocalLineTemplate 에 적었다(6차 B-4). --> - + + @@ -365,7 +370,8 @@ - + + diff --git a/src/MergeHub/Views/HomeView.xaml.cs b/src/MergeHub/Views/HomeView.xaml.cs index da3953d..be29364 100644 --- a/src/MergeHub/Views/HomeView.xaml.cs +++ b/src/MergeHub/Views/HomeView.xaml.cs @@ -473,6 +473,14 @@ namespace MergeHub.Views return; } + // 두 파일 비교 ↔ Git 을 오가면 [<] 단추가 생기고 사라진다 - 잡아 둘 자리도 함께 바뀐다. + if (e.PropertyName == nameof(HomeViewModel.BothWays)) + { + ApplyGutterReserve(); + ScheduleResync(); + return; + } + if (e.PropertyName != nameof(HomeViewModel.IsThreeWay)) return; ScheduleResync(); @@ -539,6 +547,28 @@ namespace MergeHub.Views /// 한 벌로 바꾼다 - 넷 가운데 하나라도 따로 놀면 행이 어긋난다. /// 행 높이의 하한()도 같이 옮겨야 글자를 줄였을 때 행이 준다. /// + /// 마지막으로 건 크기 한 벌. 모드가 바뀔 때 여백만 다시 잡으려고 들고 있는다. + private CodeFontMetrics _metrics = CodeFontMetrics.For(CodeFontMetrics.Default); + + /// + /// 두 파일 비교에서만 나오는 [<] 단추 자리를 줄마다 늘 잡아 둔다(2026-09-28 사용자 보고). + /// + /// 그 칸을 Auto 로 두었더니 단추가 보이는 줄에서만 칸이 벌어져, 같은 칸 안에서도 + /// 줄마다 글이 시작하는 자리가 달랐다 - 화면에서는 03 · 04 줄만 오른쪽으로 밀려 보였다. + /// 모드에 따라 0 ↔ 단추 폭으로 갈아 끼우면, 한 모드 안에서는 모든 줄이 같은 자리에서 시작한다. + /// Git 모드는 왼쪽이 지난 커밋이라 이 단추가 아예 없으므로 0 - 그때는 여백이 예전 그대로다. + /// + /// 편집기 여백(EditorGutterMargin)도 같은 값만큼 밀어야 한다 - 투명한 편집기와 + /// 아래 표시층이 어긋나면 캐럿이 글자와 다른 자리에 선다. + /// + private void ApplyGutterReserve() + { + var reserve = (DataContext as HomeViewModel)?.BothWays == true ? _metrics.ButtonWidth : 0; + + Resources["GutterBothWaysWidth"] = new GridLength(reserve); + Resources["EditorGutterMargin"] = new Thickness(_metrics.GutterWidth + reserve, 0, 0, 0); + } + private void ApplyCodeFont(double size) { var m = CodeFontMetrics.For(size); @@ -553,7 +583,9 @@ namespace MergeHub.Views Resources["GutterButtonHeight"] = m.ButtonHeight; Resources["GutterButtonFontSize"] = m.ButtonFontSize; Resources["BookmarkHeight"] = m.BookmarkHeight; - Resources["EditorGutterMargin"] = new Thickness(m.GutterWidth, 0, 0, 0); + + _metrics = m; + ApplyGutterReserve(); if (MergeLine.MinimumRowHeight != m.LineHeight) {