11차 F-5: 코드 글자 크기 조절(8~24)

- 한 값을 모든 모니터에(모니터 배율은 플랫폼), 코드 칸만(사용자 결정)
- CodeFontMetrics: 줄 높이 · 번호 칸 · 여백 단추를 같은 비율로, 12 에서 지금 값 그대로
- 화면은 DynamicResource 한 벌, MergeLine.MinimumRowHeight 도 따라감
- Ctrl+휠 · Ctrl++/- · Ctrl+0 · 설정 "보기 > 코드 글자 크기" · 상태 줄 글자 N
- 줄 번호 기준선을 코드와 맞춤
- FontTest 110 · ShortcutTest +14(1,538건)

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
김승준 2026-09-22 16:37:15 +09:00
parent bc97a2d2e5
commit a7b4a728d3
10 changed files with 259 additions and 33 deletions

View File

@ -163,6 +163,7 @@ A-1 에서 값으로 확인한 것 — 지운 파일은 "삭제되어 건너뜀
- F-2: [이 메서드 반영](C# · C/C++, 클래스 멤버 통째, 단추 아래 한 줄에 잡은 범위 · 못 잡은 까닭), 덩어리 · 메서드 반영은 주석 한 줄 · 로그 한 줄 · Undo 한 번. 매뉴얼의 반영 단추 설명에. 숫자 23벌 1,395건. - F-2: [이 메서드 반영](C# · C/C++, 클래스 멤버 통째, 단추 아래 한 줄에 잡은 범위 · 못 잡은 까닭), 덩어리 · 메서드 반영은 주석 한 줄 · 로그 한 줄 · Undo 한 번. 매뉴얼의 반영 단추 설명에. 숫자 23벌 1,395건.
- F-3: 매뉴얼 "탐색기에서 열기" — 여러 개를 골라 보내면 앞의 둘(3개 이상은 알림), 폴더 둘은 바로 폴더 비교, 260자 넘는 경로는 열지 못함(알림), 배포 묶음을 옮겨도 켜면 보내기 바로가기가 따라옴, 설치 파일 필요 없음. 알아 둘 한계에 "떠 있어도 새 창". 숫자 23벌 1,411건. - F-3: 매뉴얼 "탐색기에서 열기" — 여러 개를 골라 보내면 앞의 둘(3개 이상은 알림), 폴더 둘은 바로 폴더 비교, 260자 넘는 경로는 열지 못함(알림), 배포 묶음을 옮겨도 켜면 보내기 바로가기가 따라옴, 설치 파일 필요 없음. 알아 둘 한계에 "떠 있어도 새 창". 숫자 23벌 1,411건.
- F-4: 매뉴얼 파일 비교 화면 — [ACTIONS 감추기] · F9, 아래 탭 줄 [탭 접기] · 띠 · F11(플랫폼), 단축키 표에 F9 · F11. 숫자 23벌 1,414건 · 플랫폼 31건. - F-4: 매뉴얼 파일 비교 화면 — [ACTIONS 감추기] · F9, 아래 탭 줄 [탭 접기] · 띠 · F11(플랫폼), 단축키 표에 F9 · F11. 숫자 23벌 1,414건 · 플랫폼 31건.
- F-5: 매뉴얼 설정 표 "보기 > 코드 글자 크기", 파일 비교 화면 Ctrl+휠 · Ctrl++/- · Ctrl+0 · 상태 줄 `글자 N`, 단축키 표. 숫자 24벌 1,538건.
## B-1. 배포 묶음을 다시 만들고 꼭 필요한 파일을 가림 (2026-09-22, 완료) ## B-1. 배포 묶음을 다시 만들고 꼭 필요한 파일을 가림 (2026-09-22, 완료)
@ -691,6 +692,40 @@ libgit2 의 다듬기(`PrettifyMessages`)를 켜면 **손대지 않은 뒤 커
- ~~플랫폼 배포~~ — 사용자 "배포해줘" 뒤 `publish-platform.ps1`(16:22, 경고 0 · 오류 0, 48개 가운데 Core · Shell · README 셋 바뀜). MergeHub Debug 를 다시 빌드해 두 파일 해시가 배포본과 같음, 배포본으로 [탭 접기] → 24px 띠 → 띠로 펴기 확인(`f4-deployed.ps1`, 화면 설정 · MergeHub 설정 바이트 그대로 되돌림). - ~~플랫폼 배포~~ — 사용자 "배포해줘" 뒤 `publish-platform.ps1`(16:22, 경고 0 · 오류 0, 48개 가운데 Core · Shell · README 셋 바뀜). MergeHub Debug 를 다시 빌드해 두 파일 해시가 배포본과 같음, 배포본으로 [탭 접기] → 24px 띠 → 띠로 펴기 확인(`f4-deployed.ps1`, 화면 설정 · MergeHub 설정 바이트 그대로 되돌림).
- F-6(넓게 보기)에서 몇 줄이 늘었는지 1920 × 1080 기준으로 다시 잰다. - F-6(넓게 보기)에서 몇 줄이 늘었는지 1920 × 1080 기준으로 다시 잰다.
## F-5. 코드 글자 크기 조절 (2026-09-22, 완료)
사용자: "모니터 해상도와 관계없이 모든 모니터에 적용될 수 있도록 하면 좋겠는데".
### 먼저 본 것
- 코드 칸은 `Consolas 12` · 줄 높이 20 으로 박혀 있었다 — 행 템플릿 넷 · 편집기 · `CodeLineHeight` 리소스(StaticResource) · `MergeLine.MinimumRowHeight = 20` 상수. 여백도 번호 46(LOCAL 은 표식 6 + 번호 40) + 단추 20 = 66, 단추 높이 14 · 글자 9 로 박혀 있어 글자만 키우면 번호가 잘리고, 줄이면 단추가 줄보다 커지고 행이 20 아래로 줄지 않는다.
- 플랫폼은 PerMonitorV2 라 WPF 단위(1/96 인치)의 크기는 창이 있는 모니터의 Windows 배율에 맞춰 다시 그려진다.
### 정한 것 (2026-09-22 사용자)
**한 값을 모든 모니터에**(모니터 배율은 플랫폼이 맞춤), **코드 칸만**(앱 전체는 이미 UI Setting 화면 배율), **Ctrl+휠 · Ctrl++/- · Ctrl+0 + 설정**, 8~24.
### 만든 것
- `CodeFontMetrics`(새) — 글자 크기 하나에서 줄 높이 · 여백 · 번호 칸 · 좁은 번호 칸 · 표식 · 단추 칸 · 단추 높이 · 단추 글자를 같은 비율로. 12 에서 지금 값과 정확히 같다(20 · 66 · 46 · 40 · 6 · 20 · 14 · 9).
- 화면: 이 값들을 **DynamicResource** 로(행 템플릿 넷 · 편집기 · 줄 컨테이너 · 편집기 여백), `ApplyCodeFont` 가 한 벌로 갈아 끼운다. `MergeLine.MinimumRowHeight` 를 설정할 수 있는 값으로 바꾸고 바뀌면 모든 행을 다시 잰다.
- 줄 번호에 코드와 같은 줄 높이 규칙(`LineHeight` · `BlockLineHeight`) — 원래 번호가 코드보다 몇 px 위에 떠 있었는데(12 에서 약 6px), 글자를 키우면 그만큼 커져 24 에서 눈에 띄었다. 이제 기준선이 같다.
- 설정 "보기 > 코드 글자 크기 (8~24, 기본 12)"(`CodeFontSize`). 바꿀 때마다 저장, 설정 화면에서 바꾸고 돌아오면 따라감. 단축키 Ctrl+= · Ctrl+숫자판 + · Ctrl+- · Ctrl+숫자판 - · Ctrl+0 · Ctrl+숫자판 0, Ctrl+휠. 상태 줄 커서 위치 옆에 기본이 아닐 때만 `글자 14`(누르면 기본).
### 확인한 것
- 하네스 **FontTest**(새, 110건 — 8~24 모든 크기에서 여백 합 · 단추 ≤ 줄 · 번호 다섯 자리 · 정수 줄 높이, 끝에서 멈춤, NaN · 0 은 기본) · ShortcutTest +14(85건 — 새 키 · 수식키 없는 +/- 는 편집기 몫). 24벌 **1,538건** · 빌드 경고 0 · 오류 0.
- 화면(`f5-verify.ps1`, 1440p · 150%, 코드 칸만 창 그림(PrintWindow)으로 — 다른 창이 찍히지 않게):
| 크기 | 두 칸 행 높이(BASE · LOCAL) | 네 칸 행 높이(Mine · BASE · REMOTE · MERGED) | 여백 단추 |
|---|---|---|---|
| 8 | 19 · 20 번갈아(13 DIP × 1.5) — 두 칸 같음 | 넷 모두 같은 순서로 19 · 20 | 행 안 |
| 12 | 30 | — | 행 안 |
| 24 | 60 | 넷 모두 60 | 행 안 |
- 상태 줄 `글자 8` · `글자 24`, 12 는 비움. 그림: 줄 번호 · 여백 단추 · 코드 · 편집기 글자가 행마다 맞음(24 에서 번호가 뜨던 것을 고친 뒤 다시 찍음).
- **키 시험은 못 함** — 시험 도구가 앱 창을 앞으로 올리지 못했다(사용 중인 다른 창이 있으면 Windows 가 막는다). 키 → 명령은 ShortcutTest, 설정 → 화면은 위 표로 확인. Ctrl+휠 · 키로 바꾼 값이 남는지는 사용자가 한 번 눌러 보는 것으로.
## F-12. C# 코드 스타일 맞춤의 기본값을 AURORA 로 (2026-09-18, 완료) ## F-12. C# 코드 스타일 맞춤의 기본값을 AURORA 로 (2026-09-18, 완료)
사용자: "기본값은 원본형태를 따르고 C#인 경우에 AURORA 스타일로 하자" → 물어서 정한 것은 **제품 기본값 AURORA · C# 파일만 · 저장 동작은 지금 그대로**(켜져 있으면 저장도 그 스타일로 쓴다). 사용자: "기본값은 원본형태를 따르고 C#인 경우에 AURORA 스타일로 하자" → 물어서 정한 것은 **제품 기본값 AURORA · C# 파일만 · 저장 동작은 지금 그대로**(켜져 있으면 저장도 그 스타일로 쓴다).

View File

@ -8,6 +8,7 @@
| 날짜 | 항목 | 커밋 | | 날짜 | 항목 | 커밋 |
|---|---|---| |---|---|---|
| 2026-09-22 | **11차 F-5 (추가 요청)** — 코드 칸 글자 크기 8~24(기본 12). 한 값을 모든 모니터에(사용자 결정 — 모니터마다 다른 Windows 배율은 플랫폼 PerMonitorV2 가 맞춤), 코드 칸만. `CodeFontMetrics` 가 줄 높이 · 번호 칸 · 여백 단추를 같은 비율로 내고(12 에서 지금 값 그대로) 화면이 DynamicResource 로 한 벌 갈아 끼움, `MergeLine.MinimumRowHeight` 도 따라감. Ctrl+휠 · Ctrl++/- · Ctrl+0 · 설정 "보기 > 코드 글자 크기", 상태 줄 `글자 N`. 줄 번호가 코드보다 몇 px 위에 뜨던 것(24 에서 커짐)도 같은 줄 높이 규칙으로 맞춤. 8 · 12 · 24 에서 네 칸 행 높이 같음. FontTest 110 · ShortcutTest +14(1,538건) | 아래 |
| 2026-09-22 | **11차 F-4 (추가 요청)** — 파일 비교 오른쪽 ACTIONS 칸을 감추는 단추 · F9(사용자 결정). 감추면 칸과 구분선 폭을 0 으로 해 코드 칸이 넓어지고, 펴면 끌어 둔 폭 그대로. 설정 `ActionsHidden` 에 기억. 감춘 채 Ctrl+S · Alt+←/→ 그대로. **덧(사용자 요청)**: 아래 탭 줄 접기 — 플랫폼에 [탭 접기] · 띠 · F11 을 넣음(플랫폼 changelog 참고, 사용자 확인 뒤 배포 09-22 16:22). 1440p 150% 에서 코드 칸 폭 +163px · 높이 +71px. ShortcutTest +3 · 플랫폼 PlatformCfgTest +7 | 아래 | | 2026-09-22 | **11차 F-4 (추가 요청)** — 파일 비교 오른쪽 ACTIONS 칸을 감추는 단추 · F9(사용자 결정). 감추면 칸과 구분선 폭을 0 으로 해 코드 칸이 넓어지고, 펴면 끌어 둔 폭 그대로. 설정 `ActionsHidden` 에 기억. 감춘 채 Ctrl+S · Alt+←/→ 그대로. **덧(사용자 요청)**: 아래 탭 줄 접기 — 플랫폼에 [탭 접기] · 띠 · F11 을 넣음(플랫폼 changelog 참고, 사용자 확인 뒤 배포 09-22 16:22). 1440p 150% 에서 코드 칸 폭 +163px · 높이 +71px. ShortcutTest +3 · 플랫폼 PlatformCfgTest +7 | 아래 |
| 2026-09-22 | **11차 F-3 뒤 (사용자 발견)** — 탐색기에서 폴더 둘을 보내면 왼쪽 칸이 설정의 기본 저장소(`plain-compare`)로 덮여 비교가 "왼쪽만" 투성이였다. `FolderViewModel` 이 넘어온 요청을 받은 뒤 "열어 둔 저장소를 왼쪽 기본값으로" 가 덮어쓴 것(비교는 비동기라 덮인 값을 읽음) — 기본값을 먼저, 요청을 나중에. 켤 때 받은 인자를 파일 로그에 남김. 앞선 시험은 로그만 보고 칸 값을 제대로 읽지 않아 지나쳤다 | c35280a | | 2026-09-22 | **11차 F-3 뒤 (사용자 발견)** — 탐색기에서 폴더 둘을 보내면 왼쪽 칸이 설정의 기본 저장소(`plain-compare`)로 덮여 비교가 "왼쪽만" 투성이였다. `FolderViewModel` 이 넘어온 요청을 받은 뒤 "열어 둔 저장소를 왼쪽 기본값으로" 가 덮어쓴 것(비교는 비동기라 덮인 값을 읽음) — 기본값을 먼저, 요청을 나중에. 켤 때 받은 인자를 파일 로그에 남김. 앞선 시험은 로그만 보고 칸 값을 제대로 읽지 않아 지나쳤다 | c35280a |
| 2026-09-22 | **11차 F-3 (추가 요청)** — 탐색기 [보내기] 가 여러 개를 어떻게 넘기는지 셸의 같은 길(바로가기에 Drop)로 일곱 경우를 잼: **프로세스 하나에 인자로 모두**, 폴더 둘은 창 하나에서 폴더 비교까지 됨. 고친 것(사용자 결정): 3개 이상은 앞의 둘 + 알림(예전엔 말없이 버림), 260자 넘는 경로(탐색기가 8.3 이름으로 넘기고 net48 이 긴 이름으로 펼쳐 못 찾음 — 예전엔 아무것도 안 열림)는 열지 않고 까닭 알림, 알림은 이름 창 뒤로 지나가지 않게 본 창이 활성이 된 뒤에. 배포 묶음을 옮기면 켤 때 보내기 바로가기를 지금 실행 파일로 고침(등록한 사람만 · 바로가기 파일만 · 레지스트리 안 씀). 설치 파일 필요 없음 확인. 떠 있을 때 새 창은 그대로(플랫폼 일). ArgsTest +16(1,411건) | 아래 | | 2026-09-22 | **11차 F-3 (추가 요청)** — 탐색기 [보내기] 가 여러 개를 어떻게 넘기는지 셸의 같은 길(바로가기에 Drop)로 일곱 경우를 잼: **프로세스 하나에 인자로 모두**, 폴더 둘은 창 하나에서 폴더 비교까지 됨. 고친 것(사용자 결정): 3개 이상은 앞의 둘 + 알림(예전엔 말없이 버림), 260자 넘는 경로(탐색기가 8.3 이름으로 넘기고 net48 이 긴 이름으로 펼쳐 못 찾음 — 예전엔 아무것도 안 열림)는 열지 않고 까닭 알림, 알림은 이름 창 뒤로 지나가지 않게 본 창이 활성이 된 뒤에. 배포 묶음을 옮기면 켤 때 보내기 바로가기를 지금 실행 파일로 고침(등록한 사람만 · 바로가기 파일만 · 레지스트리 안 씀). 설치 파일 필요 없음 확인. 떠 있을 때 새 창은 그대로(플랫폼 일). ArgsTest +16(1,411건) | 아래 |

View File

@ -374,7 +374,7 @@
| **완료** | F-2 메서드 단위로 골라 반영 — [이 메서드 반영](C# + C/C++, 클래스 멤버 전부 · 사용자 결정), 캐럿이 놓인 멤버를 반영해 올 쪽에서 중괄호 짝으로 잡음(`MemberRanges` — 문자열 · 주석 · raw · `#if` 갈래에 안 속음, 못 잡으면 단추 끄고 까닭 한 줄). 덩어리 · 메서드 반영은 주석 한 줄(메서드 이름 위) · 로그 한 줄 · Undo 한 번 — 덩어리가 줄마다 주석을 달던 것도 고침. 메서드 반영 = 같은 줄 줄 단위 반영 바이트 같음. MemberTest 83건(C# 29 · C++ 13 멤버) · 1,395건 | | **완료** | F-2 메서드 단위로 골라 반영 — [이 메서드 반영](C# + C/C++, 클래스 멤버 전부 · 사용자 결정), 캐럿이 놓인 멤버를 반영해 올 쪽에서 중괄호 짝으로 잡음(`MemberRanges` — 문자열 · 주석 · raw · `#if` 갈래에 안 속음, 못 잡으면 단추 끄고 까닭 한 줄). 덩어리 · 메서드 반영은 주석 한 줄(메서드 이름 위) · 로그 한 줄 · Undo 한 번 — 덩어리가 줄마다 주석을 달던 것도 고침. 메서드 반영 = 같은 줄 줄 단위 반영 바이트 같음. MemberTest 83건(C# 29 · C++ 13 멤버) · 1,395건 |
| **완료** | F-3 탐색기 [보내기] 로 폴더 두 개 바로 비교 — 탐색기는 여러 개를 프로세스 하나에 인자로 모두 넘김(일곱 경우 값으로 잼), 폴더 둘은 창 하나에서 폴더 비교까지. 사용자 결정대로 3개 이상은 앞의 둘 + 알림, 260자 넘는 경로(탐색기가 8.3 이름으로 넘김 · net48 이 못 찾음)는 열지 않고 알림, 옮긴 배포 묶음은 켤 때 보내기 바로가기를 저절로 고침(바로가기 파일만 · 레지스트리 안 씀), 떠 있을 때는 새 창 그대로. 설치 파일 필요 없음. ArgsTest +16 · 1,411건. **사용자가 실제 탐색기에서 찾은 것**: 보낸 왼쪽 폴더를 기본 저장소가 덮어써 "왼쪽만" 투성이 → 기본값을 먼저 두고 요청을 나중에 받게 고침, 켤 때 받은 인자를 파일 로그에 남김 | | **완료** | F-3 탐색기 [보내기] 로 폴더 두 개 바로 비교 — 탐색기는 여러 개를 프로세스 하나에 인자로 모두 넘김(일곱 경우 값으로 잼), 폴더 둘은 창 하나에서 폴더 비교까지. 사용자 결정대로 3개 이상은 앞의 둘 + 알림, 260자 넘는 경로(탐색기가 8.3 이름으로 넘김 · net48 이 못 찾음)는 열지 않고 알림, 옮긴 배포 묶음은 켤 때 보내기 바로가기를 저절로 고침(바로가기 파일만 · 레지스트리 안 씀), 떠 있을 때는 새 창 그대로. 설치 파일 필요 없음. ArgsTest +16 · 1,411건. **사용자가 실제 탐색기에서 찾은 것**: 보낸 왼쪽 폴더를 기본 저장소가 덮어써 "왼쪽만" 투성이 → 기본값을 먼저 두고 요청을 나중에 받게 고침, 켤 때 받은 인자를 파일 로그에 남김 |
| **완료** | F-4 ACTIONS 칸 감추기(단추 · F9, 끌어 둔 폭 기억, 감춰도 Ctrl+S · Alt+←/→ 그대로) + **덧: 아래 탭 줄 접기**(사용자 요청 — 플랫폼 [탭 접기] · 16 DIP 띠 · F11, 그 항목만 기억, 다른 소비 프로그램도 쓰되 기본 펼침). 1440p 150% 에서 코드 칸 폭 +163px · 높이 +71px. 플랫폼 배포함(09-22 16:22) | | **완료** | F-4 ACTIONS 칸 감추기(단추 · F9, 끌어 둔 폭 기억, 감춰도 Ctrl+S · Alt+←/→ 그대로) + **덧: 아래 탭 줄 접기**(사용자 요청 — 플랫폼 [탭 접기] · 16 DIP 띠 · F11, 그 항목만 기억, 다른 소비 프로그램도 쓰되 기본 펼침). 1440p 150% 에서 코드 칸 폭 +163px · 높이 +71px. 플랫폼 배포함(09-22 16:22) |
| 대기 | F-5 글자 크기 조절 (지금은 Consolas 12 고정) | | **완료** | F-5 코드 글자 크기(8~24, 기본 12) — 한 값을 모든 모니터에(모니터 배율은 플랫폼), 코드 칸만, Ctrl+휠 · Ctrl++/- · Ctrl+0 + 설정 "보기 > 코드 글자 크기"(사용자 결정). 줄 높이 · 번호 칸 · 여백 단추가 같은 비율로(`CodeFontMetrics`, 12 에서 지금 값 그대로), 줄 번호 기준선을 코드와 맞춤. 8 · 12 · 24 에서 네 칸 행 높이 같음 · 단추 행 안. FontTest 110 · 1,538건. 키로 바꾸기는 사용자 확인 남음 |
| 대기 | F-6 글자를 되도록 많이 보이게 — 넓게 보기 한 단추, 늘어난 줄 수로 잼 | | 대기 | F-6 글자를 되도록 많이 보이게 — 넓게 보기 한 단추, 늘어난 줄 수로 잼 |
| 대기 | F-7 어느 모니터에서든 제대로 뜨게 — 증상부터 적고 플랫폼 영향 확인 | | 대기 | F-7 어느 모니터에서든 제대로 뜨게 — 증상부터 적고 플랫폼 영향 확인 |
| 대기 | F-8 저장한 뒤에도 되돌리기 (지금은 저장 네 길이 스택을 비움) | | 대기 | F-8 저장한 뒤에도 되돌리기 (지금은 저장 네 길이 스택을 비움) |

View File

@ -94,6 +94,15 @@ namespace MergeHub
[DisplayName("커밋 조회 개수")] [DisplayName("커밋 조회 개수")]
public int CommitPageSize { get; set; } = 200; public int CommitPageSize { get; set; } = 200;
/// <summary>
/// 코드 칸 글자 크기(11차 F-5). 코드 · 줄 번호 · 여백 단추 · 줄 높이가 같은 비율로 따라간다.
/// 한 값이 모든 모니터에 쓰인다 - 모니터마다 다른 Windows 배율은 플랫폼이 맞춘다.
/// 파일 비교 화면에서 Ctrl+휠 · Ctrl++/- · Ctrl+0 으로도 바꾸고, 그 값이 여기 남는다.
/// </summary>
[Category("보기")]
[DisplayName("코드 글자 크기 (8~24, 기본 12)")]
public int CodeFontSize { get; set; } = 12;
[Category("머지 주석")] [Category("머지 주석")]
[DisplayName("반영한 줄에 주석 남기기")] [DisplayName("반영한 줄에 주석 남기기")]
public bool InsertMergeComment { get; set; } = true; public bool InsertMergeComment { get; set; } = true;

View File

@ -201,8 +201,15 @@ namespace MergeHub.Models
/// <summary>읽기 전용 원본 칸들의 행 높이. 2-Way 에서는 RowHeight 와 같다.</summary> /// <summary>읽기 전용 원본 칸들의 행 높이. 2-Way 에서는 RowHeight 와 같다.</summary>
[ObservableProperty] private double _sourceRowHeight = MinimumRowHeight; [ObservableProperty] private double _sourceRowHeight = MinimumRowHeight;
/// <summary>접히지 않은 보통 줄의 높이. HomeView 의 CodeLineHeight 와 같은 값이어야 한다.</summary> /// <summary>
private const double MinimumRowHeight = 20; /// 접히지 않은 보통 줄의 높이. HomeView 의 CodeLineHeight 와 같은 값이어야 한다.
/// 코드 글자 크기를 바꾸면 화면이 이 값을 함께 바꾸고 <see cref="RefreshRowHeight"/> 를 부른다(11차 F-5) -
/// 예전에는 20 으로 박혀 있어 글자를 줄여도 행이 20 아래로 줄지 않았다.
/// </summary>
public static double MinimumRowHeight { get; set; } = 20;
/// <summary>줄 높이 기준이 바뀌었을 때 알던 글 높이로 다시 잰다.</summary>
public void RefreshRowHeight() => ApplyRowHeights();
/// <summary>각 패널이 자기 글이 실제로 얼마나 높은지 알려 준다.</summary> /// <summary>각 패널이 자기 글이 실제로 얼마나 높은지 알려 준다.</summary>
public void ReportTextHeight(TextPane pane, double height) public void ReportTextHeight(TextPane pane, double height)
@ -217,6 +224,11 @@ namespace MergeHub.Models
case TextPane.OriginalLocal: _originalLocalTextHeight = height; break; case TextPane.OriginalLocal: _originalLocalTextHeight = height; break;
} }
ApplyRowHeights();
}
private void ApplyRowHeights()
{
if (IsThreeWay) if (IsThreeWay)
{ {
RowHeight = Math.Max(MinimumRowHeight, _localTextHeight); RowHeight = Math.Max(MinimumRowHeight, _localTextHeight);

View File

@ -0,0 +1,57 @@
using System;
namespace MergeHub.Services
{
/// <summary>
/// 코드 칸 글자 크기 하나에서 나오는 크기들(11차 F-5). 줄 높이 · 줄 번호 칸 · 여백 단추가 같은 비율로 따라간다.
///
/// 기본 12 에서 지금까지의 값(줄 20 · 여백 66 = 번호 46 + 단추 20 · LOCAL 은 표식 6 + 번호 40 + 단추 20 · 단추 14 · 단추 글자 9)과
/// 정확히 같다. 네 칸이 모두 이 값을 쓰므로 어느 크기에서나 행이 같은 눈높이에 온다.
///
/// 크기는 WPF 단위(1/96 인치)다. 모니터마다 Windows 배율은 플랫폼(PerMonitorV2)이 맞추므로
/// 한 값이 어느 모니터에서나 같은 눈 크기로 보인다(사용자 결정 "한 값을 모든 모니터에").
/// </summary>
public sealed record CodeFontMetrics(
double FontSize,
double LineHeight,
double GutterWidth,
double NumberWidth,
double NarrowNumberWidth,
double MarkWidth,
double ButtonWidth,
double ButtonHeight,
double ButtonFontSize)
{
public const double Default = 12;
public const double Min = 8;
public const double Max = 24;
public static double Clamp(double size) =>
double.IsNaN(size) || size <= 0 ? Default : Math.Max(Min, Math.Min(Max, Math.Round(size)));
/// <summary>한 칸(1) 키우거나 줄인다. 끝에서는 그대로.</summary>
public static double Step(double current, int delta) => Clamp(Math.Round(Clamp(current)) + delta);
public static CodeFontMetrics For(double size)
{
var f = Clamp(size);
var k = f / Default;
var mark = Math.Round(6 * k);
var narrow = Math.Round(40 * k);
var button = Math.Round(20 * k);
var number = mark + narrow;
return new CodeFontMetrics(
FontSize: f,
LineHeight: Math.Round(20 * k),
GutterWidth: number + button,
NumberWidth: number,
NarrowNumberWidth: narrow,
MarkWidth: mark,
ButtonWidth: button,
ButtonHeight: Math.Round(14 * k),
ButtonFontSize: Math.Round(9 * k, 1));
}
}
}

View File

@ -35,6 +35,9 @@ namespace MergeHub.Services
CloseFind, CloseFind,
ShowHelp, ShowHelp,
ToggleActions, ToggleActions,
FontBigger,
FontSmaller,
FontReset,
} }
/// <summary>단축키 한 줄. 키 처리와 설명 창이 <b>둘 다 이 목록만</b> 본다.</summary> /// <summary>단축키 한 줄. 키 처리와 설명 창이 <b>둘 다 이 목록만</b> 본다.</summary>
@ -147,6 +150,12 @@ namespace MergeHub.Services
new ShortcutEntry(ShortcutAction.Recompare, Key.F5, ModifierKeys.None, "파일·보기", "다시 비교(새로고침)"), new ShortcutEntry(ShortcutAction.Recompare, Key.F5, ModifierKeys.None, "파일·보기", "다시 비교(새로고침)"),
new ShortcutEntry(ShortcutAction.Recompare, Key.R, ModifierKeys.Control, "파일·보기", "다시 비교 (대체 키)"), new ShortcutEntry(ShortcutAction.Recompare, Key.R, ModifierKeys.Control, "파일·보기", "다시 비교 (대체 키)"),
new ShortcutEntry(ShortcutAction.Save, Key.S, ModifierKeys.Control, "파일·보기", "저장"), new ShortcutEntry(ShortcutAction.Save, Key.S, ModifierKeys.Control, "파일·보기", "저장"),
new ShortcutEntry(ShortcutAction.FontBigger, Key.OemPlus, ModifierKeys.Control, "파일·보기", "코드 글자 크게 (Ctrl+휠 위로도)"),
new ShortcutEntry(ShortcutAction.FontBigger, Key.Add, ModifierKeys.Control, "파일·보기", "코드 글자 크게 (숫자판)"),
new ShortcutEntry(ShortcutAction.FontSmaller, Key.OemMinus, ModifierKeys.Control, "파일·보기", "코드 글자 작게 (Ctrl+휠 아래로도)"),
new ShortcutEntry(ShortcutAction.FontSmaller, Key.Subtract, ModifierKeys.Control, "파일·보기", "코드 글자 작게 (숫자판)"),
new ShortcutEntry(ShortcutAction.FontReset, Key.D0, ModifierKeys.Control, "파일·보기", "코드 글자 기본 크기(12)"),
new ShortcutEntry(ShortcutAction.FontReset, Key.NumPad0, ModifierKeys.Control, "파일·보기", "코드 글자 기본 크기 (숫자판)"),
new ShortcutEntry(ShortcutAction.ToggleActions, Key.F9, ModifierKeys.None, "파일·보기", "오른쪽 ACTIONS 칸 감추기 · 보이기", new ShortcutEntry(ShortcutAction.ToggleActions, Key.F9, ModifierKeys.None, "파일·보기", "오른쪽 ACTIONS 칸 감추기 · 보이기",
"감춰도 저장 · 반영 · 차이 이동 키는 그대로 듣는다. 아래 탭 줄 접기(F11)는 플랫폼 몫이라 이 표에 없다."), "감춰도 저장 · 반영 · 차이 이동 키는 그대로 듣는다. 아래 탭 줄 접기(F11)는 플랫폼 몫이라 이 표에 없다."),

View File

@ -49,6 +49,7 @@ namespace MergeHub.ViewModels
_workspace.CommitChosen += OnCommitChosenElsewhere; _workspace.CommitChosen += OnCommitChosenElsewhere;
_isRulesOpen = _workspace.Settings.ActionsRulesExpanded; _isRulesOpen = _workspace.Settings.ActionsRulesExpanded;
_isActionsHidden = _workspace.Settings.ActionsHidden; _isActionsHidden = _workspace.Settings.ActionsHidden;
_codeFontSize = CodeFontMetrics.Clamp(_workspace.Settings.CodeFontSize);
_reflowTimer.Tick += (_, _) => Reflow(); _reflowTimer.Tick += (_, _) => Reflow();
RefreshRecent(); RefreshRecent();
@ -409,6 +410,34 @@ namespace MergeHub.ViewModels
/// <summary>단추 글자 - 누르면 무엇이 되는지와 키를 함께(RulesToggleLabel 과 같은 까닭).</summary> /// <summary>단추 글자 - 누르면 무엇이 되는지와 키를 함께(RulesToggleLabel 과 같은 까닭).</summary>
public string ActionsToggleLabel => IsActionsHidden ? "◀ ACTIONS 보이기 (F9)" : "ACTIONS 감추기 ▶ (F9)"; public string ActionsToggleLabel => IsActionsHidden ? "◀ ACTIONS 보이기 (F9)" : "ACTIONS 감추기 ▶ (F9)";
/// <summary>
/// 코드 칸 글자 크기(11차 F-5, 8~24). 화면이 줄 높이 · 여백을 함께 맞춘다(<see cref="CodeFontMetrics"/>).
/// 바꿀 때마다 설정에 남긴다 - 한 값이 모든 모니터에 쓰인다.
/// </summary>
[ObservableProperty]
[NotifyPropertyChangedFor(nameof(CodeFontLabel))]
private double _codeFontSize = CodeFontMetrics.Default;
/// <summary>상태 줄에 보일 글. 기본이면 비운다 - 늘 보이면 자리만 먹는다.</summary>
public string CodeFontLabel => CodeFontSize == CodeFontMetrics.Default ? string.Empty : $"글자 {CodeFontSize:0}";
partial void OnCodeFontSizeChanged(double value)
{
var size = (int)CodeFontMetrics.Clamp(value);
if (_workspace.Settings.CodeFontSize == size) return;
_workspace.Settings.CodeFontSize = size;
_workspace.SaveSettings();
}
[RelayCommand]
private void FontBigger() => CodeFontSize = CodeFontMetrics.Step(CodeFontSize, +1);
[RelayCommand]
private void FontSmaller() => CodeFontSize = CodeFontMetrics.Step(CodeFontSize, -1);
[RelayCommand]
private void FontReset() => CodeFontSize = CodeFontMetrics.Default;
[RelayCommand] [RelayCommand]
private void ToggleActions() private void ToggleActions()
{ {
@ -3013,6 +3042,9 @@ namespace MergeHub.ViewModels
/// </summary> /// </summary>
public void RecompareIfSettingsChanged() public void RecompareIfSettingsChanged()
{ {
var font = CodeFontMetrics.Clamp(_workspace.Settings.CodeFontSize);
if (font != CodeFontSize) CodeFontSize = font;
// C# 스타일은 원본부터 다시 읽어야 맞춰진다(편집 칸만 다시 정렬하면 BASE 가 옛 스타일로 남는다). // C# 스타일은 원본부터 다시 읽어야 맞춰진다(편집 칸만 다시 정렬하면 BASE 가 옛 스타일로 남는다).
if (_workspace.Settings.CSharpBraceStyle != _appliedStyle && Lines.Count > 0) if (_workspace.Settings.CSharpBraceStyle != _appliedStyle && Lines.Count > 0)
{ {

View File

@ -22,6 +22,18 @@
<!-- 코드 한 줄의 높이. BASE/LOCAL 이 이 값을 똑같이 써야 두 패널의 같은 행이 같은 눈높이에 온다. --> <!-- 코드 한 줄의 높이. BASE/LOCAL 이 이 값을 똑같이 써야 두 패널의 같은 행이 같은 눈높이에 온다. -->
<system:Double x:Key="CodeLineHeight">20</system:Double> <system:Double x:Key="CodeLineHeight">20</system:Double>
<!-- 코드 글자 크기와 그에 따르는 여백(11차 F-5). 기본 12 의 값이다 - 화면(ApplyCodeFont)이
CodeFontMetrics 로 함께 바꾼다. DynamicResource 로 읽어야 바뀐 값이 바로 그려진다. -->
<system:Double x:Key="CodeFontSize">12</system:Double>
<GridLength x:Key="GutterWidth">66</GridLength>
<GridLength x:Key="GutterNumberWidth">46</GridLength>
<GridLength x:Key="GutterNarrowNumberWidth">40</GridLength>
<GridLength x:Key="GutterMarkWidth">6</GridLength>
<GridLength x:Key="GutterButtonWidth">20</GridLength>
<system:Double x:Key="GutterButtonHeight">14</system:Double>
<system:Double x:Key="GutterButtonFontSize">9</system:Double>
<Thickness x:Key="EditorGutterMargin">66,0,0,0</Thickness>
<!-- BASE / LOCAL 하단 요약 칸 공통 높이. 두 패널의 코드 영역이 같은 크기여야 나란히 읽힌다. --> <!-- BASE / LOCAL 하단 요약 칸 공통 높이. 두 패널의 코드 영역이 같은 크기여야 나란히 읽힌다. -->
<system:Double x:Key="PaneFooterHeight">54</system:Double> <system:Double x:Key="PaneFooterHeight">54</system:Double>
@ -113,7 +125,7 @@
<Style x:Key="Mono" TargetType="TextBlock"> <Style x:Key="Mono" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Consolas"/> <Setter Property="FontFamily" Value="Consolas"/>
<Setter Property="FontSize" Value="12"/> <Setter Property="FontSize" Value="{DynamicResource CodeFontSize}"/>
</Style> </Style>
<!-- <!--
@ -122,8 +134,8 @@
워드랩일 때만 풀어 준다 - 그때는 줄마다 높이가 달라야 하기 때문이다. 워드랩일 때만 풀어 준다 - 그때는 줄마다 높이가 달라야 하기 때문이다.
--> -->
<Style x:Key="CodeLineItem" TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}"> <Style x:Key="CodeLineItem" TargetType="ListBoxItem" BasedOn="{StaticResource {x:Type ListBoxItem}}">
<Setter Property="Height" Value="{StaticResource CodeLineHeight}"/> <Setter Property="Height" Value="{DynamicResource CodeLineHeight}"/>
<Setter Property="MinHeight" Value="{StaticResource CodeLineHeight}"/> <Setter Property="MinHeight" Value="{DynamicResource CodeLineHeight}"/>
<Setter Property="Padding" Value="0"/> <Setter Property="Padding" Value="0"/>
<Setter Property="Margin" Value="0"/> <Setter Property="Margin" Value="0"/>
<Setter Property="VerticalContentAlignment" Value="Top"/> <Setter Property="VerticalContentAlignment" Value="Top"/>
@ -143,10 +155,10 @@
66 인 까닭은 LocalLineTemplate 에 적었다(6차 B-4). --> 66 인 까닭은 LocalLineTemplate 에 적었다(6차 B-4). -->
<Grid MinHeight="{Binding SourceRowHeight}"> <Grid MinHeight="{Binding SourceRowHeight}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="66"/> <ColumnDefinition Width="{DynamicResource GutterWidth}"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding BaseNumberText}" Style="{StaticResource Mono}" <TextBlock Grid.Column="0" Text="{Binding BaseNumberText}" Style="{StaticResource Mono}" LineHeight="{DynamicResource CodeLineHeight}" LineStackingStrategy="BlockLineHeight"
Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right" Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right"
VerticalAlignment="Top" Margin="0,0,8,0"/> VerticalAlignment="Top" Margin="0,0,8,0"/>
<Border Grid.Column="1" Padding="2,0" <Border Grid.Column="1" Padding="2,0"
@ -160,8 +172,8 @@
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
TextWrapping="{Binding WrapMode, TextWrapping="{Binding WrapMode,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
FontFamily="Consolas" FontSize="12" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"
LineHeight="{StaticResource CodeLineHeight}" LineHeight="{DynamicResource CodeLineHeight}"
LineStackingStrategy="BlockLineHeight" LineStackingStrategy="BlockLineHeight"
VerticalAlignment="Top" VerticalAlignment="Top"
SizeChanged="BaseText_SizeChanged"> SizeChanged="BaseText_SizeChanged">
@ -182,17 +194,17 @@
<DataTemplate x:Key="OriginalLocalLineTemplate"> <DataTemplate x:Key="OriginalLocalLineTemplate">
<Grid MinHeight="{Binding SourceRowHeight}"> <Grid MinHeight="{Binding SourceRowHeight}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="46"/> <ColumnDefinition Width="{DynamicResource GutterNumberWidth}"/>
<ColumnDefinition Width="20"/> <ColumnDefinition Width="{DynamicResource GutterButtonWidth}"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding OriginalLocalNumberText}" Style="{StaticResource Mono}" <TextBlock Grid.Column="0" Text="{Binding OriginalLocalNumberText}" Style="{StaticResource Mono}" LineHeight="{DynamicResource CodeLineHeight}" LineStackingStrategy="BlockLineHeight"
Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right" Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right"
VerticalAlignment="Top" Margin="0,0,4,0"/> VerticalAlignment="Top" Margin="0,0,4,0"/>
<Button Grid.Column="1" Content="&lt;" Padding="0" Margin="0" MinWidth="16" <Button Grid.Column="1" Content="&lt;" Padding="0" Margin="0" MinWidth="16"
Height="14" MinHeight="14" FontSize="9" VerticalAlignment="Top" Height="{DynamicResource GutterButtonHeight}" MinHeight="{DynamicResource GutterButtonHeight}" FontSize="{DynamicResource GutterButtonFontSize}" VerticalAlignment="Top"
Visibility="{Binding CanTakeLocal, Converter={StaticResource BoolToVis}}" Visibility="{Binding CanTakeLocal, Converter={StaticResource BoolToVis}}"
Command="{Binding DataContext.TakeLocalLineCommand, Command="{Binding DataContext.TakeLocalLineCommand,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
@ -210,8 +222,8 @@
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
TextWrapping="{Binding WrapMode, TextWrapping="{Binding WrapMode,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
FontFamily="Consolas" FontSize="12" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"
LineHeight="{StaticResource CodeLineHeight}" LineHeight="{DynamicResource CodeLineHeight}"
LineStackingStrategy="BlockLineHeight" LineStackingStrategy="BlockLineHeight"
VerticalAlignment="Top" VerticalAlignment="Top"
SizeChanged="OriginalLocalText_SizeChanged"> SizeChanged="OriginalLocalText_SizeChanged">
@ -232,17 +244,17 @@
<DataTemplate x:Key="RemoteLineTemplate"> <DataTemplate x:Key="RemoteLineTemplate">
<Grid MinHeight="{Binding SourceRowHeight}"> <Grid MinHeight="{Binding SourceRowHeight}">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="46"/> <ColumnDefinition Width="{DynamicResource GutterNumberWidth}"/>
<ColumnDefinition Width="20"/> <ColumnDefinition Width="{DynamicResource GutterButtonWidth}"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="{Binding RemoteNumberText}" Style="{StaticResource Mono}" <TextBlock Grid.Column="0" Text="{Binding RemoteNumberText}" Style="{StaticResource Mono}" LineHeight="{DynamicResource CodeLineHeight}" LineStackingStrategy="BlockLineHeight"
Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right" Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right"
VerticalAlignment="Top" Margin="0,0,4,0"/> VerticalAlignment="Top" Margin="0,0,4,0"/>
<Button Grid.Column="1" Content="&lt;" Padding="0" Margin="0" MinWidth="16" <Button Grid.Column="1" Content="&lt;" Padding="0" Margin="0" MinWidth="16"
Height="14" MinHeight="14" FontSize="9" VerticalAlignment="Top" Height="{DynamicResource GutterButtonHeight}" MinHeight="{DynamicResource GutterButtonHeight}" FontSize="{DynamicResource GutterButtonFontSize}" VerticalAlignment="Top"
Visibility="{Binding CanTakeRemote, Converter={StaticResource BoolToVis}}" Visibility="{Binding CanTakeRemote, Converter={StaticResource BoolToVis}}"
Command="{Binding DataContext.TakeRemoteLineCommand, Command="{Binding DataContext.TakeRemoteLineCommand,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
@ -260,8 +272,8 @@
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
TextWrapping="{Binding WrapMode, TextWrapping="{Binding WrapMode,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
FontFamily="Consolas" FontSize="12" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"
LineHeight="{StaticResource CodeLineHeight}" LineHeight="{DynamicResource CodeLineHeight}"
LineStackingStrategy="BlockLineHeight" LineStackingStrategy="BlockLineHeight"
VerticalAlignment="Top" VerticalAlignment="Top"
SizeChanged="RemoteText_SizeChanged"> SizeChanged="RemoteText_SizeChanged">
@ -295,25 +307,25 @@
MinHeight="{Binding RowHeight}" MinHeight="{Binding RowHeight}"
MouseLeftButtonDown="Gutter_MouseLeftButtonDown"> MouseLeftButtonDown="Gutter_MouseLeftButtonDown">
<Grid.ColumnDefinitions> <Grid.ColumnDefinitions>
<ColumnDefinition Width="6"/> <ColumnDefinition Width="{DynamicResource GutterMarkWidth}"/>
<ColumnDefinition Width="40"/> <ColumnDefinition Width="{DynamicResource GutterNarrowNumberWidth}"/>
<ColumnDefinition Width="20"/> <ColumnDefinition Width="{DynamicResource GutterButtonWidth}"/>
<ColumnDefinition Width="*"/> <ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions> </Grid.ColumnDefinitions>
<!-- 북마크 표식. 켜진 줄만 색 막대가 보인다. --> <!-- 북마크 표식. 켜진 줄만 색 막대가 보인다. -->
<Border Grid.Column="0" Width="4" HorizontalAlignment="Left" CornerRadius="1" <Border Grid.Column="0" Width="4" HorizontalAlignment="Left" CornerRadius="1"
Margin="1,3" VerticalAlignment="Top" Height="14" Margin="1,3" VerticalAlignment="Top" Height="{DynamicResource GutterButtonHeight}"
Background="{DynamicResource Ubisam.Brush.Accent}" Background="{DynamicResource Ubisam.Brush.Accent}"
Visibility="{Binding IsBookmarked, Converter={StaticResource BoolToVis}}"/> Visibility="{Binding IsBookmarked, Converter={StaticResource BoolToVis}}"/>
<TextBlock Grid.Column="1" Text="{Binding LocalNumberText}" Style="{StaticResource Mono}" <TextBlock Grid.Column="1" Text="{Binding LocalNumberText}" Style="{StaticResource Mono}" LineHeight="{DynamicResource CodeLineHeight}" LineStackingStrategy="BlockLineHeight"
Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right" Foreground="{DynamicResource Ubisam.Brush.Muted}" TextAlignment="Right"
VerticalAlignment="Top" Margin="0,0,4,0" VerticalAlignment="Top" Margin="0,0,4,0"
ToolTip="더블클릭하면 북마크를 켜고 끕니다 (F2 로 이동)"/> ToolTip="더블클릭하면 북마크를 켜고 끕니다 (F2 로 이동)"/>
<Button Grid.Column="2" Content="&gt;" Padding="0" Margin="0" MinWidth="16" <Button Grid.Column="2" Content="&gt;" Padding="0" Margin="0" MinWidth="16"
Height="14" MinHeight="14" FontSize="9" VerticalAlignment="Top" Height="{DynamicResource GutterButtonHeight}" MinHeight="{DynamicResource GutterButtonHeight}" FontSize="{DynamicResource GutterButtonFontSize}" VerticalAlignment="Top"
Visibility="{Binding CanTakeBase, Converter={StaticResource BoolToVis}}" Visibility="{Binding CanTakeBase, Converter={StaticResource BoolToVis}}"
Command="{Binding DataContext.TakeLineCommand, Command="{Binding DataContext.TakeLineCommand,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
@ -357,8 +369,8 @@
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
TextWrapping="{Binding WrapMode, TextWrapping="{Binding WrapMode,
RelativeSource={RelativeSource AncestorType=UserControl}}" RelativeSource={RelativeSource AncestorType=UserControl}}"
FontFamily="Consolas" FontSize="12" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"
LineHeight="{StaticResource CodeLineHeight}" LineHeight="{DynamicResource CodeLineHeight}"
LineStackingStrategy="BlockLineHeight" LineStackingStrategy="BlockLineHeight"
VerticalAlignment="Top" VerticalAlignment="Top"
SizeChanged="LocalText_SizeChanged"> SizeChanged="LocalText_SizeChanged">
@ -1252,9 +1264,9 @@
세로 스크롤 막대를 늘 띄워 두는 이유 - 나타났다 사라지면 글 너비가 바뀌어 세로 스크롤 막대를 늘 띄워 두는 이유 - 나타났다 사라지면 글 너비가 바뀌어
워드랩 접히는 자리가 아래층과 어긋난다. 워드랩 접히는 자리가 아래층과 어긋난다.
--> -->
<TextBox x:Name="LocalEditor" Style="{x:Null}" Margin="66,0,0,0" <TextBox x:Name="LocalEditor" Style="{x:Null}" Margin="{DynamicResource EditorGutterMargin}"
FontFamily="Consolas" FontSize="12" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"
TextBlock.LineHeight="{StaticResource CodeLineHeight}" TextBlock.LineHeight="{DynamicResource CodeLineHeight}"
TextBlock.LineStackingStrategy="BlockLineHeight" TextBlock.LineStackingStrategy="BlockLineHeight"
AcceptsReturn="True" AcceptsTab="True" AcceptsReturn="True" AcceptsTab="True"
TextWrapping="{Binding WrapMode, TextWrapping="{Binding WrapMode,
@ -1729,6 +1741,13 @@
<!-- 왼쪽: 지금 어디 --> <!-- 왼쪽: 지금 어디 -->
<StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center"> <StackPanel Grid.Column="0" Orientation="Horizontal" VerticalAlignment="Center">
<TextBlock Text="{Binding CaretPosition}" Style="{StaticResource Mono}" FontSize="11"/> <TextBlock Text="{Binding CaretPosition}" Style="{StaticResource Mono}" FontSize="11"/>
<!-- 11차 F-5: 기본(12)이 아닐 때만 보인다. 누르면 기본으로(Ctrl+0 과 같음). -->
<TextBlock Text="{Binding CodeFontLabel}" FontSize="11" Margin="10,0,0,0" Cursor="Hand"
Style="{StaticResource Muted}" ToolTip="코드 글자 크기 - Ctrl+휠 · Ctrl++/- 로 바꾸고, 누르거나 Ctrl+0 이면 기본(12)">
<TextBlock.InputBindings>
<MouseBinding MouseAction="LeftClick" Command="{Binding FontResetCommand}"/>
</TextBlock.InputBindings>
</TextBlock>
<Border Width="1" Margin="10,1" Background="{DynamicResource Ubisam.Brush.Input.Border}"/> <Border Width="1" Margin="10,1" Background="{DynamicResource Ubisam.Brush.Input.Border}"/>
<!-- <!--
차이 이동을 개수 바로 옆에 둔다(4차 C-5). 차이 이동을 개수 바로 옆에 둔다(4차 C-5).

View File

@ -238,6 +238,15 @@ namespace MergeHub.Views
DataContextChanged += OnDataContextChanged; DataContextChanged += OnDataContextChanged;
// Ctrl+휠로 코드 글자 크기(11차 F-5). 휠 한 칸에 1씩. 목록 · 편집기의 스크롤보다 먼저 가로챈다.
PreviewMouseWheel += (_, e) =>
{
if (Keyboard.Modifiers != ModifierKeys.Control || DataContext is not HomeViewModel vm) return;
var command = e.Delta > 0 ? vm.FontBiggerCommand : vm.FontSmallerCommand;
if (command.CanExecute(null)) command.Execute(null);
e.Handled = true;
};
// 설정 화면에서 비교 규칙을 고치고 돌아오면 그때 다시 비교한다. // 설정 화면에서 비교 규칙을 고치고 돌아오면 그때 다시 비교한다.
IsVisibleChanged += (_, e) => IsVisibleChanged += (_, e) =>
{ {
@ -378,6 +387,7 @@ namespace MergeHub.Views
now.ScrollToRowRequested += OnScrollToRowRequested; now.ScrollToRowRequested += OnScrollToRowRequested;
now.PropertyChanged += OnViewModelPropertyChanged; now.PropertyChanged += OnViewModelPropertyChanged;
ApplyActionsHidden(now.IsActionsHidden); ApplyActionsHidden(now.IsActionsHidden);
ApplyCodeFont(now.CodeFontSize);
// 편집기 글은 이 컨트롤이 들고 있고, ViewModel 은 필요할 때만 읽어 간다. // 편집기 글은 이 컨트롤이 들고 있고, ViewModel 은 필요할 때만 읽어 간다.
// 바인딩으로 매 글자마다 문서 전체를 넘기면 큰 파일에서 눈에 띄게 느리다. // 바인딩으로 매 글자마다 문서 전체를 넘기면 큰 파일에서 눈에 띄게 느리다.
@ -391,6 +401,12 @@ namespace MergeHub.Views
/// </summary> /// </summary>
private void OnViewModelPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e) private void OnViewModelPropertyChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
{ {
if (e.PropertyName == nameof(HomeViewModel.CodeFontSize) && sender is HomeViewModel fontVm)
{
ApplyCodeFont(fontVm.CodeFontSize);
return;
}
if (e.PropertyName == nameof(HomeViewModel.IsActionsHidden) && sender is HomeViewModel hideVm) if (e.PropertyName == nameof(HomeViewModel.IsActionsHidden) && sender is HomeViewModel hideVm)
{ {
ApplyActionsHidden(hideVm.IsActionsHidden); ApplyActionsHidden(hideVm.IsActionsHidden);
@ -456,6 +472,38 @@ namespace MergeHub.Views
/// <summary>칸 폭을 사용자가 끌어 놓을 수 있는 세 칸.</summary> /// <summary>칸 폭을 사용자가 끌어 놓을 수 있는 세 칸.</summary>
private ColumnDefinition[] PaneColumns => new[] { LocalColumn, BaseColumn, RemoteColumn }; private ColumnDefinition[] PaneColumns => new[] { LocalColumn, BaseColumn, RemoteColumn };
/// <summary>
/// 코드 칸 글자 크기를 화면에 건다(11차 F-5). 글자 · 줄 높이 · 줄 번호 칸 · 여백 단추 · 편집기 여백을
/// <see cref="CodeFontMetrics"/> 한 벌로 바꾼다 - 넷 가운데 하나라도 따로 놀면 행이 어긋난다.
/// 행 높이의 하한(<see cref="MergeLine.MinimumRowHeight"/>)도 같이 옮겨야 글자를 줄였을 때 행이 준다.
/// </summary>
private void ApplyCodeFont(double size)
{
var m = CodeFontMetrics.For(size);
Resources["CodeFontSize"] = m.FontSize;
Resources["CodeLineHeight"] = m.LineHeight;
Resources["GutterWidth"] = new GridLength(m.GutterWidth);
Resources["GutterNumberWidth"] = new GridLength(m.NumberWidth);
Resources["GutterNarrowNumberWidth"] = new GridLength(m.NarrowNumberWidth);
Resources["GutterMarkWidth"] = new GridLength(m.MarkWidth);
Resources["GutterButtonWidth"] = new GridLength(m.ButtonWidth);
Resources["GutterButtonHeight"] = m.ButtonHeight;
Resources["GutterButtonFontSize"] = m.ButtonFontSize;
Resources["EditorGutterMargin"] = new Thickness(m.GutterWidth, 0, 0, 0);
if (MergeLine.MinimumRowHeight != m.LineHeight)
{
MergeLine.MinimumRowHeight = m.LineHeight;
if (DataContext is HomeViewModel vm)
{
foreach (var line in vm.Lines) line.RefreshRowHeight();
}
}
Dispatcher.BeginInvoke(new Action(MatchTextWidths), System.Windows.Threading.DispatcherPriority.Loaded);
}
/// <summary>감추기 전 ACTIONS 칸 폭. 구분선을 끌어 바꿔 뒀으면 그 폭으로 돌아온다.</summary> /// <summary>감추기 전 ACTIONS 칸 폭. 구분선을 끌어 바꿔 뒀으면 그 폭으로 돌아온다.</summary>
private GridLength _actionsWidth = new GridLength(214); private GridLength _actionsWidth = new GridLength(214);
@ -942,6 +990,10 @@ namespace MergeHub.Views
case ShortcutAction.ToggleActions: return Run(vm.ToggleActionsCommand); case ShortcutAction.ToggleActions: return Run(vm.ToggleActionsCommand);
case ShortcutAction.FontBigger: return Run(vm.FontBiggerCommand);
case ShortcutAction.FontSmaller: return Run(vm.FontSmallerCommand);
case ShortcutAction.FontReset: return Run(vm.FontResetCommand);
case ShortcutAction.OpenFolderCompare: case ShortcutAction.OpenFolderCompare:
UbisamBase.Core.Modules.TabManager.Activate(ViewIds.Folder); UbisamBase.Core.Modules.TabManager.Activate(ViewIds.Folder);
return true; return true;