Compare commits
3 Commits
b717f4ed06
...
09fb7b9bf6
| Author | SHA1 | Date | |
|---|---|---|---|
| 09fb7b9bf6 | |||
| df06947afc | |||
| 18b05d6b38 |
@ -2,6 +2,23 @@
|
||||
|
||||
지시서: [../작업지시/12차.md](../작업지시/12차.md)
|
||||
|
||||
## Shift+휠 가로 · Ctrl+↓ 와 아래 "지금 줄" 칸 · Ctrl+W 로 폴더 비교 · 다크 모드 (2026-10-01, 사용자 요청 · 결정 · 완료)
|
||||
|
||||
1. **Shift+휠 = 가로 스크롤**(파일 비교 · 메모, 사용자 결정). 예전에는 Ctrl+휠(글자 크기)만 따로 받고 Shift+휠은 세로로 굴렀다.
|
||||
파일 비교는 가로 휠(틸트)과 같은 길(`ScrollSourcePanes` · `ScrollEditor`)로 보낸다 — 마우스가 놓인 칸이 움직이고 나머지는 지금처럼 따라온다. 휠 아래 = 오른쪽.
|
||||
2. **Ctrl+↓ / Ctrl+↑ = 다음 · 이전 차이**(대체 키, 단축키 표에 더함 — 설명 창에도 나온다). 그리고 **아래 "지금 줄" 칸**(사용자 결정: 캐럿 줄 두 줄) —
|
||||
칸과 상태 줄 사이에 캐럿 행의 BASE(변경 전) · LOCAL(변경 후)을 위아래로. 칸과 같은 `CodeTextBlock`(문법 색 · 바뀐 글자 칠하기 · 줄 색), 긴 줄은 접어 끝까지,
|
||||
한쪽에 없는 줄이면 `(이 줄 없음 …)`. `HomeViewModel.CaretLine` — 캐럿이 옮겨지거나 행이 다시 만들어지면(`UpdateSummaries`) 다시 알린다.
|
||||
3. **Ctrl+W 로 닫으면 폴더 비교로**(사용자 결정: 폴더 비교에서 연 파일일 때만). `RequestPlainCompare(fromFolder:)` 로 표시를 실어 보내고
|
||||
(폴더 비교 두 번 누르기 · 폴더 검색 결과), 파일 비교가 문서 탭(`DocTab.FromFolder`)에 붙인다. ◀ 이전 파일 · 다음 파일 ▶ 로 짝을 바꿔도(탭을 새로 만드는 `Replace`) 이어 받는다.
|
||||
그 탭을 닫으면 `TabManager.Activate(ViewIds.Folder)`. 남은 탭은 그대로 다음 탭을 띄워 둔다.
|
||||
"폴더 비교에서 파일을 열면 하단 탭도 파일 비교로" 는 플랫폼 `8158bbf`(배포본 `2026-10-01 13:37:46`)에서 이미 고쳤다 — 그 전 플랫폼인 PC 에서 보인 것.
|
||||
4. **다크 모드 가독성** — 어두운 테마로 켜서 찍어 봤다. 가장 큰 것은 **폴더 비교 목록만 흰 바탕**: 플랫폼 테마가 ListBox · ListView · DataGrid 는 칠하지만
|
||||
TreeView 는 칠하지 않아 WPF 기본(흰 바탕 · 검은 글자)으로 남았다 → 바탕 · 글자색을 테마에서 받고 항목(TreeViewItem) 글자색도 준다(줄 상태 색은 반투명이라 그대로 맞는다).
|
||||
색 구분의 0 항목 흐리기 0.35 → 0.55(어두운 바탕에서 거의 묻혔다). 차이 줄 바탕색 대비는 두 테마가 비슷해(1.2~1.5) 그대로. 꺼진 단추 글자가 흐린 것은 플랫폼 테마 몫이라 손대지 않았다.
|
||||
|
||||
시험(이것만): `g27-five`(새, 어두운 테마) — Shift+휠 편집기 가로 0 → 20%(세로 그대로) · BASE 칸 위에서도 · 메모 0 → 5.7%, Ctrl+↓ 로 차이 2/2 → 1/2 · 아래 칸 BASE · LOCAL 이름표,
|
||||
기본 짝은 Ctrl+W 뒤 파일 비교 그대로 · 폴더 비교에서 연 alpha 는 하단 탭 파일 비교(1) → Ctrl+W 뒤 폴더 비교(0), 사진으로 폴더 목록 어두운 바탕 · 아래 칸 확인. 실패 0. 기존 회귀는 돌리지 않았다.
|
||||
## 전체 반영 · 자동 병합의 주석이 너무 많다 (2026-10-01, 사용자 요청 · 결정 · 완료)
|
||||
|
||||
[전체 반영] 은 반영할 줄마다 `Apply` 를 따로 불러 **바뀐 줄마다 머지 주석 한 줄**, 되돌리기도 줄마다 한 걸음이었다.
|
||||
|
||||
@ -8,6 +8,9 @@
|
||||
|
||||
| 날짜 | 항목 | 커밋 |
|
||||
|---|---|---|
|
||||
| 2026-10-02 | **버전 0.12.1** — `MergeHub.csproj` 의 `<Version>` 0.12.0 → 0.12.1(사용자 결정: 12차 안의 고침 · 추가라 끝자리만). 12차 G 묶음 뒤의 고침(종료 확인 · 스크롤 멈춤 · 전체 반영/자동 병합 주석 · Shift+휠 · 아래 "지금 줄" 칸 · Ctrl+W → 폴더 비교 · 다크 모드)이 들어간 배포본(`배포\MergeHub_v0.12.1_20261002.zip`, 플랫폼 `2026-10-01 13:37:46`). 배포본 이름에서 "알파" 를 뺐다(사용자 결정) | 아래 |
|
||||
| 2026-10-01 | **Shift+휠 가로 · Ctrl+↓ 와 아래 "지금 줄" 칸 · Ctrl+W 로 폴더 비교 · 다크 모드(사용자 요청 · 결정)** — ① Shift+휠 = 가로(파일 비교는 가로 휠과 같은 길, 메모도) ② Ctrl+↓/↑ = 다음 · 이전 차이(대체 키) + 칸과 상태 줄 사이에 캐럿 행의 BASE(변경 전) · LOCAL(변경 후)을 위아래로(같은 `CodeTextBlock`, 긴 줄은 접음, `CaretLine`) ③ 폴더 비교에서 연 탭(`DocTab.FromFolder`, `RequestPlainCompare(fromFolder:)`, ◀ ▶ 로 바꿔도 이어 받음)을 닫으면 폴더 비교로 ④ 폴더 비교 목록이 어두운 테마에서도 흰 바탕 · 검은 글자 — 플랫폼 테마가 TreeView 는 안 칠함 → 테마 바탕 · 글자색, 색 구분 0 항목 흐리기 0.35 → 0.55. 하단 탭이 파일 비교로 안 바뀌던 것은 플랫폼 `8158bbf` 에서 이미 고침. 화면 `g27-five`(새, 어두운 테마) 실패 0. 기존 회귀는 돌리지 않음. 빌드 경고 0 · 오류 0 | 아래 |
|
||||
| 2026-10-01 | **배포 묶음 스크립트를 런처 기준으로(사용자 요청)** — `scripts\make-bundle.ps1` 은 11차(셸을 켜던 때) 것이라 새 플랫폼의 `UbisamBase.Launcher.exe` · 그 설정 · `platform-version.json` 을 "까닭 미상" 으로 경고했다. 셋에 까닭을 적고, 런처와 런처 설정을 꼭 있어야 하는 파일로, 런처 설정의 바인딩 리디렉트 검사를 더함(없으면 켜자마자 죽는다 - 플랫폼 `publish-platform.ps1` 과 같은 검사). `배포묶음.txt` 는 "런처를 켠다" · 런처가 켤 때 하는 일 · 플랫폼 버전. 확인: `-NoBuild` 로 44개 · 경고 없음, 묶음에서 런처로 켜고 끔. 같은 날 알파판 ZIP(`배포\MergeHub_v0.12_alpha_20261001.zip`, 커밋 `b717f4e` · 플랫폼 `2026-10-01 13:37:46`)은 지난번 알파판 구성(Release 출력 + `UbisamPlatform\bin` + 설치안내)으로 따로 만들었다 | 아래 |
|
||||
| 2026-10-01 | **전체 반영 · 자동 병합의 주석을 구간마다 한 줄로(사용자 요청 · 결정)** — 줄마다 머지 주석이 붙던 것. ① 두 파일 비교 [전체 반영]: 반영할 수 있는 줄이 이어진 구간마다 [구간 반영] 과 같게(`ApplyGroup`), 지우는 반영은 `삭제 N줄`, 모든 구간을 한 묶음으로 Undo 한 번 ② 3-Way [전체 반영] 끔 — 차이 나는 모든 줄을 공통 조상으로 바꾸던 동작(꺼져도 툴팁으로 까닭) ③ 3-Way [자동 병합]: 저쪽만 고친 줄 구간마다 주석 한 줄 · Undo 한 번(충돌 · 내 줄은 구간을 끊고 그대로). 화면 `g22-accept-all` 주석 7 → 3, `g23-three-way`(`--merge`) 5 → 2, 실패 0. 기존 회귀는 돌리지 않음. 빌드 경고 0 · 오류 0 | 아래 |
|
||||
| 2026-10-01 | **스크롤을 내리면 프로그램이 뻗던 것(사용자 보고)** — 어제 칸 맞추기(`f105bab`) 뒤 응답 없음. ① 사람이 BASE 를 굴려도 LOCAL 기준으로 되돌려 초당 32번 밀고 당김 → 손이 닿은 칸(휠 · 누름 · 키)을 기준으로, LOCAL 쪽일 때만 BASE 를 맞춤 ② 따라 굴러가는 도중에 재서 보정값이 휠 한 칸씩 6,619px 까지 쌓임 → 메아리 막기 중이면 큰 맞추기는 앱이 한가할 때 한 번, 못 굴리면 실제로 움직인 만큼만 ③ 칸 목록(그 칸에 있는 줄만)의 항목 번호를 정렬 행 번호로 써 엉뚱한 줄끼리 견줌 → 줄 객체로 오감 ④ 빠르게 굴리면 사람의 스크롤이 메아리로 버려져 따라가는 칸이 멈춤 → 멈춘 뒤 한 번 따라잡기, BASE 를 굴릴 때 보정값을 보이는 줄에서 다시 잼. 화면 `g20-scroll-end` · `g21-blocks-fast`(새) 응답 · 따라옴, `g7` 실패 0, `g17` 통과. 사용자 파일로는 확인 안 함 · 기존 회귀는 돌리지 않음. 빌드 경고 0 · 오류 0 | 아래 |
|
||||
| 2026-09-30 | **끌 때 저장하지 않은 편집을 묻는다(사용자 요청 · 결정)** — 파일 비교의 모든 탭(지금 화면 · Git 모드 · 뒤 탭 · 닫은 탭, 메모 제외)에 편집이 있으면 [저장하고 종료] · [저장하지 않고 종료] · [취소]. 저장은 기존 길(`SaveWorkingCopy` · `WritePlainFile`), 하나라도 실패하면 끄지 않음. 버리면 걸려 있던 보관 쓰기를 기다린 뒤 보관본을 비워 다음에 안 살아남. 플랫폼 `ICloseGuard` 사용(수정 없음) — 곧바로 답하면 셸의 `Close()` 가 Closing 안에서 불려 창이 안 꺼져 `await Task.Yield()` 로 비켜섬. 화면 `g19-exit-confirm` 다섯 경우 실패 0(Git 모드는 화면 시험 안 함). **기존 회귀는 사용자 지시로 돌리지 않음.** 빌드 경고 0 · 오류 0 | 아래 |
|
||||
|
||||
@ -446,6 +446,7 @@
|
||||
|
||||
| 상태 | 항목 |
|
||||
|---|---|
|
||||
| **완료** | **Shift+휠 가로 · Ctrl+↓ 와 아래 "지금 줄" 칸 · Ctrl+W 로 폴더 비교 · 다크 모드**(사용자 요청 · 결정) — Shift+휠 가로(파일 비교 · 메모), Ctrl+↓/↑ 차이 이동 대체 키 + 캐럿 행의 BASE · LOCAL 을 아래에 위아래로, 폴더 비교에서 연 탭을 닫으면 폴더 비교로, 폴더 비교 목록이 어두운 테마에서도 흰 바탕이던 것(TreeView 는 플랫폼 테마가 안 칠함) · 0 항목 흐리기 완화. 화면 `g27-five` 실패 0 |
|
||||
| **완료** | **전체 반영 · 자동 병합의 주석이 너무 많다**(사용자 요청 · 결정) — 두 파일 비교 [전체 반영] 을 구간 반영처럼(구간마다 주석 한 줄 · Undo 한 번), 3-Way [전체 반영] 은 끔(공통 조상으로 되돌리는 동작이었다), 3-Way [자동 병합] 도 구간마다 주석 한 줄 · Undo 한 번. 화면 `g22` 주석 7 → 3, `g23` 5 → 2, 실패 0 |
|
||||
| **완료** | **스크롤을 내리면 프로그램이 뻗는다**(사용자 보고, 어제 `f105bab` 뒤) — 응답 없음(AppHang). 원인 넷: BASE 를 굴려도 LOCAL 쪽으로 되돌려 밀고 당김 · 따라 굴러가는 도중에 재서 보정값이 6,619px 까지 쌓임 · 칸 목록 항목 번호를 정렬 행 번호로 씀(한쪽에만 있는 줄만큼 엉뚱한 줄끼리 견줌) · 빠르게 굴리면 사람의 스크롤이 버려짐. 손이 닿은 칸을 기준으로, 큰 맞추기는 한가할 때 한 번, 줄 객체로 오가기, 버려지면 멈춘 뒤 따라잡기. 화면 `g20` · `g21`(새) 응답, `g7` 실패 0, `g17` 통과 |
|
||||
| **완료** | **끌 때 저장하지 않은 편집을 묻는다**(사용자 요청 · 결정) — 파일 비교의 모든 탭(Git 모드 · 뒤 탭 · 닫은 탭 포함, 메모 제외)에 편집이 있으면 [저장하고 종료] · [저장하지 않고 종료] · [취소]. 버리면 보관본도 비워 다음에 안 살아남. 플랫폼 `ICloseGuard` 를 그대로 씀(플랫폼 수정 없음). 화면 `g19-exit-confirm` 실패 0. Git 모드는 화면 시험 안 함 · 기존 회귀는 사용자 지시로 안 돌림 |
|
||||
|
||||
@ -12,8 +12,12 @@
|
||||
# powershell -ExecutionPolicy Bypass -File scripts\make-bundle.ps1
|
||||
# powershell -ExecutionPolicy Bypass -File scripts\make-bundle.ps1 -Out D:\배포\MergeHub_베타 -NoBuild
|
||||
#
|
||||
# 셸과 플랫폼 dll 은 빌드할 때 플랫폼 배포 폴더(D:\UbisamPlatform\bin)에서 복사되어 온다.
|
||||
# 런처 · 셸 · 플랫폼 dll 은 빌드할 때 플랫폼 배포 폴더(D:\UbisamPlatform\bin)에서 복사되어 온다.
|
||||
# 플랫폼을 새로 배포했다면 이 스크립트를 다시 돌려야 묶음에 반영된다.
|
||||
#
|
||||
# 켜는 것은 UbisamBase.Launcher.exe 다(2026-10-01, 공용 플랫폼의 런처 방식). 런처는 켤 때마다
|
||||
# D:\UbisamPlatform\bin 을 자기 폴더로 복사해 오고(업데이트도 확인) 같은 프로세스 안에서 셸을 띄운다.
|
||||
# 셸을 직접 눌러도 같은 폴더의 런처로 넘긴다. 그 폴더가 없는 PC 에서는 경고 창 뒤 묶음 안의 파일로 뜬다.
|
||||
|
||||
param(
|
||||
# 묶음을 만들 폴더. 이미 있으면 이 스크립트가 만든 묶음일 때만 비우고 다시 채운다.
|
||||
@ -54,7 +58,7 @@ $Excluded = [ordered]@{
|
||||
"MergeHub.pdb" = "디버그 심볼"
|
||||
"LibGit2Sharp.dll.config" = "Mono 용 dll 대응표 - .NET Framework 는 lib\win32 를 스스로 찾는다"
|
||||
"Lang\" = "비어 있음 - 없으면 켤 때 플랫폼(LanguageService)이 만든다"
|
||||
"README.txt" = "플랫폼 배포 폴더 안내문 - 묶음에는 맞지 않아 배포묶음.txt 로 바꿈"
|
||||
"README.txt" = "플랫폼 배포 폴더 안내문 - 묶음에는 맞지 않아 배포묶음.txt 로 바꿈(런처가 켤 때 플랫폼 배포 폴더에서 다시 가져온다)"
|
||||
}
|
||||
|
||||
# ---- 넣는 것이 왜 필요한지 (배포묶음.txt 에 적음) -------------------------
|
||||
@ -64,7 +68,10 @@ function Why([string]$path) {
|
||||
}
|
||||
function Reason([string]$path) {
|
||||
switch -Regex ($path) {
|
||||
'^UbisamBase\.Shell\.exe$' { "셸 - 이것을 켠다" }
|
||||
'^UbisamBase\.Launcher\.exe$' { "런처 - 이것을 켠다. 플랫폼 배포 폴더를 복사해 온 뒤 같은 프로세스에서 셸을 띄운다" }
|
||||
'^UbisamBase\.Launcher\.exe\.config$' { "런처 설정 - 셸이 런처 프로세스 안에서 돌아 실제로 쓰이는 바인딩 리디렉트(없으면 켜자마자 죽는다)" }
|
||||
'^platform-version\.json$' { "플랫폼 버전 도장 - 런처가 업데이트를 확인할 때 견준다" }
|
||||
'^UbisamBase\.Shell\.exe$' { "셸 - 런처가 띄운다(직접 눌러도 런처로 넘긴다)" }
|
||||
'^UbisamBase\.Shell\.exe\.config$' { "셸 설정 - .NET 4.8 · 어셈블리 버전 맞춤" }
|
||||
'^UbisamBase\.Core\.dll$' { "플랫폼" }
|
||||
'^MergeHub\.dll$' { "MergeHub - 셸이 폴더의 dll 을 훑어 찾는다" }
|
||||
@ -121,28 +128,34 @@ foreach ($rel in $files) {
|
||||
}
|
||||
|
||||
# 꼭 있어야 하는 것
|
||||
foreach ($must in "UbisamBase.Shell.exe", "UbisamBase.Shell.exe.config", "UbisamBase.Core.dll", "MergeHub.dll", "LibGit2Sharp.dll") {
|
||||
foreach ($must in "UbisamBase.Launcher.exe", "UbisamBase.Launcher.exe.config", "UbisamBase.Shell.exe", "UbisamBase.Shell.exe.config", "UbisamBase.Core.dll", "MergeHub.dll", "LibGit2Sharp.dll") {
|
||||
if (-not (Test-Path (Join-Path $Out $must))) { throw "묶음에 $must 가 없습니다." }
|
||||
}
|
||||
if (-not (Get-ChildItem (Join-Path $Out "lib\win32\x64") -Filter "git2-*.dll" -ErrorAction SilentlyContinue)) { throw "묶음에 lib\win32\x64\git2-*.dll 이 없습니다." }
|
||||
# 셸은 런처 프로세스 안에서 돈다 - 런처 설정에 바인딩 리디렉트가 없으면 켜자마자 FileLoadException 으로 죽는다(플랫폼 publish-platform.ps1 과 같은 검사).
|
||||
if (-not (Select-String -Path (Join-Path $Out "UbisamBase.Launcher.exe.config") -Pattern "assemblyBinding" -Quiet)) { throw "런처 설정에 바인딩 리디렉트가 없습니다." }
|
||||
|
||||
# ---- 4. 배포묶음.txt --------------------------------------------------------
|
||||
$total = ($kept | Measure-Object Size -Sum).Sum
|
||||
$commit = try { (& git -C $root rev-parse --short HEAD 2>$null) } catch { "-" }
|
||||
$dll = Get-Item (Join-Path $Out "MergeHub.dll")
|
||||
$shell = Get-Item (Join-Path $Out "UbisamBase.Shell.exe")
|
||||
$platformVersion = try { (Get-Content (Join-Path $Out "platform-version.json") -Raw | ConvertFrom-Json).version } catch { "-" }
|
||||
$mb = { param($b) "{0:N1}MB" -f ($b / 1MB) }
|
||||
|
||||
$lines = @()
|
||||
$lines += "MergeHub 배포 묶음"
|
||||
$lines += "=================="
|
||||
$lines += ""
|
||||
$lines += "UbisamBase.Shell.exe 를 켠다. 설치 없이 폴더째 복사해 쓴다."
|
||||
$lines += "UbisamBase.Launcher.exe 를 켠다. 설치 없이 폴더째 복사해 쓴다."
|
||||
$lines += "런처는 켤 때마다 D:\UbisamPlatform\bin(공용 플랫폼)을 이 폴더로 복사해 오고 업데이트를 확인한 뒤 셸을 띄운다."
|
||||
$lines += "그 폴더가 없는 PC 에서는 '플랫폼 파일을 갱신하는 중 문제' 경고 뒤 이 폴더 안의 파일로 그대로 뜬다."
|
||||
$lines += "UbisamBase.Shell.exe 를 직접 눌러도 런처로 넘어간다."
|
||||
$lines += "설정 · 로그는 D:\UbisamConfig 에 쓴다(플랫폼)."
|
||||
$lines += ""
|
||||
$lines += "만든 시각 : " + (Get-Date -Format "yyyy-MM-dd HH:mm:ss")
|
||||
$lines += "MergeHub : " + $dll.LastWriteTime.ToString("yyyy-MM-dd HH:mm") + " (커밋 $commit)"
|
||||
$lines += "셸 · 플랫폼 : " + $shell.LastWriteTime.ToString("yyyy-MM-dd HH:mm") + " (D:\UbisamPlatform\bin 에서 온 것)"
|
||||
$lines += "셸 · 플랫폼 : " + $shell.LastWriteTime.ToString("yyyy-MM-dd HH:mm") + " (D:\UbisamPlatform\bin 에서 온 것 · 플랫폼 버전 $platformVersion)"
|
||||
$lines += ("파일 {0}개 · {1}" -f $kept.Count, (& $mb $total))
|
||||
$lines += ""
|
||||
$lines += "[ 들어 있는 것 ]"
|
||||
|
||||
@ -12,7 +12,7 @@
|
||||
<!-- 프로그램 정보 창(12차 B-2)이 실행 파일에서 읽는 값들. 손으로 적은 글이 아니라 이 값이 보인다.
|
||||
차수에 맞춰 올린다 - 12차 = 0.12.x. 여기만 고치면 창 · 파일 속성이 함께 따라간다. -->
|
||||
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
|
||||
<Version>0.12.0</Version>
|
||||
<Version>0.12.1</Version>
|
||||
<Product>MergeHub</Product>
|
||||
<Company>UbiSam</Company>
|
||||
<!-- 사내 문의처 받침값(12차 G-5). 설정의 "사내 문의처" 가 비면 정보 창이 이것을 보인다 -
|
||||
|
||||
@ -68,6 +68,9 @@ namespace MergeHub.Services
|
||||
/// <summary>화면에 없는 동안 맡아 둔 편집. 떠 있는 탭은 화면이 주인이라 비어 있다.</summary>
|
||||
public DocTabState? Parked { get; set; }
|
||||
|
||||
/// <summary>폴더 비교에서 연 탭. 닫으면 폴더 비교로 돌아간다(2026-10-01 사용자 요청).</summary>
|
||||
public bool FromFolder { get; set; }
|
||||
|
||||
private bool _isDirty;
|
||||
|
||||
/// <summary>저장하지 않은 편집이 있는가. 탭 이름 앞 · 표시에 쓴다.</summary>
|
||||
|
||||
@ -653,11 +653,13 @@ namespace MergeHub.Services
|
||||
/// 찾은 줄을 눈으로 다시 찾아야 한다.
|
||||
/// </param>
|
||||
/// <param name="lineIsLeft">그 번호가 왼쪽 파일 기준인지. 아니면 오른쪽 기준이다.</param>
|
||||
public void RequestPlainCompare(string leftFile, string rightFile, int line = 0, bool lineIsLeft = true)
|
||||
/// <param name="fromFolder">폴더 비교에서 열었는지. 파일 비교가 그 문서 탭에 적어 두고, 탭을 닫으면 폴더 비교로 돌려보낸다.</param>
|
||||
public void RequestPlainCompare(string leftFile, string rightFile, int line = 0, bool lineIsLeft = true, bool fromFolder = false)
|
||||
{
|
||||
_pendingPlainCompare = (leftFile, rightFile);
|
||||
RequestedLine = line;
|
||||
RequestedLineIsLeft = lineIsLeft;
|
||||
RequestedFromFolder = fromFolder;
|
||||
OnUi(DeliverPendingPlainCompare);
|
||||
}
|
||||
|
||||
@ -695,6 +697,17 @@ namespace MergeHub.Services
|
||||
/// <summary>그 번호가 왼쪽 파일 기준인지.</summary>
|
||||
public bool RequestedLineIsLeft { get; private set; }
|
||||
|
||||
/// <summary>넘긴 짝을 폴더 비교에서 열었는지.</summary>
|
||||
public bool RequestedFromFolder { get; private set; }
|
||||
|
||||
/// <summary>폴더 비교에서 열었는지를 한 번 쓰고 지운다 - 다음에 다른 길로 연 짝까지 끌려가지 않게.</summary>
|
||||
public bool TakeRequestedFromFolder()
|
||||
{
|
||||
var one = RequestedFromFolder;
|
||||
RequestedFromFolder = false;
|
||||
return one;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 짚어 줄 자리를 한 번 쓰고 지운다.
|
||||
/// 지우지 않으면 그 다음에 연 파일까지 같은 줄로 끌려간다.
|
||||
|
||||
@ -114,6 +114,8 @@ namespace MergeHub.Services
|
||||
new ShortcutEntry(ShortcutAction.PrevDiff, Key.Up, ModifierKeys.Alt, "차이 이동", "이전 차이"),
|
||||
new ShortcutEntry(ShortcutAction.NextDiff, Key.F4, ModifierKeys.None, "차이 이동", "다음 차이 (대체 키)"),
|
||||
new ShortcutEntry(ShortcutAction.PrevDiff, Key.F4, ModifierKeys.Shift, "차이 이동", "이전 차이 (대체 키)"),
|
||||
new ShortcutEntry(ShortcutAction.NextDiff, Key.Down, ModifierKeys.Control, "차이 이동", "다음 차이 (대체 키)"),
|
||||
new ShortcutEntry(ShortcutAction.PrevDiff, Key.Up, ModifierKeys.Control, "차이 이동", "이전 차이 (대체 키)"),
|
||||
new ShortcutEntry(ShortcutAction.FirstDiff, Key.Home, ModifierKeys.Alt, "차이 이동", "파일의 첫 차이"),
|
||||
new ShortcutEntry(ShortcutAction.LastDiff, Key.End, ModifierKeys.Alt, "차이 이동", "파일의 마지막 차이"),
|
||||
new ShortcutEntry(ShortcutAction.FirstDiff, Key.Home, ModifierKeys.Control, "차이 이동", "첫 차이 (대체 키)"),
|
||||
|
||||
@ -650,7 +650,7 @@ namespace MergeHub.ViewModels
|
||||
|
||||
// 오른쪽에서만 나온 줄이면 오른쪽 파일 기준 번호다.
|
||||
_workspace.RequestPlainCompare(hit.LeftPath, hit.RightPath, hit.LineNumber,
|
||||
lineIsLeft: hit.Side != SearchSide.Right);
|
||||
lineIsLeft: hit.Side != SearchSide.Right, fromFolder: true);
|
||||
UbisamBase.Core.Modules.TabManager.Activate(ViewIds.Home);
|
||||
}
|
||||
|
||||
@ -762,7 +762,7 @@ namespace MergeHub.ViewModels
|
||||
|
||||
// 요청을 먼저 걸고 탭을 연다. 파일 비교 화면이 아직 없으면 그 화면이 만들어지면서
|
||||
// 남아 있는 요청을 직접 집어 간다(GitWorkspace.RequestPlainCompare 설명 참고).
|
||||
_workspace.RequestPlainCompare(node.LeftPath, node.RightPath);
|
||||
_workspace.RequestPlainCompare(node.LeftPath, node.RightPath, fromFolder: true);
|
||||
UbisamBase.Core.Modules.TabManager.Activate(ViewIds.Home);
|
||||
}
|
||||
|
||||
|
||||
@ -319,6 +319,10 @@ namespace MergeHub.ViewModels
|
||||
SyncTabItems();
|
||||
SaveSession(); // 12차 E-1 - 닫아도 글은 남는다. 그 자리에서 적어 둔다.
|
||||
|
||||
// 폴더 비교에서 연 파일을 닫았으면 폴더 비교로 돌아간다(2026-10-01 사용자 요청 - 목록에서 하나씩 열어 보고 닫는 손버릇).
|
||||
// 남은 탭은 그대로 다음 탭을 띄워 둔다 - 파일 비교 탭으로 돌아오면 거기서 이어진다.
|
||||
if (tab.FromFolder) UbisamBase.Core.Modules.TabManager.Activate(ViewIds.Folder);
|
||||
|
||||
if (next is null || ReferenceEquals(next, tab)) return;
|
||||
|
||||
_resumeTab = next;
|
||||
|
||||
@ -133,7 +133,12 @@ namespace MergeHub.ViewModels
|
||||
// 탭을 먼저 잡아 둔다. 아래 LoadPlainFilesAsync 가 다 읽은 뒤 맡겨 둔 편집을 되살린다.
|
||||
var replaceTab = _replaceTab;
|
||||
_replaceTab = false;
|
||||
|
||||
// 폴더 비교에서 연 짝이면 탭에 적어 둔다 - 닫으면 폴더 비교로 돌아간다. ◀ 이전 파일 · 다음 파일 ▶ 은 폴더 목록을
|
||||
// 훑는 것이라 탭을 새로 만들어도(Replace) 그 표시를 이어 받는다.
|
||||
var fromFolder = _workspace.TakeRequestedFromFolder() || (replaceTab && Tabs.Current?.FromFolder == true);
|
||||
OpenPairInTab(leftFile, rightFile, replaceTab);
|
||||
if (fromFolder && Tabs.Current is { } openedTab) openedTab.FromFolder = true;
|
||||
|
||||
// 3-Way 를 끄되 그 때문에 본문을 다시 읽지는 않게 한다 - 그 재로드가 작업 게이트를
|
||||
// 먼저 잡으면 바로 아래 파일 비교가 "다른 작업 진행 중"으로 건너뛰어진다.
|
||||
@ -3668,8 +3673,15 @@ namespace MergeHub.ViewModels
|
||||
AcceptBlockToBaseCommand.NotifyCanExecuteChanged(); // 12차 G-2 - 왼쪽으로 보내는 짝
|
||||
AcceptMemberCommand.NotifyCanExecuteChanged();
|
||||
OnPropertyChanged(nameof(MemberHint));
|
||||
OnPropertyChanged(nameof(CaretLine));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 캐럿이 있는 행. 화면 아래 "지금 줄" 칸이 이 행의 BASE · LOCAL 을 위아래로 보여 준다(2026-10-01 사용자 요청 -
|
||||
/// 다음 차이로 옮겨 가면 무엇이 바뀌었는지 아래에서 한 줄씩 견줘 보고 싶다). 행이 다시 만들어지면 <see cref="UpdateSummaries"/> 가 다시 알린다.
|
||||
/// </summary>
|
||||
public MergeLine? CaretLine => CaretRow >= 0 && CaretRow < Lines.Count ? Lines[CaretRow] : null;
|
||||
|
||||
/// <summary>상태바에 띄우는 "차이 3 / 15".</summary>
|
||||
[ObservableProperty] private string _diffPosition = "차이 -";
|
||||
|
||||
@ -4233,6 +4245,8 @@ namespace MergeHub.ViewModels
|
||||
|
||||
private void UpdateSummaries()
|
||||
{
|
||||
OnPropertyChanged(nameof(CaretLine)); // 행이 다시 만들어지면 아래 "지금 줄" 칸이 옛 행을 붙들지 않게
|
||||
|
||||
// 줄을 고르거나 머지 주석이 끼어들면 결과 줄 수가 바뀐다. 그릴 때마다 번호를 다시 매긴다(8차 B-3).
|
||||
RenumberMerged(Lines);
|
||||
RenumberBase(Lines); // 왼쪽도 마찬가지다(12차 B-1 로 왼쪽이 바뀔 수 있게 됐다)
|
||||
|
||||
@ -12,8 +12,11 @@ namespace MergeHub.Views.Controls
|
||||
/// </summary>
|
||||
public sealed class ZeroToDimConverter : IValueConverter
|
||||
{
|
||||
/// <summary>0 일 때의 흐리기. 읽히기는 하되 눈이 먼저 가지는 않는 정도.</summary>
|
||||
private const double Dim = 0.35;
|
||||
/// <summary>
|
||||
/// 0 일 때의 흐리기. 읽히기는 하되 눈이 먼저 가지는 않는 정도.
|
||||
/// 0.35 는 어두운 테마에서 바탕에 거의 묻혔다(2026-10-01 사용자 보고) - 두 테마 모두 읽히는 0.55 로.
|
||||
/// </summary>
|
||||
private const double Dim = 0.55;
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
|
||||
value is int count && count == 0 ? Dim : 1.0;
|
||||
|
||||
@ -107,6 +107,8 @@
|
||||
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}"/>
|
||||
<!-- 줄 배경이 오른쪽 끝까지 가도록 항목을 가로로 늘린다. -->
|
||||
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
|
||||
<!-- WPF 기본 TreeViewItem 은 글자색을 시스템 검정으로 박아 둔다 - 테마 글자색으로(어두운 테마). -->
|
||||
<Setter Property="Foreground" Value="{DynamicResource Ubisam.Brush.ContentForeground}"/>
|
||||
</Style>
|
||||
</ResourceDictionary>
|
||||
</UserControl.Resources>
|
||||
@ -366,8 +368,12 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<!-- 바탕 · 글자색을 테마에서 받는다(2026-10-01 사용자 보고 "다크 모드에서 잘 안 보인다"). 플랫폼 테마는 ListBox · ListView ·
|
||||
DataGrid 는 칠하지만 TreeView 는 칠하지 않아, 어두운 테마에서도 이 목록만 WPF 기본(흰 바탕 · 검은 글자)으로 남았다. -->
|
||||
<TreeView Grid.Row="0" x:Name="Tree" BorderThickness="1"
|
||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"
|
||||
Background="{DynamicResource Ubisam.Brush.ContentBackground}"
|
||||
Foreground="{DynamicResource Ubisam.Brush.ContentForeground}"
|
||||
ItemsSource="{Binding Nodes}"
|
||||
ItemTemplate="{StaticResource NodeTemplate}"
|
||||
ItemContainerStyle="{StaticResource NodeItemStyle}"
|
||||
|
||||
@ -555,6 +555,8 @@
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="*"/>
|
||||
<!-- 지금 줄 전/후(2026-10-01). 캐럿이 있는 행의 BASE · LOCAL 을 위아래로. -->
|
||||
<RowDefinition Height="Auto"/>
|
||||
<!-- 상태바. 패널 안이 아니라 창 아래 한 줄로 둔다(4차 C-2). -->
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
@ -1991,6 +1993,94 @@
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!--
|
||||
③-1 지금 줄 전/후 (2026-10-01 사용자 요청).
|
||||
다음 차이(Alt+↓ · Ctrl+↓)로 옮겨 가면 그 행의 BASE(변경 전) · LOCAL(변경 후)을 위아래 두 줄로 견줘 보인다 -
|
||||
나란한 두 칸에서는 긴 줄의 바뀐 곳이 옆으로 멀리 떨어져 눈이 오가야 했다(WinMerge 의 아래 비교 칸과 같은 뜻).
|
||||
칸과 같은 그리기(CodeTextBlock: 문법 색 · 바뀐 글자 칠하기 · 줄 색)를 쓴다. 긴 줄은 접어 끝까지 보인다.
|
||||
-->
|
||||
<Border Grid.Row="3" Padding="8,3" BorderThickness="1,1,1,0" Margin="0,2,0,0"
|
||||
Background="{DynamicResource Ubisam.Brush.Sidebar.Background}"
|
||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"
|
||||
DataContext="{Binding CaretLine}">
|
||||
<Border.Style>
|
||||
<Style TargetType="Border">
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding}" Value="{x:Null}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</Border.Style>
|
||||
<Grid>
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="Auto"/>
|
||||
<ColumnDefinition Width="*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="Auto"/>
|
||||
<RowDefinition Height="Auto"/>
|
||||
</Grid.RowDefinitions>
|
||||
|
||||
<TextBlock Grid.Row="0" Grid.Column="0" Text="BASE" Style="{StaticResource PanelTitle}" FontSize="11"
|
||||
VerticalAlignment="Top" Margin="0,1,8,0" ToolTip="변경 전 (왼쪽 칸)"/>
|
||||
<TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding BaseNumberText}" Style="{StaticResource Mono}"
|
||||
Foreground="{DynamicResource Ubisam.Brush.Muted}" MinWidth="36" TextAlignment="Right"
|
||||
VerticalAlignment="Top" Margin="0,0,8,0"/>
|
||||
<Border Grid.Row="0" Grid.Column="2" Padding="2,0"
|
||||
Background="{Binding Highlight, Converter={StaticResource HighlightBrush}}">
|
||||
<Grid>
|
||||
<ctl:CodeTextBlock Code="{Binding BaseText}" Words="{Binding BaseWords}"
|
||||
InBlockComment="{Binding BaseInComment}"
|
||||
CodeLanguage="{Binding DataContext.Language, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
HighlightSyntax="{Binding DataContext.SyntaxHighlight, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
TextWrapping="Wrap" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"/>
|
||||
<TextBlock Text="(이 줄 없음 - LOCAL 에만 있다)" FontSize="11">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource Muted}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasBase}" Value="False">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<TextBlock Grid.Row="1" Grid.Column="0" Text="LOCAL" Style="{StaticResource PanelTitle}" FontSize="11"
|
||||
VerticalAlignment="Top" Margin="0,3,8,0" ToolTip="변경 후 (오른쪽 칸 · 편집하는 글)"/>
|
||||
<TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding LocalNumberText}" Style="{StaticResource Mono}"
|
||||
Foreground="{DynamicResource Ubisam.Brush.Muted}" MinWidth="36" TextAlignment="Right"
|
||||
VerticalAlignment="Top" Margin="0,2,8,0"/>
|
||||
<Border Grid.Row="1" Grid.Column="2" Padding="2,0" Margin="0,2,0,0"
|
||||
Background="{Binding Highlight, Converter={StaticResource HighlightBrush}}">
|
||||
<Grid>
|
||||
<ctl:CodeTextBlock Code="{Binding LocalText}" Words="{Binding LocalWords}"
|
||||
InBlockComment="{Binding LocalInComment}"
|
||||
CodeLanguage="{Binding DataContext.Language, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
HighlightSyntax="{Binding DataContext.SyntaxHighlight, RelativeSource={RelativeSource AncestorType=UserControl}}"
|
||||
TextWrapping="Wrap" FontFamily="Consolas" FontSize="{DynamicResource CodeFontSize}"/>
|
||||
<TextBlock Text="(이 줄 없음 - BASE 에만 있다)" FontSize="11">
|
||||
<TextBlock.Style>
|
||||
<Style TargetType="TextBlock" BasedOn="{StaticResource Muted}">
|
||||
<Setter Property="Visibility" Value="Collapsed"/>
|
||||
<Style.Triggers>
|
||||
<DataTrigger Binding="{Binding HasLocal}" Value="False">
|
||||
<Setter Property="Visibility" Value="Visible"/>
|
||||
</DataTrigger>
|
||||
</Style.Triggers>
|
||||
</Style>
|
||||
</TextBlock.Style>
|
||||
</TextBlock>
|
||||
</Grid>
|
||||
</Border>
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!--
|
||||
④ 상태바 — 창 아래 한 줄.
|
||||
|
||||
@ -2002,7 +2092,7 @@
|
||||
<b>자리 규칙</b> - 왼쪽은 지금 어디에 있는지, 가운데는 얼마나 남았는지, 오른쪽은 이 파일이 무엇인지.
|
||||
패널 밖으로 나오면서 두 패널의 코드 영역 높이가 저절로 같아진다.
|
||||
-->
|
||||
<Border Grid.Row="3" Padding="8,4" BorderThickness="1,1,1,1" Margin="0,2,0,0"
|
||||
<Border Grid.Row="4" Padding="8,4" BorderThickness="1,1,1,1" Margin="0,2,0,0"
|
||||
Background="{DynamicResource Ubisam.Brush.Sidebar.Background}"
|
||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
|
||||
<Grid>
|
||||
|
||||
@ -241,6 +241,15 @@ namespace MergeHub.Views
|
||||
// Ctrl+휠로 코드 글자 크기(11차 F-5). 휠 한 칸에 1씩. 목록 · 편집기의 스크롤보다 먼저 가로챈다.
|
||||
PreviewMouseWheel += (_, e) =>
|
||||
{
|
||||
// Shift+휠은 가로로(2026-10-01 사용자 요청 - VS · 브라우저와 같은 손버릇). 가로 휠(틸트)과 같은 길로 보낸다 -
|
||||
// 마우스가 놓인 칸이 움직이고 나머지는 지금처럼 따라온다. 휠을 아래로 굴리면 오른쪽으로 간다.
|
||||
if (Keyboard.Modifiers == ModifierKeys.Shift)
|
||||
{
|
||||
var step = -e.Delta / 120.0 * 48;
|
||||
if (ScrollSourcePanes(step) || ScrollEditor(step)) e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Keyboard.Modifiers != ModifierKeys.Control || DataContext is not HomeViewModel vm) return;
|
||||
var command = e.Delta > 0 ? vm.FontBiggerCommand : vm.FontSmallerCommand;
|
||||
_scrollDriver = MergeLine.TextPane.Local; // 확대 뒤에는 BASE 를 LOCAL 에 맞춘다
|
||||
|
||||
@ -68,6 +68,14 @@ namespace MergeHub.Views
|
||||
// Ctrl+휠로 글자 크기(파일 비교 F-5 와 같은 손버릇).
|
||||
PreviewMouseWheel += (_, e) =>
|
||||
{
|
||||
// Shift+휠은 가로로(2026-10-01 사용자 요청, 파일 비교와 같게). 휠을 아래로 굴리면 오른쪽으로.
|
||||
if (Keyboard.Modifiers == ModifierKeys.Shift)
|
||||
{
|
||||
Editor.ScrollToHorizontalOffset(Math.Max(0, Editor.HorizontalOffset - e.Delta / 120.0 * 48));
|
||||
e.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Keyboard.Modifiers != ModifierKeys.Control) return;
|
||||
var size = Editor.FontSize + (e.Delta > 0 ? 1 : -1);
|
||||
Editor.FontSize = Math.Max(8, Math.Min(28, size));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user