From aa30988a3551e76ad990872453aed13f72e6dab3 Mon Sep 17 00:00:00 2001 From: ksj09406 Date: Thu, 10 Sep 2026 21:59:16 +0900 Subject: [PATCH] =?UTF-8?q?=EC=97=94=ED=84=B0=20=EA=B3=A0=EC=B9=A8?= =?UTF-8?q?=EC=9D=B4=20=EB=A7=8C=EB=93=A0=20=EB=90=98=EB=8F=8C=EC=9D=B4=20?= =?UTF-8?q?=EB=AC=B8=EC=A0=9C=EB=A5=BC=20=EA=B3=A0=EC=B9=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit TextChanged 안에서 재정렬을 부르니 편집기 글을 자기 이벤트 안에서 갈아 끼우게 됐다. 캐럿이 엉키고 글자가 엉뚱한 자리에 찍혔다. 타이머 간격을 1ms 로 두어 이 입력이 끝난 다음 차례에 돌게 했다. 속도는 그대로다. --- doc/history/2026-09-10-4차.md | 30 +++++++++++++++++++++++- doc/history/changelog.md | 2 ++ src/MergeHub/ViewModels/HomeViewModel.cs | 26 +++++++++++++++----- 3 files changed, 51 insertions(+), 7 deletions(-) diff --git a/doc/history/2026-09-10-4차.md b/doc/history/2026-09-10-4차.md index ce58d9b..6294edf 100644 --- a/doc/history/2026-09-10-4차.md +++ b/doc/history/2026-09-10-4차.md @@ -388,4 +388,32 @@ MERGED 바닥② 편집 0건 · 되돌리기 0건 · 남은 차이 10 라인 | **엔터가 글자 한 자와 구별되지 않는 수준이 됐다.** 예전에는 0.6초 동안 아무것도 안 나왔다. 2000줄에서도 200줄과 같은 값이 나오는 것을 보면 재정렬 자체는 이 크기에서 문제가 아니다. -화면에서도 확인했다 - 엔터로 넣은 빈 줄이 양쪽 칸에 곧바로 나타나고 정렬이 어긋나지 않는다. \ No newline at end of file +화면에서도 확인했다 - 엔터로 넣은 빈 줄이 양쪽 칸에 곧바로 나타나고 정렬이 어긋나지 않는다. +### 엔터 고침이 만든 되돌이 문제 — **고침** (2026-09-10) + +**사용자 지적** - "엔터 줄바꿈하고 글자가 이상하게 찍히고 커서 포인트 줄도 안 맞아." + +**내가 만든 문제였다.** 바로 위에서 "그 자리에서 재정렬" 하도록 고쳤는데, 그 자리가 +편집기의 `TextChanged` 이벤트 안이었다. 재정렬은 편집기 글을 통째로 갈아 끼우고 +캐럿 자리도 다시 잡는다(`OnEditorTextReplaced`). **자기 이벤트 안에서 자기 글을 바꾸는 셈**이라 +캐럿이 엉키고 뒤따라오던 글자가 엉뚱한 자리에 찍혔다. + +**고친 방법** - 부르는 자리를 한 차례 뒤로 물렸다. 타이머 간격을 상황에 따라 나눈다. + +| 상황 | 간격 | 왜 | +|---|---|---| +| 보통 타이핑 | 600ms | 글자마다 다시 정렬하면 화면이 요동친다 | +| 줄 수가 바뀜 | **1ms** | 늦추려는 것이 아니라 이 입력이 끝난 다음 차례에 돌게 하려는 것 | + +`0` 이 아니라 `1ms` 인 까닭이 그것이다. 값이 아니라 차례가 목적이다. + +**다시 확인한 것** + +| 확인 | 결과 | +|---|---| +| 2행 끝에서 엔터 → `added` 입력 | 3행에 정확히 `added`, 캐럿 `3행 6열` | +| 양쪽 칸 정렬 | BASE 01·02 · 빈 줄 · 03·04 / LOCAL 01·02·03·04·05 로 줄이 맞는다 | +| 엔터 20번 | 622ms (한 번당 31ms) — 글자 치기와 같은 값 유지 | + +**남길 것** - 화면 반응을 앞당길 때 어느 이벤트 안에서 부르는지를 먼저 봐야 한다. +"바로 부른다"가 "지금 이 자리에서 부른다"가 되면 되돌이가 생긴다. \ No newline at end of file diff --git a/doc/history/changelog.md b/doc/history/changelog.md index 5d75fba..0ef6759 100644 --- a/doc/history/changelog.md +++ b/doc/history/changelog.md @@ -8,6 +8,7 @@ | 날짜 | 항목 | 커밋 | |---|---|---| +| 2026-09-10 | **엔터 고침의 되돌이 문제** — TextChanged 안에서 편집기 글을 갈아 끼워 캐럿이 엉켰다. 한 차례 뒤로 물림 | 아래 | | 2026-09-10 | **엔터 반응 지연** — 줄 수가 바뀌면 0.6초 타이머만 기다리느라 화면이 비어 있었다. 그 자리에서 다시 맞추게 고침 | 아래 | | 2026-09-10 | **4차 C-2** — 아래쪽 세 군데 상태 정보를 창 아래 한 줄로. 두 패널 코드 높이가 저절로 맞는다 | 아래 | | 2026-09-10 | **4차 C-1 다시** — 머리글을 파일 이름만으로 줄인 것이 잘못이었다. 두 경로에서 다른 부분만 남기게 고침 | 아래 | @@ -35,6 +36,7 @@ | 날짜 | 문서 | 내용 | |---|---|---| +| 2026-09-10 | **엔터 고침의 되돌이 문제** — TextChanged 안에서 편집기 글을 갈아 끼워 캐럿이 엉켰다. 한 차례 뒤로 물림 | 아래 | | 2026-09-10 | **엔터 반응 지연** — 줄 수가 바뀌면 0.6초 타이머만 기다리느라 화면이 비어 있었다. 그 자리에서 다시 맞추게 고침 | 아래 | | 2026-09-10 | **4차 C-2** — 아래쪽 세 군데 상태 정보를 창 아래 한 줄로. 두 패널 코드 높이가 저절로 맞는다 | 아래 | | 2026-09-10 | **4차 C-1 다시** — 머리글을 파일 이름만으로 줄인 것이 잘못이었다. 두 경로에서 다른 부분만 남기게 고침 | 아래 | diff --git a/src/MergeHub/ViewModels/HomeViewModel.cs b/src/MergeHub/ViewModels/HomeViewModel.cs index b2e5738..2efe1c3 100644 --- a/src/MergeHub/ViewModels/HomeViewModel.cs +++ b/src/MergeHub/ViewModels/HomeViewModel.cs @@ -28,8 +28,7 @@ namespace MergeHub.ViewModels private readonly Stack _redo = new Stack(); /// 타이핑이 멈춘 뒤에 다시 정렬하려고 두는 짧은 대기. - private readonly DispatcherTimer _reflowTimer = - new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(600) }; + private readonly DispatcherTimer _reflowTimer = new DispatcherTimer(); public HomeViewModel(GitWorkspace workspace) { @@ -1412,19 +1411,34 @@ namespace MergeHub.ViewModels if (ShowTypedLineNow(text, caretIndex)) { // 지금 치는 줄은 이미 화면에 나왔다. 무거운 BASE 재정렬만 손이 멈춘 뒤로 미룬다. + _reflowTimer.Interval = ReflowAfterTyping; _reflowTimer.Start(); return; } // 줄 수가 달라졌다 - 엔터 · 줄 합치기 · 여러 줄 붙여넣기. // - // 한 줄만 고쳐서는 맞출 수 없는 경우인데, 예전에는 여기서도 타이머에만 맡겼다. - // 편집기 글자는 투명이라 그 0.6초 동안 화면에 아무것도 나오지 않았다 - + // 한 줄만 고쳐서는 맞출 수 없는 경우인데, 예전에는 여기서도 0.6초 타이머에 맡겼다. + // 편집기 글자는 투명이라 그 동안 화면에 아무것도 나오지 않았다 - // "엔터를 누르면 한참 뒤에 반응한다"는 것의 정체가 이것이다. - // 지금은 그 자리에서 다시 맞춘다. 사람이 칠 수 있는 속도에서는 이쪽이 훨씬 싸다. - Reflow(); + // + // 그렇다고 이 자리에서 바로 부르면 안 된다. 재정렬은 편집기 글을 통째로 갈아 끼우는데, + // 지금은 편집기의 TextChanged 안이다. 자기 이벤트 안에서 자기 글을 바꾸면 캐럿이 엉키고 + // 뒤따라오던 글자가 엉뚱한 자리에 찍힌다(실제로 그렇게 됐다). + // 타이머를 짧게 놓아 이 입력이 끝난 바로 다음 차례에 돌게 한다. + _reflowTimer.Interval = ReflowNow; + _reflowTimer.Start(); } + /// 타이핑이 멈추기를 기다리는 시간. 글자마다 다시 정렬하면 화면이 요동친다. + private static readonly TimeSpan ReflowAfterTyping = TimeSpan.FromMilliseconds(600); + + /// + /// 기다리지 않고 바로. 다만 0 이 아니라 1ms 다 - 지금 이벤트가 끝난 다음 차례에 + /// 돌게 하려는 것이지, 늦추려는 것이 아니다. + /// + private static readonly TimeSpan ReflowNow = TimeSpan.FromMilliseconds(1); + /// /// 캐럿이 있는 줄 하나만 표시층에 바로 반영한다. ///