D-1: 주석만 다른 파일을 다른 색으로
폴더 비교에 "주석만 다름" 상태를 새로 두었다. 코드는 같고 주석/공백만 다른 파일이다. 봐야 할 성격이 다르다. 주석만 손댄 파일은 눈으로 훑고 넘길 수 있는데 다른 것과 같은 색으로 섞여 있으면 전부 열어 봐야 한다. 판단은 주석 토큰을 걷어내고 공백을 지운 뒤 견주는 것이다. 주석 기호는 언어마다 다르므로 확장자로 고른 언어표를 따르고, 언어를 모르는 파일은 하지 않는다. 양쪽 확장자가 다르면 같은 언어로 볼 근거가 없으니 역시 하지 않는다. 줄 구분은 코드가 있는 줄에만 남긴다. 큰 파일은 건너뛴다. 곁들여 색 뜻풀이 줄을 목록 위에 붙이고, 보기 필터에 "코드가 다른 것만"을 더했다. 주석만 다른 것을 빼고 보는 쪽이 실제로 필요한 동작이다. 확인: 주석만 고친 .cs 는 회색 "주석만 다름", 값이 바뀐 .cs 와 평문 .txt 는 노란 "다름". "코드가 다른 것만"을 고르면 앞의 것이 빠진다. FolderTest 4건 추가. 전체 428건 통과. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
5c8c942ba5
commit
451b6245cb
31
doc/진행상황.md
31
doc/진행상황.md
@ -126,7 +126,7 @@ CommunityToolkit 커맨드는 CommandManager 를 구독하지 않는데 이 둘
|
|||||||
|
|
||||||
| 상태 | 항목 |
|
| 상태 | 항목 |
|
||||||
|---|---|
|
|---|---|
|
||||||
| 대기 | D-1 주석만 다른 파일을 다른 색으로 |
|
| **완료** | D-1 주석만 다른 파일을 다른 색으로 |
|
||||||
| **완료** | D-2 C++ 문법 강조 (이미 되고 있었음 · 전처리 지시문만 추가) |
|
| **완료** | D-2 C++ 문법 강조 (이미 되고 있었음 · 전처리 지시문만 추가) |
|
||||||
| 대기 | D-3 폴더 안 전체 검색 |
|
| 대기 | D-3 폴더 안 전체 검색 |
|
||||||
| ~~취소~~ | ~~D-4 비교 창 여러 개~~ (2026-09-09 사용자 판단으로 뺌) |
|
| ~~취소~~ | ~~D-4 비교 창 여러 개~~ (2026-09-09 사용자 판단으로 뺌) |
|
||||||
@ -147,6 +147,35 @@ CommunityToolkit 커맨드는 CommandManager 를 구독하지 않는데 이 둘
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
### D-1. 주석만 다른 파일을 다른 색으로 — **완료** (2026-09-09)
|
||||||
|
|
||||||
|
폴더 비교 결과에 `주석만 다름` 상태를 새로 두었다. 코드는 같고 주석·공백만 다른 파일이다.
|
||||||
|
|
||||||
|
**왜 나누나** - 봐야 할 성격이 다르다. 주석만 손댄 파일은 눈으로 훑고 넘길 수 있는데
|
||||||
|
다른 것과 같은 색으로 섞여 있으면 전부 열어 봐야 한다.
|
||||||
|
|
||||||
|
**판단하는 법**: 주석 토큰을 걷어내고 공백을 지운 뒤 견준다. 주석 기호는 언어마다 다르므로
|
||||||
|
확장자로 고른 언어표를 따르고, 언어를 모르는 파일(평문·표)은 이 판단을 하지 않는다 -
|
||||||
|
주석이라는 것이 없다. 양쪽 확장자가 다르면 같은 언어로 볼 근거가 없으니 역시 하지 않는다.
|
||||||
|
|
||||||
|
줄 구분은 <b>코드가 있는 줄에만</b> 남긴다. 그래야 주석 한 줄을 통째로 지운 경우도 같다고 보고,
|
||||||
|
반대로 코드를 다른 줄로 옮긴 것은 다르다고 본다.
|
||||||
|
|
||||||
|
큰 파일은 이 판단을 건너뛴다. 전체 비교에서 이미 쓰는 한도(8MB)를 그대로 따른다 -
|
||||||
|
폴더 하나에 수천 개가 있을 때 이 판단만으로 몇 분이 더 들면 안 된다.
|
||||||
|
|
||||||
|
**곁들여 둘**
|
||||||
|
|
||||||
|
- <b>색 뜻풀이 줄</b>을 목록 위에 붙였다. 색만 칠해 두면 무슨 뜻인지 아무도 모른다 -
|
||||||
|
파일 비교 화면의 "색 구분" 줄과 같은 성격이다.
|
||||||
|
- 보기 필터에 <b>코드가 다른 것만</b>을 더했다. 주석만 다른 것을 빼고 보는 쪽이
|
||||||
|
실제로 필요한 동작이다.
|
||||||
|
|
||||||
|
**확인**: 주석만 고친 `.cs` 는 회색 `주석만 다름`, 값이 바뀐 `.cs` 와 평문 `.txt` 는 노란 `다름`.
|
||||||
|
`코드가 다른 것만` 을 고르면 앞의 것이 목록에서 빠진다.
|
||||||
|
`FolderTest` 4건 추가(37 → 41건).
|
||||||
|
---
|
||||||
|
|
||||||
### D-2 · D-5 — **완료** (2026-09-09)
|
### D-2 · D-5 — **완료** (2026-09-09)
|
||||||
|
|
||||||
#### D-2. C++ 문법 강조
|
#### D-2. C++ 문법 강조
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
|
using MergeHub.Views.Controls;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace MergeHub.Services
|
namespace MergeHub.Services
|
||||||
@ -18,7 +19,15 @@ namespace MergeHub.Services
|
|||||||
/// <summary>오른쪽에만 있다.</summary>
|
/// <summary>오른쪽에만 있다.</summary>
|
||||||
RightOnly,
|
RightOnly,
|
||||||
/// <summary>내용이 다르지만 이진 파일이라 줄 단위로 볼 수 없다.</summary>
|
/// <summary>내용이 다르지만 이진 파일이라 줄 단위로 볼 수 없다.</summary>
|
||||||
Binary
|
Binary,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// <b>코드는 같고 주석·공백만</b> 다르다.
|
||||||
|
///
|
||||||
|
/// 따로 두는 이유 - 봐야 할 성격이 다르다. 주석만 손댄 파일은 눈으로 훑고 넘길 수 있는데
|
||||||
|
/// 다른 것과 같은 색으로 섞여 있으면 전부 열어 봐야 한다.
|
||||||
|
/// </summary>
|
||||||
|
CommentOnly
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>폴더 비교 규칙.</summary>
|
/// <summary>폴더 비교 규칙.</summary>
|
||||||
@ -250,7 +259,7 @@ namespace MergeHub.Services
|
|||||||
if (!item.LeftExists) return FolderEntryStatus.RightOnly;
|
if (!item.LeftExists) return FolderEntryStatus.RightOnly;
|
||||||
|
|
||||||
// 크기가 다르면 내용을 볼 필요가 없다.
|
// 크기가 다르면 내용을 볼 필요가 없다.
|
||||||
if (item.LeftSize != item.RightSize) return DifferentKind(leftPath, rightPath);
|
if (item.LeftSize != item.RightSize) return DifferentKind(leftPath, rightPath, Math.Max(item.LeftSize, item.RightSize), options);
|
||||||
|
|
||||||
var quick = options.QuickCompare || item.LeftSize > options.FullCompareLimitBytes;
|
var quick = options.QuickCompare || item.LeftSize > options.FullCompareLimitBytes;
|
||||||
|
|
||||||
@ -262,19 +271,108 @@ namespace MergeHub.Services
|
|||||||
var gap = left > right ? left - right : right - left;
|
var gap = left > right ? left - right : right - left;
|
||||||
return gap <= options.TimeTolerance
|
return gap <= options.TimeTolerance
|
||||||
? FolderEntryStatus.Same
|
? FolderEntryStatus.Same
|
||||||
: DifferentKind(leftPath, rightPath);
|
: DifferentKind(leftPath, rightPath, Math.Max(item.LeftSize, item.RightSize), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
return SameContent(leftPath, rightPath)
|
return SameContent(leftPath, rightPath)
|
||||||
? FolderEntryStatus.Same
|
? FolderEntryStatus.Same
|
||||||
: DifferentKind(leftPath, rightPath);
|
: DifferentKind(leftPath, rightPath, Math.Max(item.LeftSize, item.RightSize), options);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>다른 파일이 이진이면 따로 표시한다 - 줄 단위 비교 화면을 열어도 볼 것이 없다.</summary>
|
/// <summary>
|
||||||
private static FolderEntryStatus DifferentKind(string leftPath, string rightPath) =>
|
/// 다른 파일을 어떤 "다름"으로 볼지.
|
||||||
TextFile.IsBinary(leftPath) || TextFile.IsBinary(rightPath)
|
///
|
||||||
? FolderEntryStatus.Binary
|
/// 이진이면 줄 단위 비교 화면을 열어도 볼 것이 없으니 따로 표시한다.
|
||||||
|
/// 글 파일이면 <b>코드는 같고 주석만 다른지</b>를 한 번 더 본다.
|
||||||
|
/// </summary>
|
||||||
|
private static FolderEntryStatus DifferentKind(string leftPath, string rightPath, long size,
|
||||||
|
FolderCompareOptions options)
|
||||||
|
{
|
||||||
|
if (TextFile.IsBinary(leftPath) || TextFile.IsBinary(rightPath)) return FolderEntryStatus.Binary;
|
||||||
|
|
||||||
|
return OnlyCommentsDiffer(leftPath, rightPath, size, options)
|
||||||
|
? FolderEntryStatus.CommentOnly
|
||||||
: FolderEntryStatus.Different;
|
: FolderEntryStatus.Different;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 코드는 같고 <b>주석·공백만</b> 다른가.
|
||||||
|
///
|
||||||
|
/// 판단은 주석 토큰을 걷어내고 공백을 지운 뒤 견주는 것이다. 주석 기호는 언어마다 다르므로
|
||||||
|
/// 확장자로 고른 언어표를 따른다. 언어를 모르는 파일(평문·표 등)은 이 판단을 하지 않는다 -
|
||||||
|
/// 주석이라는 것이 없다.
|
||||||
|
///
|
||||||
|
/// 줄 구분은 <b>코드가 있는 줄에만</b> 남긴다. 그래야 주석 한 줄을 통째로 지운 경우에도
|
||||||
|
/// 같다고 볼 수 있고, 반대로 코드를 다른 줄로 옮긴 것은 다르다고 본다.
|
||||||
|
///
|
||||||
|
/// 큰 파일은 하지 않는다. 전체 비교에서 이미 걸러 둔 한도를 그대로 쓴다 -
|
||||||
|
/// 폴더 하나에 수천 개가 있을 때 이 판단만으로 몇 분이 더 들면 안 된다.
|
||||||
|
/// </summary>
|
||||||
|
private static bool OnlyCommentsDiffer(string leftPath, string rightPath, long size,
|
||||||
|
FolderCompareOptions options)
|
||||||
|
{
|
||||||
|
if (size > options.FullCompareLimitBytes) return false;
|
||||||
|
|
||||||
|
var profile = LanguageCatalog.ForPath(leftPath);
|
||||||
|
if (!profile.IsCode) return false;
|
||||||
|
|
||||||
|
// 확장자가 서로 다르면 같은 언어로 볼 근거가 없다.
|
||||||
|
if (!ReferenceEquals(profile, LanguageCatalog.ForPath(rightPath))) return false;
|
||||||
|
|
||||||
|
var left = CodeOnly(leftPath, profile);
|
||||||
|
if (left is null) return false;
|
||||||
|
|
||||||
|
var right = CodeOnly(rightPath, profile);
|
||||||
|
if (right is null) return false;
|
||||||
|
|
||||||
|
return string.Equals(left, right, StringComparison.Ordinal);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>주석과 공백을 걷어낸 글. 읽지 못하면 null.</summary>
|
||||||
|
private static string? CodeOnly(string path, LanguageProfile profile)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var text = TextFile.Read(path);
|
||||||
|
var builder = new System.Text.StringBuilder(text.Length);
|
||||||
|
var inBlockComment = false;
|
||||||
|
|
||||||
|
foreach (var line in text.Split('\n'))
|
||||||
|
{
|
||||||
|
var body = line.TrimEnd('\r');
|
||||||
|
var tokens = CodeTokenizer.Tokenize(body, profile, inBlockComment, out inBlockComment);
|
||||||
|
|
||||||
|
var isComment = new bool[body.Length];
|
||||||
|
foreach (var token in tokens)
|
||||||
|
{
|
||||||
|
if (token.Kind != CodeTokenKind.Comment && token.Kind != CodeTokenKind.XmlDoc) continue;
|
||||||
|
|
||||||
|
var end = Math.Min(body.Length, token.Start + token.Length);
|
||||||
|
for (var i = Math.Max(0, token.Start); i < end; i++) isComment[i] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var before = builder.Length;
|
||||||
|
for (var i = 0; i < body.Length; i++)
|
||||||
|
{
|
||||||
|
if (isComment[i] || char.IsWhiteSpace(body[i])) continue;
|
||||||
|
builder.Append(body[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 코드가 한 글자라도 있던 줄에만 줄 구분을 남긴다.
|
||||||
|
if (builder.Length > before) builder.Append('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.ToString();
|
||||||
|
}
|
||||||
|
catch (IOException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
catch (UnauthorizedAccessException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>내용을 앞에서부터 덩어리째 견준다. 다른 곳을 만나면 바로 멈춘다.</summary>
|
/// <summary>내용을 앞에서부터 덩어리째 견준다. 다른 곳을 만나면 바로 멈춘다.</summary>
|
||||||
private static bool SameContent(string leftPath, string rightPath)
|
private static bool SameContent(string leftPath, string rightPath)
|
||||||
|
|||||||
@ -17,6 +17,10 @@ namespace MergeHub.ViewModels
|
|||||||
public enum FolderFilter
|
public enum FolderFilter
|
||||||
{
|
{
|
||||||
Different,
|
Different,
|
||||||
|
|
||||||
|
/// <summary>주석만 다른 것은 빼고 <b>코드가 다른 것</b>만. 볼 것이 많을 때 쓴다.</summary>
|
||||||
|
CodeDifferent,
|
||||||
|
|
||||||
All,
|
All,
|
||||||
LeftOnly,
|
LeftOnly,
|
||||||
RightOnly,
|
RightOnly,
|
||||||
@ -64,6 +68,7 @@ namespace MergeHub.ViewModels
|
|||||||
FolderEntryStatus.LeftOnly => "왼쪽만",
|
FolderEntryStatus.LeftOnly => "왼쪽만",
|
||||||
FolderEntryStatus.RightOnly => "오른쪽만",
|
FolderEntryStatus.RightOnly => "오른쪽만",
|
||||||
FolderEntryStatus.Binary => "다름(이진)",
|
FolderEntryStatus.Binary => "다름(이진)",
|
||||||
|
FolderEntryStatus.CommentOnly => "주석만 다름",
|
||||||
_ => string.Empty
|
_ => string.Empty
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -167,12 +172,13 @@ namespace MergeHub.ViewModels
|
|||||||
|
|
||||||
public IReadOnlyList<FolderFilter> Filters { get; } = new[]
|
public IReadOnlyList<FolderFilter> Filters { get; } = new[]
|
||||||
{
|
{
|
||||||
FolderFilter.Different, FolderFilter.All,
|
FolderFilter.Different, FolderFilter.CodeDifferent, FolderFilter.All,
|
||||||
FolderFilter.LeftOnly, FolderFilter.RightOnly, FolderFilter.Same
|
FolderFilter.LeftOnly, FolderFilter.RightOnly, FolderFilter.Same
|
||||||
};
|
};
|
||||||
|
|
||||||
public static string FilterName(FolderFilter filter) => filter switch
|
public static string FilterName(FolderFilter filter) => filter switch
|
||||||
{
|
{
|
||||||
|
FolderFilter.CodeDifferent => "코드가 다른 것만",
|
||||||
FolderFilter.All => "전체",
|
FolderFilter.All => "전체",
|
||||||
FolderFilter.LeftOnly => "왼쪽에만",
|
FolderFilter.LeftOnly => "왼쪽에만",
|
||||||
FolderFilter.RightOnly => "오른쪽에만",
|
FolderFilter.RightOnly => "오른쪽에만",
|
||||||
@ -318,6 +324,10 @@ namespace MergeHub.ViewModels
|
|||||||
FolderFilter.LeftOnly => status == FolderEntryStatus.LeftOnly,
|
FolderFilter.LeftOnly => status == FolderEntryStatus.LeftOnly,
|
||||||
FolderFilter.RightOnly => status == FolderEntryStatus.RightOnly,
|
FolderFilter.RightOnly => status == FolderEntryStatus.RightOnly,
|
||||||
FolderFilter.Same => status == FolderEntryStatus.Same,
|
FolderFilter.Same => status == FolderEntryStatus.Same,
|
||||||
|
|
||||||
|
// 주석만 다른 것은 뺀다. 볼 것이 많을 때 "진짜 다른 것"만 남기려는 필터다.
|
||||||
|
FolderFilter.CodeDifferent =>
|
||||||
|
status != FolderEntryStatus.Same && status != FolderEntryStatus.CommentOnly,
|
||||||
_ => status != FolderEntryStatus.Same,
|
_ => status != FolderEntryStatus.Same,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.Windows.Data;
|
using System.Windows.Data;
|
||||||
using System.Windows.Media;
|
using System.Windows.Media;
|
||||||
@ -100,6 +100,7 @@ namespace MergeHub.Views.Controls
|
|||||||
{
|
{
|
||||||
Services.FolderEntryStatus.Different => LineHighlightBrushes.Changed,
|
Services.FolderEntryStatus.Different => LineHighlightBrushes.Changed,
|
||||||
Services.FolderEntryStatus.Binary => LineHighlightBrushes.Moved,
|
Services.FolderEntryStatus.Binary => LineHighlightBrushes.Moved,
|
||||||
|
Services.FolderEntryStatus.CommentOnly => LineHighlightBrushes.Ignored,
|
||||||
Services.FolderEntryStatus.LeftOnly => LineHighlightBrushes.Removed,
|
Services.FolderEntryStatus.LeftOnly => LineHighlightBrushes.Removed,
|
||||||
Services.FolderEntryStatus.RightOnly => LineHighlightBrushes.Added,
|
Services.FolderEntryStatus.RightOnly => LineHighlightBrushes.Added,
|
||||||
_ => LineHighlightBrushes.None
|
_ => LineHighlightBrushes.None
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
<UserControl x:Class="MergeHub.Views.FolderView"
|
<UserControl x:Class="MergeHub.Views.FolderView"
|
||||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:vm="clr-namespace:MergeHub.ViewModels"
|
xmlns:vm="clr-namespace:MergeHub.ViewModels"
|
||||||
|
xmlns:svc="clr-namespace:MergeHub.Services"
|
||||||
xmlns:ctl="clr-namespace:MergeHub.Views.Controls">
|
xmlns:ctl="clr-namespace:MergeHub.Views.Controls">
|
||||||
|
|
||||||
<UserControl.Resources>
|
<UserControl.Resources>
|
||||||
@ -80,6 +81,7 @@
|
|||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
|
<RowDefinition Height="Auto"/>
|
||||||
<RowDefinition Height="*"/>
|
<RowDefinition Height="*"/>
|
||||||
<RowDefinition Height="Auto"/>
|
<RowDefinition Height="Auto"/>
|
||||||
</Grid.RowDefinitions>
|
</Grid.RowDefinitions>
|
||||||
@ -158,8 +160,50 @@
|
|||||||
</WrapPanel>
|
</WrapPanel>
|
||||||
</Border>
|
</Border>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
④ 색 뜻풀이. 색만 칠해 두면 무슨 뜻인지 아무도 모른다 -
|
||||||
|
파일 비교 화면의 "색 구분" 줄과 같은 성격이다.
|
||||||
|
-->
|
||||||
|
<Border Grid.Row="2" Padding="8,4" BorderThickness="1,1,1,0" Margin="0,0,0,0"
|
||||||
|
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
|
||||||
|
<WrapPanel Orientation="Horizontal">
|
||||||
|
<TextBlock Text="색 구분" Style="{StaticResource Muted}" FontSize="11" Margin="0,0,10,0"
|
||||||
|
VerticalAlignment="Center"/>
|
||||||
|
<Border Width="12" Height="12" Margin="0,0,4,0" VerticalAlignment="Center"
|
||||||
|
Background="{Binding Source={x:Static svc:FolderEntryStatus.Different},
|
||||||
|
Converter={StaticResource StatusBrush}}"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"/>
|
||||||
|
<TextBlock Text="다름" FontSize="11" Margin="0,0,14,0" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
|
<Border Width="12" Height="12" Margin="0,0,4,0" VerticalAlignment="Center"
|
||||||
|
Background="{Binding Source={x:Static svc:FolderEntryStatus.CommentOnly},
|
||||||
|
Converter={StaticResource StatusBrush}}"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"/>
|
||||||
|
<TextBlock Text="주석만 다름" FontSize="11" Margin="0,0,14,0" VerticalAlignment="Center"
|
||||||
|
ToolTip="코드는 같고 주석·공백만 다른 파일입니다"/>
|
||||||
|
|
||||||
|
<Border Width="12" Height="12" Margin="0,0,4,0" VerticalAlignment="Center"
|
||||||
|
Background="{Binding Source={x:Static svc:FolderEntryStatus.LeftOnly},
|
||||||
|
Converter={StaticResource StatusBrush}}"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"/>
|
||||||
|
<TextBlock Text="왼쪽에만" FontSize="11" Margin="0,0,14,0" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
|
<Border Width="12" Height="12" Margin="0,0,4,0" VerticalAlignment="Center"
|
||||||
|
Background="{Binding Source={x:Static svc:FolderEntryStatus.RightOnly},
|
||||||
|
Converter={StaticResource StatusBrush}}"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"/>
|
||||||
|
<TextBlock Text="오른쪽에만" FontSize="11" Margin="0,0,14,0" VerticalAlignment="Center"/>
|
||||||
|
|
||||||
|
<Border Width="12" Height="12" Margin="0,0,4,0" VerticalAlignment="Center"
|
||||||
|
Background="{Binding Source={x:Static svc:FolderEntryStatus.Binary},
|
||||||
|
Converter={StaticResource StatusBrush}}"
|
||||||
|
BorderThickness="1" BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"/>
|
||||||
|
<TextBlock Text="다름(이진)" FontSize="11" VerticalAlignment="Center"/>
|
||||||
|
</WrapPanel>
|
||||||
|
</Border>
|
||||||
|
|
||||||
<!-- ③ 목록 머리글. 트리 항목의 칸 폭과 같은 값을 쓴다. -->
|
<!-- ③ 목록 머리글. 트리 항목의 칸 폭과 같은 값을 쓴다. -->
|
||||||
<Border Grid.Row="2" Padding="8,4" BorderThickness="1,1,1,0"
|
<Border Grid.Row="3" Padding="8,4" BorderThickness="1,1,1,0"
|
||||||
Background="{DynamicResource Ubisam.Brush.Sidebar.Background}"
|
Background="{DynamicResource Ubisam.Brush.Sidebar.Background}"
|
||||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
|
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
|
||||||
<Grid Margin="26,0,0,0">
|
<Grid Margin="26,0,0,0">
|
||||||
@ -182,7 +226,7 @@
|
|||||||
채움 칸(*)이 0 이 되고 줄 배경이 글자 끝에서 끊긴다. 칸 폭이 고정이라
|
채움 칸(*)이 0 이 되고 줄 배경이 글자 끝에서 끊긴다. 칸 폭이 고정이라
|
||||||
가로로 넘칠 일이 없으므로 꺼 두는 편이 맞다.
|
가로로 넘칠 일이 없으므로 꺼 두는 편이 맞다.
|
||||||
-->
|
-->
|
||||||
<TreeView Grid.Row="3" x:Name="Tree" BorderThickness="1"
|
<TreeView Grid.Row="4" x:Name="Tree" BorderThickness="1"
|
||||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"
|
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}"
|
||||||
ItemsSource="{Binding Nodes}"
|
ItemsSource="{Binding Nodes}"
|
||||||
ItemTemplate="{StaticResource NodeTemplate}"
|
ItemTemplate="{StaticResource NodeTemplate}"
|
||||||
@ -196,7 +240,7 @@
|
|||||||
VirtualizingPanel.VirtualizationMode="Recycling"/>
|
VirtualizingPanel.VirtualizationMode="Recycling"/>
|
||||||
|
|
||||||
<!-- ⑤ 요약 · 동작 -->
|
<!-- ⑤ 요약 · 동작 -->
|
||||||
<Border Grid.Row="4" Padding="8" BorderThickness="1,0,1,1" Margin="0,0,0,0"
|
<Border Grid.Row="5" Padding="8" BorderThickness="1,0,1,1" Margin="0,0,0,0"
|
||||||
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
|
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user