ksj09406 05c74fcb0e C 묶음: 코드 툴팁 · 글자 잘림 · 폴더 복사 확인 창
C-1. 코드 위에 마우스를 올리면 그 줄 내용이 그대로 툴팁으로 다시 떴다. 글이
이미 보이는데 같은 글이 상자로 겹쳐 뜨니 가리기만 한다. 원본 세 칸에서 뺐다.
버튼과 상태 아이콘 툴팁은 그대로 둔다. 그쪽은 화면에 없는 정보를 알려 준다.

C-2. Git 탭 목록의 글자가 ... 없이 중간에서 뚝 끊겼다. 줄임표 설정은 이미
있었는데 듣지 않았다. 목록의 가로 스크롤이 켜져 있으면 항목이 제 글 길이만큼
넓게 잡히고, 그러면 잘릴 일이 없으니 줄임표도 나오지 않는다. 가로 스크롤을
끄면 항목이 칸 너비에 갇히고 그때 비로소 줄임표가 나온다. 커밋/변경 파일/
브랜치/충돌/태그/서브모듈 여섯 목록에 같이 걸었다.

"작업 취소" 버튼과 Git 탭 입력 칸이 잘리는 것은 재현하지 못했다. 2560x1600 과
1920x1080 에서 배율 100%/120% 로 여섯 하위 탭을 모두 봤지만 멀쩡했다.

C-3. 폴더 복사 확인 창을 윈도우 기본 대화상자에서 플랫폼 것으로 바꿨다.
글꼴도 색도 배치도 혼자 달라 "이 프로그램이 묻는 것"으로 읽히지 않았다.
묻는 것 자체는 없애지 않았다. 복사/삭제는 되돌릴 수 없다.

확인: 코드 위 3초 머물러도 툴팁 없음. 이력 목록이 ... 로 줄어듦. 폴더 복사
확인 창과 완료 토스트가 프로그램의 다른 알림과 같은 모양.
테스트 399건 그대로 통과.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 13:24:03 +09:00

523 lines
34 KiB
XML

<UserControl x:Class="MergeHub.Views.GitView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MergeHub.Views"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/MergeHub;component/Views/Controls/AppStyles.xaml"/>
</ResourceDictionary.MergedDictionaries>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
<Style TargetType="Button" BasedOn="{StaticResource {x:Type Button}}">
<Setter Property="Margin" Value="2"/>
<Setter Property="MinWidth" Value="76"/>
</Style>
<Style x:Key="Muted" TargetType="TextBlock">
<Setter Property="Foreground" Value="{DynamicResource Ubisam.Brush.Muted}"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
<Style x:Key="GroupTitle" TargetType="TextBlock">
<Setter Property="FontWeight" Value="Bold"/>
<Setter Property="Foreground" Value="{DynamicResource Ubisam.Brush.Accent}"/>
<Setter Property="Margin" Value="0,0,0,4"/>
</Style>
<Style x:Key="Code" TargetType="TextBox" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="FontFamily" Value="Consolas"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="IsReadOnly" Value="True"/>
<Setter Property="AcceptsReturn" Value="True"/>
<Setter Property="TextWrapping" Value="NoWrap"/>
<Setter Property="VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
</Style>
</ResourceDictionary>
</UserControl.Resources>
<Grid Margin="8" TextElement.Foreground="{DynamicResource Ubisam.Brush.ContentForeground}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="120"/>
</Grid.RowDefinitions>
<!-- ===== 저장소 연결 ===== -->
<Border Grid.Row="0" Padding="10,8" Margin="0,0,0,6"
Background="{DynamicResource Ubisam.Brush.Input.Background}"
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}" BorderThickness="1">
<StackPanel>
<TextBlock Text="저장소 연결" Style="{StaticResource GroupTitle}"/>
<Grid Margin="0,0,0,4">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="로컬 경로" Style="{StaticResource Muted}" Margin="0,0,6,0"/>
<TextBox Grid.Column="1" Text="{Binding Workspace.RepositoryPath, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="2" Content="폴더..." Click="BrowseFolder_Click"/>
<Button Grid.Column="3" Content="열기" Command="{Binding OpenCommand}"/>
</Grid>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="원격 URL" Style="{StaticResource Muted}" Margin="0,0,6,0"/>
<TextBox Grid.Column="1" Text="{Binding Workspace.RemoteUrl, UpdateSourceTrigger=PropertyChanged}"
ToolTip="예) https://gitea.내부도메인/team/repo.git"/>
<TextBlock Grid.Column="2" Text="이름" Style="{StaticResource Muted}" Margin="8,0,6,0"/>
<TextBox Grid.Column="3" Text="{Binding Workspace.RemoteName, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="4" Content="클론" Command="{Binding CloneCommand}"/>
<Button Grid.Column="5" Content="원격 추가" Command="{Binding AddRemoteCommand}"
ToolTip="다른 저장소를 원격으로 등록하고 바로 fetch"/>
<Button Grid.Column="6" Content="원격 삭제" Command="{Binding RemoveRemoteCommand}"/>
</Grid>
<Grid Margin="0,4,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="Gitea 계정" Style="{StaticResource Muted}" Margin="0,0,6,0"/>
<TextBox Grid.Column="1" Text="{Binding Workspace.UserName, UpdateSourceTrigger=PropertyChanged}"/>
<TextBlock Grid.Column="2" Text="토큰/암호" Style="{StaticResource Muted}" Margin="8,0,6,0"/>
<PasswordBox Grid.Column="3" PasswordChanged="Password_Changed"
Background="{DynamicResource Ubisam.Brush.Input.Background}"
Foreground="{DynamicResource Ubisam.Brush.ContentForeground}"
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}" Padding="4,3"/>
<StackPanel Grid.Column="4" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Fetch" Command="{Binding FetchCommand}"/>
<Button Content="Pull" Command="{Binding PullCommand}"/>
<Button Content="Push" Command="{Binding PushCommand}"/>
<Button Content="새로고침" Command="{Binding RefreshCommand}"/>
</StackPanel>
</Grid>
</StackPanel>
</Border>
<!-- ===== 상태 배지 ===== -->
<!-- ItemHeight 를 24 로 묶어 두면 그보다 큰 버튼이 잘린다("mergetool 등록"이 반쯤 잘려 보였다).
줄 높이는 내용이 정하게 두고, 글자만 세로 가운데로 맞춘다. -->
<WrapPanel Grid.Row="1" Margin="2,0,0,6">
<TextBlock Text="HEAD" Style="{StaticResource Muted}" Margin="0,0,6,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Workspace.CurrentBranch}" FontWeight="Bold" Margin="0,0,6,0"
Foreground="{DynamicResource Ubisam.Brush.Accent}" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Workspace.HeadSha}" FontFamily="Consolas" Margin="0,0,16,0"
Foreground="{DynamicResource Ubisam.Brush.Warning}" VerticalAlignment="Center"/>
<TextBlock Text="Working Tree" Style="{StaticResource Muted}" Margin="0,0,6,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Workspace.WorkingTreeSummary}" Margin="0,0,16,0" VerticalAlignment="Center"/>
<TextBlock Text="{Binding Workspace.PendingOperationText}" FontWeight="Bold" Margin="0,0,16,0"
Foreground="{DynamicResource Ubisam.Brush.Danger}" VerticalAlignment="Center"/>
<Button Content="작업 취소" Command="{Binding AbortCommand}"
ToolTip="진행 중인 merge / cherry-pick / revert / rebase 를 취소"/>
<Button Content="mergetool 등록" Command="{Binding RegisterMergeToolCommand}" MinWidth="110"
ToolTip="git config 의 merge.tool 로 이 프로그램을 등록 (전역 .gitconfig 수정)"/>
<!-- HKCU 에만 쓰므로 관리자 권한이 필요 없다. 버튼 이름이 지금 상태를 그대로 말한다. -->
<Button Content="{Binding ShellIntegrationLabel}" Command="{Binding ToggleShellIntegrationCommand}"
MinWidth="140"
ToolTip="탐색기에서 파일·폴더를 고르고 [우클릭 → 보내기] 로 이 프로그램에 넘길 수 있게 합니다. 여러 개를 한 번에 골라도 됩니다 (관리자 권한 필요 없음)"/>
</WrapPanel>
<!-- ===== 작업 영역 ===== -->
<TabControl Grid.Row="2" Background="Transparent"
BorderBrush="{DynamicResource Ubisam.Brush.Input.Border}">
<!-- 브랜치 / 병합 -->
<TabItem Header="브랜치 · 병합">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="260"/>
</Grid.ColumnDefinitions>
<ListBox Grid.Column="0" ItemsSource="{Binding Workspace.Branches}"
SelectedItem="{Binding SelectedBranch}" HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid Margin="0,2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="★ " FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Accent}"
Visibility="{Binding IsCurrentHead, Converter={StaticResource BoolToVis}}"/>
<StackPanel Grid.Column="1">
<TextBlock Text="{Binding FriendlyName}"/>
<TextBlock Text="{Binding TipMessageShort}" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Muted}"
TextTrimming="CharacterEllipsis"/>
</StackPanel>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<TextBlock Text="↑" FontSize="11" Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
<TextBlock Text="{Binding AheadBy}" FontSize="11" Margin="0,0,6,0"
Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
<TextBlock Text="↓" FontSize="11" Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
<TextBlock Text="{Binding BehindBy}" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
</StackPanel>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Column="1" Margin="8,0,0,0">
<TextBlock Text="선택 브랜치" Style="{StaticResource GroupTitle}"/>
<Button Content="체크아웃" Command="{Binding CheckoutCommand}" HorizontalAlignment="Stretch"/>
<Button Content="Merge → 현재 브랜치로" Command="{Binding MergeCommand}"
HorizontalAlignment="Stretch" MinHeight="32"
Style="{StaticResource FilledButton}"
Background="{DynamicResource Ubisam.Brush.Danger.Fill}"
Foreground="{DynamicResource Ubisam.Brush.Accent.OnFill}"/>
<Button Content="브랜치 삭제" Command="{Binding DeleteBranchCommand}" HorizontalAlignment="Stretch"/>
<TextBlock Text="새 브랜치" Style="{StaticResource GroupTitle}" Margin="0,12,0,4"/>
<TextBox Text="{Binding NewBranchName, UpdateSourceTrigger=PropertyChanged}"
ToolTip="선택 커밋에서 분기. 선택이 없으면 HEAD"/>
<Button Content="생성 + 체크아웃" Command="{Binding CreateBranchCommand}"
HorizontalAlignment="Stretch" Margin="2,4,2,0"/>
<TextBlock Text="rebase" Style="{StaticResource GroupTitle}" Margin="0,12,0,4"/>
<Button Content="선택 브랜치 위로 rebase" Command="{Binding RebaseCommand}" HorizontalAlignment="Stretch"/>
<UniformGrid Columns="2">
<Button Content="계속" Command="{Binding RebaseContinueCommand}"/>
<Button Content="중단" Command="{Binding RebaseAbortCommand}"/>
</UniformGrid>
</StackPanel>
</Grid>
</TabItem>
<!-- 충돌 -->
<TabItem Header="충돌">
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Style="{StaticResource Muted}" Margin="0,0,0,6" TextWrapping="Wrap"
Text="파일 전체를 한쪽으로 채택하려면 아래 버튼을 쓰고, 줄 단위로 고르려면 홈 탭의 3분할 화면에서 처리하세요."/>
<ListBox Grid.Row="1" ItemsSource="{Binding Workspace.Conflicts}"
SelectedItem="{Binding SelectedConflict}" HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path}" TextTrimming="CharacterEllipsis"/>
<TextBlock Text=" (binary)" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Danger}"
Visibility="{Binding IsBinary, Converter={StaticResource BoolToVis}}"/>
<TextBlock Text=" · 상대쪽 삭제" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Warning}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Setter Property="Visibility" Value="Collapsed"/>
<Style.Triggers>
<DataTrigger Binding="{Binding HasTheirs}" Value="False">
<Setter Property="Visibility" Value="Visible"/>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<WrapPanel Grid.Row="2" Margin="0,6,0,0">
<Button Content="Accept Mine" Command="{Binding AcceptMineCommand}" MinWidth="100" Style="{StaticResource FilledButton}"
Background="{DynamicResource Ubisam.Brush.Success}"
Foreground="{DynamicResource Ubisam.Brush.Accent.OnFill}"/>
<Button Content="Accept Theirs" Command="{Binding AcceptTheirsCommand}" MinWidth="100" Style="{StaticResource FilledButton}"
Background="{DynamicResource Ubisam.Brush.Accent.Fill}"
Foreground="{DynamicResource Ubisam.Brush.Accent.OnFill}"/>
<Button Content="Accept Both" Command="{Binding AcceptBothCommand}" MinWidth="100" Style="{StaticResource FilledButton}"
Background="{DynamicResource Ubisam.Brush.Warning}"
Foreground="{DynamicResource Ubisam.Brush.Accent.OnFill}"/>
<Button Content="병합 커밋" Command="{Binding CommitMergeCommand}" MinWidth="100"/>
</WrapPanel>
</Grid>
</TabItem>
<!-- 변경 / 커밋 -->
<TabItem Header="변경 · 커밋">
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" ItemsSource="{Binding Workspace.StatusFiles}"
SelectedItem="{Binding SelectedStatusFile}" HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding StagedState}" Width="80" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Success}"/>
<TextBlock Text="{Binding WorkingDirState}" Width="80" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Warning}"/>
<TextBlock Text="{Binding Path}" FontSize="11" TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="1" Margin="0,6,0,0">
<WrapPanel>
<Button Content="스테이징" Command="{Binding StageSelectedCommand}"/>
<Button Content="언스테이징" Command="{Binding UnstageSelectedCommand}"/>
<Button Content="변경 취소" Command="{Binding RestoreSelectedCommand}"
ToolTip="git checkout -- &lt;file&gt;"/>
<Button Content="전체 스테이징" Command="{Binding StageAllCommand}" MinWidth="96"/>
<Button Content="stash 저장" Command="{Binding StashSaveCommand}"/>
<Button Content="blame" Command="{Binding BlameSelectedFileCommand}"
ToolTip="고른 파일을 'Blame' 탭으로 보냅니다"/>
</WrapPanel>
<!-- 치워 둔 작업(stash). 목록이 없으면 맨 위 것만 꺼낼 수 있어
"어제 치워 둔 것"에 손이 닿지 않는다. -->
<Grid Margin="0,6,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="stash" Style="{StaticResource Muted}"
VerticalAlignment="Center" Margin="0,0,6,0"/>
<ComboBox Grid.Column="1" ItemsSource="{Binding Workspace.Stashes}"
SelectedItem="{Binding SelectedStash}"
ToolTip="치워 둔 작업 목록. 새 것이 위에 옵니다">
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Index}" FontFamily="Consolas" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Warning}"
Margin="0,0,8,0"/>
<TextBlock Text="{Binding Message}" FontSize="11"
TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
<Button Grid.Column="2" Content="적용" Command="{Binding StashApplySelectedCommand}"
ToolTip="고른 stash 를 꺼내 적용합니다 (목록에서 사라집니다)"/>
<Button Grid.Column="3" Content="삭제" Command="{Binding StashDropSelectedCommand}"
ToolTip="고른 stash 를 버립니다"/>
</Grid>
<Grid Margin="0,6,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="커밋 메시지" Style="{StaticResource Muted}" Margin="0,0,6,0"/>
<TextBox Grid.Column="1" Text="{Binding CommitMessage, UpdateSourceTrigger=PropertyChanged}"/>
<Button Grid.Column="2" Content="마지막 메시지" Command="{Binding LoadLastMessageCommand}"
ToolTip="고쳐 쓰려는 메시지를 처음부터 다시 치지 않게, 마지막 커밋의 메시지를 가져옵니다"/>
<Button Grid.Column="3" Content="커밋" Command="{Binding CommitCommand}"/>
<Button Grid.Column="4" Content="커밋 수정" Command="{Binding AmendCommand}"
ToolTip="마지막 커밋을 고쳐 씁니다 (git commit --amend). 푸시하기 전에만 쓰세요"/>
</Grid>
</StackPanel>
</Grid>
</TabItem>
<!-- 이력 -->
<TabItem Header="이력">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="300"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<ListBox Grid.Row="0" Grid.Column="0" ItemsSource="{Binding Workspace.Commits}"
SelectedItem="{Binding SelectedCommit}" HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Margin="0,2">
<TextBlock Text="{Binding MessageShort}" TextTrimming="CharacterEllipsis"/>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding ShortSha}" FontFamily="Consolas" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Warning}"/>
<TextBlock Text=" · " FontSize="11" Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
<TextBlock Text="{Binding AuthorName}" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
</StackPanel>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox Grid.Row="0" Grid.Column="1" Style="{StaticResource Code}" Margin="6,0,0,0"
Text="{Binding DiffText, Mode=OneWay}"/>
<WrapPanel Grid.Row="1" Grid.ColumnSpan="2" Margin="0,6,0,0">
<TextBlock Text="선택 커밋 →" Style="{StaticResource Muted}" Margin="0,0,6,0"/>
<Button Content="Revert" Command="{Binding RevertCommand}"
ToolTip="선택 커밋의 변경을 되돌리는 커밋 생성"/>
<Button Content="Cherry-pick" Command="{Binding CherryPickCommand}" MinWidth="90"
ToolTip="선택 커밋만 현재 브랜치로 가져오기"/>
<ComboBox ItemsSource="{Binding ResetKinds}" SelectedItem="{Binding SelectedResetKind}"
Width="80" Margin="8,2,2,2"/>
<Button Content="Reset" Command="{Binding ResetCommand}"
ToolTip="선택 커밋으로 HEAD 이동"/>
<!-- 두 커밋 "사이"를 보려면 시작점을 따로 잡아야 한다.
잡지 않으면 지금까지처럼 부모와 견준다. -->
<Border Width="1" Margin="10,2" Background="{DynamicResource Ubisam.Brush.Input.Border}"/>
<TextBlock Text="{Binding DiffRangeText}" Style="{StaticResource Muted}"
VerticalAlignment="Center" Margin="0,0,6,0"
ToolTip="지금 무엇과 무엇을 견주고 있는지"/>
<Button Content="여기부터" Command="{Binding SetDiffFromCommand}"
ToolTip="고른 커밋을 비교의 시작점으로 잡습니다"/>
<Button Content="해제" Command="{Binding ClearDiffFromCommand}"
ToolTip="다시 '부모와 비교'로 돌아갑니다"/>
<Button Content="변경분 추출" Command="{Binding ExportChangesCommand}" MinWidth="96"
ToolTip="이 범위에서 바뀐 파일만 골라 폴더로 뽑습니다"/>
</WrapPanel>
</Grid>
</TabItem>
<!--
Blame - 줄마다 "누가 언제 이 줄을 만들었나".
머지 중에 "이 줄 왜 이렇게 됐지"를 묻게 되는데, 이력을 뒤지는 것보다 빠르다.
-->
<TabItem Header="Blame">
<Grid Margin="6">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0" Margin="0,0,0,6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Column="0" Text="파일 경로" Style="{StaticResource Muted}"
VerticalAlignment="Center" Margin="0,0,6,0"/>
<TextBox Grid.Column="1" Text="{Binding BlamePath, UpdateSourceTrigger=PropertyChanged}"
ToolTip="저장소 안의 상대 경로 (예: src/MergeHub/AppSetup.cs). '변경 · 커밋' 탭에서 파일을 고르고 [blame] 을 누르면 자동으로 채워집니다"/>
<Button Grid.Column="2" Content="실행" Command="{Binding BlameCommand}"
ToolTip="이력에서 커밋을 골라 두면 그 시점 기준으로 봅니다"/>
</Grid>
<TextBox Grid.Row="1" Style="{StaticResource Code}"
Text="{Binding BlameText, Mode=OneWay}"/>
</Grid>
</TabItem>
<!-- 태그 / 서브모듈 -->
<TabItem Header="태그 · 서브모듈">
<Grid Margin="6">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="태그" Style="{StaticResource GroupTitle}"/>
<ListBox Grid.Row="1" Grid.Column="0" Margin="0,0,6,0"
ItemsSource="{Binding Workspace.Tags}" SelectedItem="{Binding SelectedTag}" HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Name}" FontWeight="Bold"/>
<TextBlock Text=" · " Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
<TextBlock Text="{Binding Message}" FontSize="11"
Foreground="{DynamicResource Ubisam.Brush.Muted}"
TextTrimming="CharacterEllipsis"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Row="2" Grid.Column="0" Margin="0,6,6,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="110"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" Text="{Binding TagName, UpdateSourceTrigger=PropertyChanged}"
ToolTip="예) v1.0.0"/>
<TextBox Grid.Column="1" Margin="4,0,0,0"
Text="{Binding TagMessage, UpdateSourceTrigger=PropertyChanged}"
ToolTip="메시지를 넣으면 annotated tag"/>
<Button Grid.Column="2" Content="생성" Command="{Binding CreateTagCommand}"/>
</Grid>
<Button Content="선택 태그 삭제" Command="{Binding DeleteTagCommand}" HorizontalAlignment="Left" Margin="2,4,2,0"/>
</StackPanel>
<TextBlock Grid.Row="0" Grid.Column="1" Text="서브모듈" Style="{StaticResource GroupTitle}"/>
<ListBox Grid.Row="1" Grid.Column="1" ItemsSource="{Binding Workspace.Submodules}"
HorizontalContentAlignment="Stretch"
ScrollViewer.HorizontalScrollBarVisibility="Disabled">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Path}" TextTrimming="CharacterEllipsis"/>
<TextBlock Text="{Binding Status}" FontSize="11" TextTrimming="CharacterEllipsis"
Foreground="{DynamicResource Ubisam.Brush.Muted}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<Button Grid.Row="2" Grid.Column="1" Content="서브모듈 업데이트 (--init)"
Command="{Binding UpdateSubmodulesCommand}" HorizontalAlignment="Left" Margin="2,6,2,0"
MinWidth="180"/>
</Grid>
</TabItem>
</TabControl>
<!-- ===== 로그 ===== -->
<TextBox Grid.Row="3" Style="{StaticResource Code}" Margin="0,6,0,0"
Text="{Binding Workspace.Log, Mode=OneWay}" TextChanged="Log_TextChanged"/>
</Grid>
</UserControl>