Compare commits

..

5 commits

Author SHA1 Message Date
leo
1c345df37d
ux: add some tooltips to checkboxes
Some checks failed
Continuous Integration / Build (push) Waiting to run
Continuous Integration / Prepare version string (push) Waiting to run
Continuous Integration / Package (push) Blocked by required conditions
Localization Check / localization-check (push) Has been cancelled
2024-12-17 11:24:59 +08:00
leo
c768b1750e
feature: use -p:DisableUpdateDetection=true to disable built-in update detection feature (#819) 2024-12-17 10:26:35 +08:00
leo
707a227aca
ux: make Welcome page responsive (#821) 2024-12-17 09:36:06 +08:00
leo
f418b72c64
feature: use [$workspace] $repo_name ($repo_path) as main window's title (#818) 2024-12-16 15:47:33 +08:00
leo
5425fa64fe
refactor: use another way to open tooltip of SHA after getting commit info (#810) 2024-12-16 13:29:46 +08:00
17 changed files with 247 additions and 164 deletions

View file

@ -25,6 +25,18 @@ namespace SourceGit
private Action<object> _action = null; private Action<object> _action = null;
} }
public static bool IsCheckForUpdateCommandVisible
{
get
{
#if DISABLE_UPDATE_DETECTION
return false;
#else
return true;
#endif
}
}
public static readonly Command OpenPreferenceCommand = new Command(_ => OpenDialog(new Views.Preference())); public static readonly Command OpenPreferenceCommand = new Command(_ => OpenDialog(new Views.Preference()));
public static readonly Command OpenHotkeysCommand = new Command(_ => OpenDialog(new Views.Hotkeys())); public static readonly Command OpenHotkeysCommand = new Command(_ => OpenDialog(new Views.Hotkeys()));
public static readonly Command OpenAppDataDirCommand = new Command(_ => Native.OS.OpenInFileManager(Native.OS.DataDir)); public static readonly Command OpenAppDataDirCommand = new Command(_ => Native.OS.OpenInFileManager(Native.OS.DataDir));

View file

@ -33,7 +33,7 @@
<NativeMenu> <NativeMenu>
<NativeMenuItem Header="{DynamicResource Text.About.Menu}" Command="{x:Static s:App.OpenAboutCommand}"/> <NativeMenuItem Header="{DynamicResource Text.About.Menu}" Command="{x:Static s:App.OpenAboutCommand}"/>
<NativeMenuItem Header="{DynamicResource Text.Hotkeys}" Command="{x:Static s:App.OpenHotkeysCommand}"/> <NativeMenuItem Header="{DynamicResource Text.Hotkeys}" Command="{x:Static s:App.OpenHotkeysCommand}"/>
<NativeMenuItem Header="{DynamicResource Text.SelfUpdate}" Command="{x:Static s:App.CheckForUpdateCommand}"/> <NativeMenuItem Header="{DynamicResource Text.SelfUpdate}" Command="{x:Static s:App.CheckForUpdateCommand}" IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"/>
<NativeMenuItemSeparator/> <NativeMenuItemSeparator/>
<NativeMenuItem Header="{DynamicResource Text.Preference}" Command="{x:Static s:App.OpenPreferenceCommand}" Gesture="⌘+,"/> <NativeMenuItem Header="{DynamicResource Text.Preference}" Command="{x:Static s:App.OpenPreferenceCommand}" Gesture="⌘+,"/>
<NativeMenuItem Header="{DynamicResource Text.OpenAppDataDir}" Command="{x:Static s:App.OpenAppDataDirCommand}"/> <NativeMenuItem Header="{DynamicResource Text.OpenAppDataDir}" Command="{x:Static s:App.OpenAppDataDirCommand}"/>

View file

@ -548,9 +548,11 @@ namespace SourceGit
_launcher = new ViewModels.Launcher(startupRepo); _launcher = new ViewModels.Launcher(startupRepo);
desktop.MainWindow = new Views.Launcher() { DataContext = _launcher }; desktop.MainWindow = new Views.Launcher() { DataContext = _launcher };
#if !DISABLE_UPDATE_DETECTION
var pref = ViewModels.Preference.Instance; var pref = ViewModels.Preference.Instance;
if (pref.ShouldCheck4UpdateOnStartup()) if (pref.ShouldCheck4UpdateOnStartup())
Check4Update(); Check4Update();
#endif
} }
private ViewModels.Launcher _launcher = null; private ViewModels.Launcher _launcher = null;

View file

@ -273,7 +273,7 @@
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">Fast-Forward (without checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">Fetch</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">Fetch all remotes</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">Enable '--force' option</x:String> <x:String x:Key="Text.Fetch.Force" xml:space="preserve">Override refs check</x:String>
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Fetch without tags</x:String> <x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">Fetch without tags</x:String>
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remote:</x:String> <x:String x:Key="Text.Fetch.Remote" xml:space="preserve">Remote:</x:String>
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch Remote Changes</x:String> <x:String x:Key="Text.Fetch.Title" xml:space="preserve">Fetch Remote Changes</x:String>

View file

@ -276,7 +276,7 @@
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward无需checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快进(fast-forward无需checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">拉取(fetch)</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">拉取所有的远程仓库</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">启用 --force 选项</x:String> <x:String x:Key="Text.Fetch.Force" xml:space="preserve">覆盖REF检查</x:String>
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">不拉取远程标签</x:String> <x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">不拉取远程标签</x:String>
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">远程仓库 </x:String> <x:String x:Key="Text.Fetch.Remote" xml:space="preserve">远程仓库 </x:String>
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">拉取远程仓库内容</x:String> <x:String x:Key="Text.Fetch.Title" xml:space="preserve">拉取远程仓库内容</x:String>

View file

@ -276,7 +276,7 @@
<x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward無需 checkout)</x:String> <x:String x:Key="Text.FastForwardWithoutCheck" xml:space="preserve">快進 (fast-forward無需 checkout)</x:String>
<x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String> <x:String x:Key="Text.Fetch" xml:space="preserve">提取 (fetch)</x:String>
<x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String> <x:String x:Key="Text.Fetch.AllRemotes" xml:space="preserve">提取所有的遠端存放庫</x:String>
<x:String x:Key="Text.Fetch.Force" xml:space="preserve">啟用 [--force] 選項</x:String> <x:String x:Key="Text.Fetch.Force" xml:space="preserve">覆寫 REFs 檢查</x:String>
<x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">不提取遠端標籤</x:String> <x:String x:Key="Text.Fetch.NoTags" xml:space="preserve">不提取遠端標籤</x:String>
<x:String x:Key="Text.Fetch.Remote" xml:space="preserve">遠端存放庫:</x:String> <x:String x:Key="Text.Fetch.Remote" xml:space="preserve">遠端存放庫:</x:String>
<x:String x:Key="Text.Fetch.Title" xml:space="preserve">提取遠端存放庫內容</x:String> <x:String x:Key="Text.Fetch.Title" xml:space="preserve">提取遠端存放庫內容</x:String>

View file

@ -26,6 +26,10 @@
<TrimMode>link</TrimMode> <TrimMode>link</TrimMode>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(DisableUpdateDetection)' == 'true'">
<DefineConstants>$(DefineConstants);DISABLE_UPDATE_DETECTION</DefineConstants>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<AvaloniaResource Include="App.ico" /> <AvaloniaResource Include="App.ico" />
<AvaloniaResource Include="Resources/Fonts/*" /> <AvaloniaResource Include="Resources/Fonts/*" />

View file

@ -11,6 +11,12 @@ namespace SourceGit.ViewModels
{ {
public class Launcher : ObservableObject public class Launcher : ObservableObject
{ {
public string Title
{
get => _title;
private set => SetProperty(ref _title, value);
}
public AvaloniaList<LauncherPage> Pages public AvaloniaList<LauncherPage> Pages
{ {
get; get;
@ -31,9 +37,10 @@ namespace SourceGit.ViewModels
if (SetProperty(ref _activePage, value)) if (SetProperty(ref _activePage, value))
{ {
PopupHost.Active = value; PopupHost.Active = value;
UpdateTitle();
if (!_ignoreIndexChange && value is { Data: Repository repo }) if (!_ignoreIndexChange && value is { Data: Repository repo })
ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(repo.FullPath); _activeWorkspace.ActiveIdx = _activeWorkspace.Repositories.IndexOf(repo.FullPath);
} }
} }
} }
@ -105,6 +112,9 @@ namespace SourceGit.ViewModels
} }
_ignoreIndexChange = false; _ignoreIndexChange = false;
if (string.IsNullOrEmpty(_title))
UpdateTitle();
} }
public void Quit(double width, double height) public void Quit(double width, double height)
@ -185,6 +195,7 @@ namespace SourceGit.ViewModels
last.Node = new RepositoryNode() { Id = Guid.NewGuid().ToString() }; last.Node = new RepositoryNode() { Id = Guid.NewGuid().ToString() };
last.Data = Welcome.Instance; last.Data = Welcome.Instance;
last.Popup = null; last.Popup = null;
UpdateTitle();
GC.Collect(); GC.Collect();
} }
@ -193,7 +204,6 @@ namespace SourceGit.ViewModels
App.Quit(0); App.Quit(0);
} }
_ignoreIndexChange = false;
return; return;
} }
@ -308,7 +318,10 @@ namespace SourceGit.ViewModels
page.Data = repo; page.Data = repo;
} }
ActivePage = page; if (page != _activePage)
ActivePage = page;
else
UpdateTitle();
ActiveWorkspace.Repositories.Clear(); ActiveWorkspace.Repositories.Clear();
foreach (var p in Pages) foreach (var p in Pages)
@ -530,8 +543,37 @@ namespace SourceGit.ViewModels
page.Data = null; page.Data = null;
} }
private void UpdateTitle()
{
if (_activeWorkspace == null)
return;
var workspace = _activeWorkspace.Name;
if (_activePage is { Data: Repository repo })
{
var node = _activePage.Node;
var name = node.Name;
var path = node.Id;
if (!OperatingSystem.IsWindows())
{
var home = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
var prefixLen = home.EndsWith('/') ? home.Length - 1 : home.Length;
if (path.StartsWith(home, StringComparison.Ordinal))
path = "~" + path.Substring(prefixLen);
}
Title = $"[{workspace}] {name} ({path})";
}
else
{
Title = $"[{workspace}] Repositories";
}
}
private Workspace _activeWorkspace = null; private Workspace _activeWorkspace = null;
private LauncherPage _activePage = null; private LauncherPage _activePage = null;
private bool _ignoreIndexChange = false; private bool _ignoreIndexChange = false;
private string _title = string.Empty;
} }
} }

View file

@ -54,7 +54,8 @@
<CheckBox Grid.Row="2" Grid.Column="1" <CheckBox Grid.Row="2" Grid.Column="1"
Content="{DynamicResource Text.Apply.IgnoreWS}" Content="{DynamicResource Text.Apply.IgnoreWS}"
IsChecked="{Binding IgnoreWhiteSpace, Mode=TwoWay}"/> IsChecked="{Binding IgnoreWhiteSpace, Mode=TwoWay}"
ToolTip.Tip="--ignore-whitespace"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -5,6 +5,7 @@ using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading;
namespace SourceGit.Views namespace SourceGit.Views
{ {
@ -124,7 +125,7 @@ namespace SourceGit.Views
e.Handled = true; e.Handled = true;
} }
private async void OnSHAPointerEntered(object sender, PointerEventArgs e) private void OnSHAPointerEntered(object sender, PointerEventArgs e)
{ {
if (DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha } ctl) if (DataContext is ViewModels.CommitDetail detail && sender is Control { DataContext: string sha } ctl)
{ {
@ -132,14 +133,22 @@ namespace SourceGit.Views
if (tooltip is Models.Commit commit && commit.SHA == sha) if (tooltip is Models.Commit commit && commit.SHA == sha)
return; return;
var c = await Task.Run(() => detail.GetParent(sha)); Task.Run(() =>
if (c != null && ctl.IsVisible && ctl.DataContext is string newSHA && newSHA == sha)
{ {
ToolTip.SetTip(ctl, c); var c = detail.GetParent(sha);
if (c == null) return;
if (ctl.IsPointerOver) Dispatcher.UIThread.Invoke(() =>
ToolTip.SetIsOpen(ctl, true); {
} if (ctl.IsEffectivelyVisible && ctl.DataContext is string newSHA && newSHA == sha)
{
ToolTip.SetTip(ctl, c);
if (ctl.IsPointerOver)
ToolTip.SetIsOpen(ctl, true);
}
});
});
} }
e.Handled = true; e.Handled = true;

View file

@ -34,15 +34,18 @@
<CheckBox Grid.Row="1" Grid.Column="1" <CheckBox Grid.Row="1" Grid.Column="1"
Content="{DynamicResource Text.Fetch.Force}" Content="{DynamicResource Text.Fetch.Force}"
IsChecked="{Binding Force, Mode=TwoWay}"/> IsChecked="{Binding Force, Mode=TwoWay}"
ToolTip.Tip="--force"/>
<CheckBox Grid.Row="2" Grid.Column="1" <CheckBox Grid.Row="2" Grid.Column="1"
Content="{DynamicResource Text.Fetch.AllRemotes}" Content="{DynamicResource Text.Fetch.AllRemotes}"
IsChecked="{Binding FetchAllRemotes, Mode=TwoWay}"/> IsChecked="{Binding FetchAllRemotes, Mode=TwoWay}"
ToolTip.Tip="--all"/>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="3" Grid.Column="1"
Content="{DynamicResource Text.Fetch.NoTags}" Content="{DynamicResource Text.Fetch.NoTags}"
IsChecked="{Binding NoTags, Mode=TwoWay}"/> IsChecked="{Binding NoTags, Mode=TwoWay}"
ToolTip.Tip="--no-tags"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -10,7 +10,7 @@
x:DataType="vm:Launcher" x:DataType="vm:Launcher"
x:Name="ThisControl" x:Name="ThisControl"
Icon="/App.ico" Icon="/App.ico"
Title="SourceGit" Title="{Binding Title}"
MinWidth="1024" MinHeight="600" MinWidth="1024" MinHeight="600"
WindowStartupLocation="CenterScreen"> WindowStartupLocation="CenterScreen">
<Grid> <Grid>
@ -51,12 +51,12 @@
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="-"/> <MenuItem Header="-"/>
<MenuItem Header="{DynamicResource Text.SelfUpdate}" Command="{x:Static s:App.CheckForUpdateCommand}"> <MenuItem Header="{DynamicResource Text.SelfUpdate}" Command="{x:Static s:App.CheckForUpdateCommand}" IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}">
<MenuItem.Icon> <MenuItem.Icon>
<Path Width="14" Height="14" Data="{StaticResource Icons.SoftwareUpdate}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.SoftwareUpdate}"/>
</MenuItem.Icon> </MenuItem.Icon>
</MenuItem> </MenuItem>
<MenuItem Header="-"/> <MenuItem Header="-" IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"/>
<MenuItem Header="{DynamicResource Text.About}" Command="{x:Static s:App.OpenAboutCommand}"> <MenuItem Header="{DynamicResource Text.About}" Command="{x:Static s:App.OpenAboutCommand}">
<MenuItem.Icon> <MenuItem.Icon>
<Path Width="14" Height="14" Data="{StaticResource Icons.Info}"/> <Path Width="14" Height="14" Data="{StaticResource Icons.Info}"/>

View file

@ -2,6 +2,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:s="using:SourceGit"
xmlns:m="using:SourceGit.Models" xmlns:m="using:SourceGit.Models"
xmlns:c="using:SourceGit.Converters" xmlns:c="using:SourceGit.Converters"
xmlns:vm="using:SourceGit.ViewModels" xmlns:vm="using:SourceGit.ViewModels"
@ -45,7 +46,7 @@
<TabItem.Header> <TabItem.Header>
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/> <TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
</TabItem.Header> </TabItem.Header>
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32,32" ColumnDefinitions="Auto,*"> <Grid Margin="8" RowDefinitions="32,32,32,32,32,32,Auto" ColumnDefinitions="Auto,*">
<TextBlock Grid.Row="0" Grid.Column="0" <TextBlock Grid.Row="0" Grid.Column="0"
Text="{DynamicResource Text.Preference.General.Locale}" Text="{DynamicResource Text.Preference.General.Locale}"
HorizontalAlignment="Right" HorizontalAlignment="Right"
@ -118,6 +119,7 @@
<CheckBox Grid.Row="6" Grid.Column="1" <CheckBox Grid.Row="6" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}" Content="{DynamicResource Text.Preference.General.Check4UpdatesOnStartup}"
IsVisible="{x:Static s:App.IsCheckForUpdateCommandVisible}"
IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/> IsChecked="{Binding Source={x:Static vm:Preference.Instance}, Path=Check4UpdatesOnStartup, Mode=TwoWay}"/>
</Grid> </Grid>
</TabItem> </TabItem>

View file

@ -99,11 +99,13 @@
<CheckBox Grid.Row="5" Grid.Column="1" <CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Pull.NoTags}" Content="{DynamicResource Text.Pull.NoTags}"
IsChecked="{Binding NoTags, Mode=TwoWay}"/> IsChecked="{Binding NoTags, Mode=TwoWay}"
ToolTip.Tip="--no-tags"/>
<CheckBox Grid.Row="6" Grid.Column="1" <CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Pull.UseRebase}" Content="{DynamicResource Text.Pull.UseRebase}"
IsChecked="{Binding UseRebase, Mode=TwoWay}"/> IsChecked="{Binding UseRebase, Mode=TwoWay}"
ToolTip.Tip="--rebase"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -83,21 +83,25 @@
Height="32" Height="32"
Content="{DynamicResource Text.Push.Tracking}" Content="{DynamicResource Text.Push.Tracking}"
IsChecked="{Binding Tracking, Mode=TwoWay}" IsChecked="{Binding Tracking, Mode=TwoWay}"
IsVisible="{Binding IsSetTrackOptionVisible}"/> IsVisible="{Binding IsSetTrackOptionVisible}"
ToolTip.Tip="-u"/>
<CheckBox Grid.Row="4" Grid.Column="1" <CheckBox Grid.Row="4" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Push.CheckSubmodules}" Content="{DynamicResource Text.Push.CheckSubmodules}"
IsChecked="{Binding CheckSubmodules, Mode=TwoWay}" IsChecked="{Binding CheckSubmodules, Mode=TwoWay}"
IsVisible="{Binding IsCheckSubmodulesVisible}"/> IsVisible="{Binding IsCheckSubmodulesVisible}"
ToolTip.Tip="--recurse-submodules=check"/>
<CheckBox Grid.Row="5" Grid.Column="1" <CheckBox Grid.Row="5" Grid.Column="1"
Content="{DynamicResource Text.Push.WithAllTags}" Content="{DynamicResource Text.Push.WithAllTags}"
IsChecked="{Binding PushAllTags, Mode=TwoWay}"/> IsChecked="{Binding PushAllTags, Mode=TwoWay}"
ToolTip.Tip="--tags"/>
<CheckBox Grid.Row="6" Grid.Column="1" <CheckBox Grid.Row="6" Grid.Column="1"
Content="{DynamicResource Text.Push.Force}" Content="{DynamicResource Text.Push.Force}"
IsChecked="{Binding ForcePush, Mode=TwoWay}"/> IsChecked="{Binding ForcePush, Mode=TwoWay}"
ToolTip.Tip="--force-with-lease"/>
</Grid> </Grid>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View file

@ -27,18 +27,21 @@
Height="32" Height="32"
Content="{DynamicResource Text.Stash.IncludeUntracked}" Content="{DynamicResource Text.Stash.IncludeUntracked}"
IsChecked="{Binding IncludeUntracked, Mode=TwoWay}" IsChecked="{Binding IncludeUntracked, Mode=TwoWay}"
IsVisible="{Binding !HasSelectedFiles}"/> IsVisible="{Binding !HasSelectedFiles}"
ToolTip.Tip="--include-untracked"/>
<CheckBox Grid.Row="2" Grid.Column="1" <CheckBox Grid.Row="2" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Stash.OnlyStagedChanges}" Content="{DynamicResource Text.Stash.OnlyStagedChanges}"
IsChecked="{Binding OnlyStaged, Mode=TwoWay}" IsChecked="{Binding OnlyStaged, Mode=TwoWay}"
IsVisible="{Binding !HasSelectedFiles}"/> IsVisible="{Binding !HasSelectedFiles}"
ToolTip.Tip="--staged"/>
<CheckBox Grid.Row="3" Grid.Column="1" <CheckBox Grid.Row="3" Grid.Column="1"
Height="32" Height="32"
Content="{DynamicResource Text.Stash.KeepIndex}" Content="{DynamicResource Text.Stash.KeepIndex}"
IsChecked="{Binding KeepIndex, Mode=TwoWay}"/> IsChecked="{Binding KeepIndex, Mode=TwoWay}"
ToolTip.Tip="--keep-index"/>
<TextBlock Grid.Row="4" Grid.Column="1" <TextBlock Grid.Row="4" Grid.Column="1"
Margin="0,4,0,0" Margin="0,4,0,0"

View file

@ -9,149 +9,148 @@
x:Class="SourceGit.Views.Welcome" x:Class="SourceGit.Views.Welcome"
x:DataType="vm:Welcome"> x:DataType="vm:Welcome">
<Grid RowDefinitions="*,36"> <Grid RowDefinitions="*,36">
<Grid Grid.Row="0" Margin="0,8" ColumnDefinitions="*,600,*"> <!-- Managed Repositories -->
<Grid Grid.Column="1" RowDefinitions="Auto,*"> <Grid Grid.Column="1" MinWidth="600" Margin="8" RowDefinitions="Auto,*" HorizontalAlignment="Center">
<!-- Search Box --> <!-- Search Box -->
<TextBox Grid.Row="0" <TextBox Grid.Row="0"
x:Name="SearchBox" x:Name="SearchBox"
Height="32" Height="32"
Padding="0" Padding="0"
CornerRadius="16" CornerRadius="16"
BorderBrush="{DynamicResource Brush.Border0}" BorderBrush="{DynamicResource Brush.Border0}"
BorderThickness="1" BorderThickness="1"
Background="{DynamicResource Brush.Contents}" Background="{DynamicResource Brush.Contents}"
Watermark="{DynamicResource Text.Welcome.Search}" Watermark="{DynamicResource Text.Welcome.Search}"
VerticalContentAlignment="Center" VerticalContentAlignment="Center"
Text="{Binding SearchFilter, Mode=TwoWay}" Text="{Binding SearchFilter, Mode=TwoWay}"
v:AutoFocusBehaviour.IsEnabled="True"> v:AutoFocusBehaviour.IsEnabled="True">
<TextBox.Styles> <TextBox.Styles>
<Style Selector="TextBox:pointerover /template/ Border#PART_BorderElement"> <Style Selector="TextBox:pointerover /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/> <Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
</Style> </Style>
<Style Selector="TextBox:focus /template/ Border#PART_BorderElement"> <Style Selector="TextBox:focus /template/ Border#PART_BorderElement">
<Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/> <Setter Property="BorderBrush" Value="{DynamicResource Brush.Border0}"/>
</Style> </Style>
</TextBox.Styles> </TextBox.Styles>
<TextBox.InnerLeftContent>
<Path Width="16" Height="16" Margin="6,0,3,0" Data="{StaticResource Icons.Search}" Fill="{DynamicResource Brush.FG2}"/>
</TextBox.InnerLeftContent>
<TextBox.InnerRightContent> <TextBox.InnerLeftContent>
<Button Classes="icon_button" IsVisible="{Binding SearchFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" Command="{Binding ClearSearchFilter}"> <Path Width="16" Height="16" Margin="6,0,3,0" Data="{StaticResource Icons.Search}" Fill="{DynamicResource Brush.FG2}"/>
<Path Width="16" Height="16" Margin="0,0,0,0" Data="{StaticResource Icons.Clear}" Fill="{DynamicResource Brush.FG1}"/> </TextBox.InnerLeftContent>
</Button>
</TextBox.InnerRightContent>
</TextBox>
<!-- Repository Tree --> <TextBox.InnerRightContent>
<v:RepositoryListBox Grid.Row="1" <Button Classes="icon_button" IsVisible="{Binding SearchFilter, Converter={x:Static StringConverters.IsNotNullOrEmpty}}" Command="{Binding ClearSearchFilter}">
x:Name="TreeContainer" <Path Width="16" Height="16" Margin="0,0,0,0" Data="{StaticResource Icons.Clear}" Fill="{DynamicResource Brush.FG1}"/>
Margin="0,8,8,0" </Button>
Focusable="True" </TextBox.InnerRightContent>
Background="Transparent" </TextBox>
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ItemsSource="{Binding Rows}"
SelectionMode="Single"
Loaded="SetupTreeViewDragAndDrop"
LostFocus="OnTreeViewLostFocus"
KeyDown="OnTreeViewKeyDown">
<ListBox.Styles>
<Style Selector="ListBox">
<Setter Property="FocusAdorner">
<FocusAdornerTemplate>
<Border Background="Transparent" BorderThickness="0"/>
</FocusAdornerTemplate>
</Setter>
</Style>
<Style Selector="ListBoxItem" x:DataType="vm:RepositoryNode">
<Setter Property="Margin" Value="0"/>
<Setter Property="Padding" Value="0"/>
<Setter Property="Height" Value="30"/>
<Setter Property="CornerRadius" Value="4"/>
<Setter Property="FocusAdorner">
<FocusAdornerTemplate>
<Border Background="Transparent" BorderThickness="0"/>
</FocusAdornerTemplate>
</Setter>
</Style>
</ListBox.Styles>
<ListBox.ItemsPanel> <!-- Repository Tree -->
<ItemsPanelTemplate> <v:RepositoryListBox Grid.Row="1"
<VirtualizingStackPanel Orientation="Vertical"/> x:Name="TreeContainer"
</ItemsPanelTemplate> Margin="0,8,8,0"
</ListBox.ItemsPanel> Focusable="True"
Background="Transparent"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollBarVisibility="Auto"
ItemsSource="{Binding Rows}"
SelectionMode="Single"
Loaded="SetupTreeViewDragAndDrop"
LostFocus="OnTreeViewLostFocus"
KeyDown="OnTreeViewKeyDown">
<ListBox.Styles>
<Style Selector="ListBox">
<Setter Property="FocusAdorner">
<FocusAdornerTemplate>
<Border Background="Transparent" BorderThickness="0"/>
</FocusAdornerTemplate>
</Setter>
</Style>
<ListBox.ContextMenu> <Style Selector="ListBoxItem" x:DataType="vm:RepositoryNode">
<ContextMenu> <Setter Property="Margin" Value="0"/>
<MenuItem Header="{DynamicResource Text.Welcome.AddRootFolder}" Command="{Binding AddRootNode}"> <Setter Property="Padding" Value="0"/>
<MenuItem.Icon> <Setter Property="Height" Value="30"/>
<Path Width="12" Height="12" Data="{DynamicResource Icons.Folder.Add}"/> <Setter Property="CornerRadius" Value="4"/>
</MenuItem.Icon> <Setter Property="FocusAdorner">
</MenuItem> <FocusAdornerTemplate>
</ContextMenu> <Border Background="Transparent" BorderThickness="0"/>
</ListBox.ContextMenu> </FocusAdornerTemplate>
</Setter>
</Style>
</ListBox.Styles>
<ListBox.ItemTemplate> <ListBox.ItemsPanel>
<DataTemplate DataType="vm:RepositoryNode"> <ItemsPanelTemplate>
<Grid Background="Transparent" <VirtualizingStackPanel Orientation="Vertical"/>
Height="30" </ItemsPanelTemplate>
ColumnDefinitions="16,18,Auto,*" </ListBox.ItemsPanel>
Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}"
Loaded="SetupTreeNodeDragAndDrop"
ContextRequested="OnTreeNodeContextRequested"
PointerPressed="OnPointerPressedTreeNode"
PointerMoved="OnPointerMovedOverTreeNode"
PointerReleased="OnPointerReleasedOnTreeNode"
DoubleTapped="OnDoubleTappedTreeNode"
ClipToBounds="True">
<v:RepositoryTreeNodeToggleButton Grid.Column="0"
Classes="tree_expander"
Focusable="False"
HorizontalAlignment="Center"
IsChecked="{Binding IsExpanded, Mode=OneWay}"
IsVisible="{Binding !IsRepository}"/>
<Path Grid.Column="1"
Width="14" Height="14"
Fill="{Binding Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
HorizontalAlignment="Center"
Data="{StaticResource Icons.Bookmark}"
IsVisible="{Binding IsRepository}"/>
<ToggleButton Grid.Column="1" <ListBox.ContextMenu>
Classes="folder" <ContextMenu>
Focusable="False" <MenuItem Header="{DynamicResource Text.Welcome.AddRootFolder}" Command="{Binding AddRootNode}">
Width="14" Height="14" <MenuItem.Icon>
HorizontalAlignment="Left" <Path Width="12" Height="12" Data="{DynamicResource Icons.Folder.Add}"/>
Foreground="{DynamicResource Brush.FG1}" </MenuItem.Icon>
IsChecked="{Binding IsExpanded}" </MenuItem>
IsVisible="{Binding !IsRepository}"/> </ContextMenu>
</ListBox.ContextMenu>
<StackPanel Grid.Column="2" Orientation="Horizontal"> <ListBox.ItemTemplate>
<TextBlock Classes="primary" VerticalAlignment="Center" Text="{Binding Name}"/> <DataTemplate DataType="vm:RepositoryNode">
<Path Margin="2,0,0,0" <Grid Background="Transparent"
Width="12" Height="12" Height="30"
Data="{StaticResource Icons.Error}" ColumnDefinitions="16,18,Auto,*"
Fill="Orange" Margin="{Binding Depth, Converter={x:Static c:IntConverters.ToTreeMargin}}"
IsVisible="{Binding IsInvalid}"/> Loaded="SetupTreeNodeDragAndDrop"
</StackPanel> ContextRequested="OnTreeNodeContextRequested"
PointerPressed="OnPointerPressedTreeNode"
<TextBlock Grid.Column="3" PointerMoved="OnPointerMovedOverTreeNode"
Classes="primary" PointerReleased="OnPointerReleasedOnTreeNode"
Margin="8,0" DoubleTapped="OnDoubleTappedTreeNode"
HorizontalAlignment="Right" VerticalAlignment="Center" ClipToBounds="True">
<v:RepositoryTreeNodeToggleButton Grid.Column="0"
Classes="tree_expander"
Focusable="False"
HorizontalAlignment="Center"
IsChecked="{Binding IsExpanded, Mode=OneWay}"
IsVisible="{Binding !IsRepository}"/>
<Path Grid.Column="1"
Width="14" Height="14"
Fill="{Binding Bookmark, Converter={x:Static c:IntConverters.ToBookmarkBrush}}"
HorizontalAlignment="Center"
Data="{StaticResource Icons.Bookmark}"
IsVisible="{Binding IsRepository}"/>
<ToggleButton Grid.Column="1"
Classes="folder"
Focusable="False"
Width="14" Height="14"
HorizontalAlignment="Left"
Foreground="{DynamicResource Brush.FG1}"
IsChecked="{Binding IsExpanded}"
IsVisible="{Binding !IsRepository}"/>
<StackPanel Grid.Column="2" Orientation="Horizontal">
<TextBlock Classes="primary" VerticalAlignment="Center" Text="{Binding Name}"/>
<Path Margin="2,0,0,0"
Width="12" Height="12"
Data="{StaticResource Icons.Error}"
Fill="Orange"
IsVisible="{Binding IsInvalid}"/>
</StackPanel>
<Border Grid.Column="3" Margin="8,0" VerticalAlignment="Center" ClipToBounds="True">
<TextBlock Classes="primary"
HorizontalAlignment="Right"
Foreground="{DynamicResource Brush.FG2}" Foreground="{DynamicResource Brush.FG2}"
Text="{Binding Id, Converter={x:Static c:PathConverters.RelativeToHome}}" Text="{Binding Id, Converter={x:Static c:PathConverters.RelativeToHome}}"
IsVisible="{Binding IsRepository}"/> IsVisible="{Binding IsRepository}"/>
</Grid> </Border>
</DataTemplate> </Grid>
</ListBox.ItemTemplate> </DataTemplate>
</v:RepositoryListBox> </ListBox.ItemTemplate>
</Grid> </v:RepositoryListBox>
</Grid> </Grid>
<!-- Tips --> <!-- Tips -->