code_style: general cleanup

This commit is contained in:
Nathan Baulch 2025-06-13 07:14:08 +10:00
parent ae46728bbc
commit dc74ebb98a
48 changed files with 123 additions and 240 deletions

View file

@ -71,20 +71,20 @@ dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase # name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# private static fields should have s_ prefix # private static fields should have s_ prefix
dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style
dotnet_naming_symbols.private_static_fields.applicable_kinds = field dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.required_modifiers = static dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
@ -93,7 +93,7 @@ dotnet_naming_style.private_static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase # internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field dotnet_naming_symbols.private_internal_fields.applicable_kinds = field

View file

@ -521,7 +521,7 @@ namespace SourceGit
private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop) private bool TryLaunchAsCoreEditor(IClassicDesktopStyleApplicationLifetime desktop)
{ {
var args = desktop.Args; var args = desktop.Args;
if (args == null || args.Length <= 1 || !args[0].Equals("--core-editor", StringComparison.Ordinal)) if (args is not { Length: > 1 } || !args[0].Equals("--core-editor", StringComparison.Ordinal))
return false; return false;
var file = args[1]; var file = args[1];

View file

@ -48,16 +48,12 @@ namespace SourceGit.Commands
if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead)) if (remoteHeads.TryGetValue(b.Upstream, out var upstreamHead))
{ {
b.IsUpstreamGone = false; b.IsUpstreamGone = false;
b.TrackStatus ??= new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
if (b.TrackStatus == null)
b.TrackStatus = new QueryTrackStatus(WorkingDirectory, b.Head, upstreamHead).Result();
} }
else else
{ {
b.IsUpstreamGone = true; b.IsUpstreamGone = true;
b.TrackStatus ??= new Models.BranchTrackStatus();
if (b.TrackStatus == null)
b.TrackStatus = new Models.BranchTrackStatus();
} }
} }
} }

View file

@ -24,7 +24,7 @@ namespace SourceGit.Commands
var records = rs.StdOut.Split(_boundary, StringSplitOptions.RemoveEmptyEntries); var records = rs.StdOut.Split(_boundary, StringSplitOptions.RemoveEmptyEntries);
foreach (var record in records) foreach (var record in records)
{ {
var subs = record.Split('\0', StringSplitOptions.None); var subs = record.Split('\0');
if (subs.Length != 6) if (subs.Length != 6)
continue; continue;

View file

@ -22,7 +22,7 @@ namespace SourceGit.Commands
} }
} }
private static bool ExecCmd(string repo, string args, string outputFile, Stream input = null) private static void ExecCmd(string repo, string args, string outputFile, Stream input = null)
{ {
var starter = new ProcessStartInfo(); var starter = new ProcessStartInfo();
starter.WorkingDirectory = repo; starter.WorkingDirectory = repo;
@ -45,10 +45,7 @@ namespace SourceGit.Commands
proc.StandardInput.Write(new StreamReader(input).ReadToEnd()); proc.StandardInput.Write(new StreamReader(input).ReadToEnd());
proc.StandardOutput.BaseStream.CopyTo(sw); proc.StandardOutput.BaseStream.CopyTo(sw);
proc.WaitForExit(); proc.WaitForExit();
var rs = proc.ExitCode == 0;
proc.Close(); proc.Close();
return rs;
} }
catch (Exception e) catch (Exception e)
{ {
@ -56,7 +53,6 @@ namespace SourceGit.Commands
{ {
App.RaiseException(repo, "Save file failed: " + e.Message); App.RaiseException(repo, "Save file failed: " + e.Message);
}); });
return false;
} }
} }
} }

View file

@ -26,10 +26,7 @@ namespace SourceGit.Models
{ {
get get
{ {
if (_instance == null) return _instance ??= new AvatarManager();
_instance = new AvatarManager();
return _instance;
} }
} }

View file

@ -16,11 +16,10 @@ namespace SourceGit.Models
Deleted, Deleted,
} }
public class TextInlineRange public class TextInlineRange(int p, int n)
{ {
public int Start { get; set; } public int Start { get; set; } = p;
public int End { get; set; } public int End { get; set; } = p + n - 1;
public TextInlineRange(int p, int n) { Start = p; End = p + n - 1; }
} }
public class TextDiffLine public class TextDiffLine
@ -556,7 +555,7 @@ namespace SourceGit.Models
} }
else if (test.Type == TextDiffLineType.Added) else if (test.Type == TextDiffLineType.Added)
{ {
if (i < start - 1) if (i < start - 1 || isOldSide)
{ {
if (revert) if (revert)
{ {
@ -566,18 +565,7 @@ namespace SourceGit.Models
} }
else else
{ {
if (isOldSide) newCount++;
{
if (revert)
{
newCount++;
oldCount++;
}
}
else
{
newCount++;
}
} }
if (i == end - 1 && tailed) if (i == end - 1 && tailed)
@ -655,9 +643,7 @@ namespace SourceGit.Models
public string NewImageSize => New != null ? $"{New.PixelSize.Width} x {New.PixelSize.Height}" : "0 x 0"; public string NewImageSize => New != null ? $"{New.PixelSize.Width} x {New.PixelSize.Height}" : "0 x 0";
} }
public class NoOrEOLChange public class NoOrEOLChange;
{
}
public class FileModeDiff public class FileModeDiff
{ {

View file

@ -107,8 +107,7 @@ namespace SourceGit.Models
// Ignore // Ignore
} }
if (_customPaths == null) _customPaths ??= new ExternalToolPaths();
_customPaths = new ExternalToolPaths();
} }
public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null) public void TryAdd(string name, string icon, Func<string> finder, Func<string, string> execArgsGenerator = null)

View file

@ -8,10 +8,7 @@ namespace SourceGit.Models
{ {
public class IpcChannel : IDisposable public class IpcChannel : IDisposable
{ {
public bool IsFirstInstance public bool IsFirstInstance { get; }
{
get => _isFirstInstance;
}
public event Action<string> MessageReceived; public event Action<string> MessageReceived;
@ -20,7 +17,7 @@ namespace SourceGit.Models
try try
{ {
_singletonLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None); _singletonLock = File.Open(Path.Combine(Native.OS.DataDir, "process.lock"), FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None);
_isFirstInstance = true; IsFirstInstance = true;
_server = new NamedPipeServerStream( _server = new NamedPipeServerStream(
"SourceGitIPCChannel" + Environment.UserName, "SourceGitIPCChannel" + Environment.UserName,
PipeDirection.In, PipeDirection.In,
@ -32,7 +29,7 @@ namespace SourceGit.Models
} }
catch catch
{ {
_isFirstInstance = false; IsFirstInstance = false;
} }
} }
@ -97,7 +94,6 @@ namespace SourceGit.Models
} }
private FileStream _singletonLock = null; private FileStream _singletonLock = null;
private bool _isFirstInstance = false;
private NamedPipeServerStream _server = null; private NamedPipeServerStream _server = null;
private CancellationTokenSource _cancellationTokenSource = null; private CancellationTokenSource _cancellationTokenSource = null;
} }

View file

@ -1,6 +1,4 @@
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class Null public class Null;
{
}
} }

View file

@ -33,9 +33,7 @@ namespace SourceGit.Models
} }
} }
public class AlreadyUpToDate public class AlreadyUpToDate;
{
}
public class SelfUpdateFailed public class SelfUpdateFailed
{ {

View file

@ -102,7 +102,7 @@ namespace SourceGit.Models
private int? Integer() private int? Integer()
{ {
var start = _pos; var start = _pos;
while (Peek() is char c && c >= '0' && c <= '9') while (Peek() is >= '0' and <= '9')
{ {
_pos++; _pos++;
} }
@ -118,7 +118,7 @@ namespace SourceGit.Models
// text token start // text token start
var tok = _pos; var tok = _pos;
bool esc = false; bool esc = false;
while (Next() is char c) while (Next() is { } c)
{ {
if (esc) if (esc)
{ {
@ -129,7 +129,7 @@ namespace SourceGit.Models
{ {
case ESCAPE: case ESCAPE:
// allow to escape only \ and $ // allow to escape only \ and $
if (Peek() is char nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR)) if (Peek() is { } nc && (nc == ESCAPE || nc == VARIABLE_ANCHOR))
{ {
esc = true; esc = true;
FlushText(tok, _pos - 1); FlushText(tok, _pos - 1);
@ -173,7 +173,7 @@ namespace SourceGit.Models
if (Next() != VARIABLE_START) if (Next() != VARIABLE_START)
return null; return null;
int name_start = _pos; int name_start = _pos;
while (Next() is char c) while (Next() is { } c)
{ {
// name character, continue advancing // name character, continue advancing
if (IsNameChar(c)) if (IsNameChar(c))
@ -228,7 +228,7 @@ namespace SourceGit.Models
var sb = new StringBuilder(); var sb = new StringBuilder();
var tok = _pos; var tok = _pos;
var esc = false; var esc = false;
while (Next() is char c) while (Next() is { } c)
{ {
if (esc) if (esc)
{ {
@ -277,7 +277,7 @@ namespace SourceGit.Models
var sb = new StringBuilder(); var sb = new StringBuilder();
var tok = _pos; var tok = _pos;
var esc = false; var esc = false;
while (Next() is char c) while (Next() is { } c)
{ {
if (esc) if (esc)
{ {

View file

@ -2,27 +2,19 @@
namespace SourceGit.Models namespace SourceGit.Models
{ {
public class TextInlineChange public class TextInlineChange(int dp, int dc, int ap, int ac)
{ {
public int DeletedStart { get; set; } public int DeletedStart { get; set; } = dp;
public int DeletedCount { get; set; } public int DeletedCount { get; set; } = dc;
public int AddedStart { get; set; } public int AddedStart { get; set; } = ap;
public int AddedCount { get; set; } public int AddedCount { get; set; } = ac;
private class Chunk private class Chunk(int hash, int start, int size)
{ {
public int Hash; public readonly int Hash = hash;
public readonly int Start = start;
public readonly int Size = size;
public bool Modified; public bool Modified;
public int Start;
public int Size;
public Chunk(int hash, int start, int size)
{
Hash = hash;
Modified = false;
Start = start;
Size = size;
}
} }
private enum Edit private enum Edit
@ -43,14 +35,6 @@ namespace SourceGit.Models
public int AddEnd; public int AddEnd;
} }
public TextInlineChange(int dp, int dc, int ap, int ac)
{
DeletedStart = dp;
DeletedCount = dc;
AddedStart = ap;
AddedCount = ac;
}
public static List<TextInlineChange> Compare(string oldValue, string newValue) public static List<TextInlineChange> Compare(string oldValue, string newValue)
{ {
var hashes = new Dictionary<string, int>(); var hashes = new Dictionary<string, int>();

View file

@ -54,7 +54,7 @@ namespace SourceGit.Native
public void SetupApp(AppBuilder builder) public void SetupApp(AppBuilder builder)
{ {
// Fix drop shadow issue on Windows 10 // Fix drop shadow issue on Windows 10
if (!OperatingSystem.IsWindowsVersionAtLeast(10, 22000, 0)) if (!OperatingSystem.IsWindowsVersionAtLeast(10, 22000))
{ {
Window.WindowStateProperty.Changed.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w)); Window.WindowStateProperty.Changed.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w));
Control.LoadedEvent.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w)); Control.LoadedEvent.AddClassHandler<Window>((w, _) => FixWindowFrameOnWin10(w));
@ -385,11 +385,11 @@ namespace SourceGit.Native
Microsoft.Win32.RegistryView.Registry64); Microsoft.Win32.RegistryView.Registry64);
// Get default class for VisualStudio.Launcher.sln - the handler for *.sln files // Get default class for VisualStudio.Launcher.sln - the handler for *.sln files
if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is Microsoft.Win32.RegistryKey launcher) if (localMachine.OpenSubKey(@"SOFTWARE\Classes\VisualStudio.Launcher.sln\CLSID") is { } launcher)
{ {
// Get actual path to the executable // Get actual path to the executable
if (launcher.GetValue(string.Empty) is string CLSID && if (launcher.GetValue(string.Empty) is string CLSID &&
localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is Microsoft.Win32.RegistryKey devenv && localMachine.OpenSubKey(@$"SOFTWARE\Classes\CLSID\{CLSID}\LocalServer32") is { } devenv &&
devenv.GetValue(string.Empty) is string localServer32) devenv.GetValue(string.Empty) is string localServer32)
return localServer32!.Trim('\"'); return localServer32!.Trim('\"');
} }

View file

@ -529,13 +529,7 @@
<Setter Property="MinHeight" Value="24"/> <Setter Property="MinHeight" Value="24"/>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Grid> <Grid ColumnDefinitions="*,1,Auto">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="1" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button x:Name="PART_PrimaryButton" <Button x:Name="PART_PrimaryButton"
Grid.Column="0" Grid.Column="0"
Classes="flat primary" Classes="flat primary"
@ -1001,12 +995,7 @@
<Setter Property="VerticalAlignment" Value="Center"/> <Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="Template"> <Setter Property="Template">
<ControlTemplate> <ControlTemplate>
<Grid Background="Transparent"> <Grid Background="Transparent" ColumnDefinitions="Auto,*">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Border x:Name="Border" Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" BorderBrush="{DynamicResource Brush.Border1}" BorderThickness="1" Background="Transparent" CornerRadius="2"> <Border x:Name="Border" Grid.Column="0" Width="16" Height="16" VerticalAlignment="Center" BorderBrush="{DynamicResource Brush.Border1}" BorderThickness="1" Background="Transparent" CornerRadius="2">
<Path x:Name="Icon" Height="12" Width="12" Data="{DynamicResource Icons.Check}" Fill="{DynamicResource Brush.Accent}" IsVisible="False" Margin="0,2,0,0"/> <Path x:Name="Icon" Height="12" Width="12" Data="{DynamicResource Icons.Check}" Fill="{DynamicResource Brush.Accent}" IsVisible="False" Margin="0,2,0,0"/>
</Border> </Border>

View file

@ -118,7 +118,7 @@ namespace SourceGit.ViewModels
public ContextMenu CreateChangeContextMenu() public ContextMenu CreateChangeContextMenu()
{ {
if (_selectedChanges == null || _selectedChanges.Count != 1) if (_selectedChanges is not { Count: 1 })
return null; return null;
var change = _selectedChanges[0]; var change = _selectedChanges[0];

View file

@ -74,9 +74,11 @@ namespace SourceGit.ViewModels
public class Builder public class Builder
{ {
public List<BranchTreeNode> Locals => _locals; public List<BranchTreeNode> Locals { get; } = [];
public List<BranchTreeNode> Remotes => _remotes;
public List<string> InvalidExpandedNodes => _invalidExpandedNodes; public List<BranchTreeNode> Remotes { get; } = [];
public List<string> InvalidExpandedNodes { get; } = [];
public Builder(Models.BranchSortMode localSortMode, Models.BranchSortMode remoteSortMode) public Builder(Models.BranchSortMode localSortMode, Models.BranchSortMode remoteSortMode)
{ {
@ -109,14 +111,14 @@ namespace SourceGit.ViewModels
fakeRemoteTime--; fakeRemoteTime--;
folders.Add(path, node); folders.Add(path, node);
_remotes.Add(node); Remotes.Add(node);
} }
foreach (var branch in branches) foreach (var branch in branches)
{ {
if (branch.IsLocal) if (branch.IsLocal)
{ {
MakeBranchNode(branch, _locals, folders, "refs/heads", bForceExpanded); MakeBranchNode(branch, Locals, folders, "refs/heads", bForceExpanded);
continue; continue;
} }
@ -131,20 +133,20 @@ namespace SourceGit.ViewModels
foreach (var path in _expanded) foreach (var path in _expanded)
{ {
if (!folders.ContainsKey(path)) if (!folders.ContainsKey(path))
_invalidExpandedNodes.Add(path); InvalidExpandedNodes.Add(path);
} }
folders.Clear(); folders.Clear();
if (_localSortMode == Models.BranchSortMode.Name) if (_localSortMode == Models.BranchSortMode.Name)
SortNodesByName(_locals); SortNodesByName(Locals);
else else
SortNodesByTime(_locals); SortNodesByTime(Locals);
if (_remoteSortMode == Models.BranchSortMode.Name) if (_remoteSortMode == Models.BranchSortMode.Name)
SortNodesByName(_remotes); SortNodesByName(Remotes);
else else
SortNodesByTime(_remotes); SortNodesByTime(Remotes);
} }
private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded) private void MakeBranchNode(Models.Branch branch, List<BranchTreeNode> roots, Dictionary<string, BranchTreeNode> folders, string prefix, bool bForceExpanded)
@ -269,9 +271,6 @@ namespace SourceGit.ViewModels
private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name; private readonly Models.BranchSortMode _localSortMode = Models.BranchSortMode.Name;
private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name; private readonly Models.BranchSortMode _remoteSortMode = Models.BranchSortMode.Name;
private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>();
private readonly List<BranchTreeNode> _remotes = new List<BranchTreeNode>();
private readonly List<string> _invalidExpandedNodes = new List<string>();
private readonly HashSet<string> _expanded = new HashSet<string>(); private readonly HashSet<string> _expanded = new HashSet<string>();
} }
} }

View file

@ -81,7 +81,7 @@ namespace SourceGit.ViewModels
{ {
if (SetProperty(ref _selectedChanges, value)) if (SetProperty(ref _selectedChanges, value))
{ {
if (value == null || value.Count != 1) if (value is not { Count: 1 })
DiffContext = null; DiffContext = null;
else else
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_commit, value[0]), _diffContext); DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_commit, value[0]), _diffContext);

View file

@ -46,10 +46,7 @@ namespace SourceGit.ViewModels
else if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote)) else if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote))
{ {
var def = _repo.Remotes.Find(r => r.Name == _repo.Settings.DefaultRemote); var def = _repo.Remotes.Find(r => r.Name == _repo.Settings.DefaultRemote);
if (def != null) SelectedRemote = def ?? _repo.Remotes[0];
SelectedRemote = def;
else
SelectedRemote = _repo.Remotes[0];
} }
else else
{ {

View file

@ -240,8 +240,7 @@ namespace SourceGit.ViewModels
} }
} }
if (firstRemoteBranch == null) firstRemoteBranch ??= remoteBranch;
firstRemoteBranch = remoteBranch;
} }
} }
@ -555,9 +554,7 @@ namespace SourceGit.ViewModels
var parents = new List<Models.Commit>(); var parents = new List<Models.Commit>();
foreach (var sha in commit.Parents) foreach (var sha in commit.Parents)
{ {
var parent = _commits.Find(x => x.SHA == sha); var parent = _commits.Find(x => x.SHA == sha) ?? new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
if (parent == null)
parent = new Commands.QuerySingleCommit(_repo.FullPath, sha).Result();
if (parent != null) if (parent != null)
parents.Add(parent); parents.Add(parent);

View file

@ -65,17 +65,14 @@ namespace SourceGit.ViewModels
var repos = ActiveWorkspace.Repositories.ToArray(); var repos = ActiveWorkspace.Repositories.ToArray();
foreach (var repo in repos) foreach (var repo in repos)
{ {
var node = pref.FindNode(repo); var node = pref.FindNode(repo) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = repo, Id = repo,
Name = Path.GetFileName(repo), Name = Path.GetFileName(repo),
Bookmark = 0, Bookmark = 0,
IsRepository = true, IsRepository = true,
}; };
}
OpenRepositoryInTab(node, null); OpenRepositoryInTab(node, null);
} }
@ -184,17 +181,14 @@ namespace SourceGit.ViewModels
var repos = to.Repositories.ToArray(); var repos = to.Repositories.ToArray();
foreach (var repo in repos) foreach (var repo in repos)
{ {
var node = pref.FindNode(repo); var node = pref.FindNode(repo) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = repo, Id = repo,
Name = Path.GetFileName(repo), Name = Path.GetFileName(repo),
Bookmark = 0, Bookmark = 0,
IsRepository = true, IsRepository = true,
}; };
}
OpenRepositoryInTab(node, null); OpenRepositoryInTab(node, null);
} }
@ -290,8 +284,7 @@ namespace SourceGit.ViewModels
return; return;
} }
if (page == null) page ??= _activePage;
page = _activePage;
var removeIdx = Pages.IndexOf(page); var removeIdx = Pages.IndexOf(page);
var activeIdx = Pages.IndexOf(_activePage); var activeIdx = Pages.IndexOf(_activePage);

View file

@ -87,7 +87,7 @@ namespace SourceGit.ViewModels
public bool CanCreatePopup() public bool CanCreatePopup()
{ {
return _popup == null || !_popup.InProgress; return _popup is not { InProgress: true };
} }
public void StartPopup(Popup popup) public void StartPopup(Popup popup)

View file

@ -7,7 +7,7 @@ namespace SourceGit.ViewModels
public class Pull : Popup public class Pull : Popup
{ {
public List<Models.Remote> Remotes => _repo.Remotes; public List<Models.Remote> Remotes => _repo.Remotes;
public Models.Branch Current => _current; public Models.Branch Current { get; }
public bool HasSpecifiedRemoteBranch public bool HasSpecifiedRemoteBranch
{ {
@ -64,7 +64,7 @@ namespace SourceGit.ViewModels
public Pull(Repository repo, Models.Branch specifiedRemoteBranch) public Pull(Repository repo, Models.Branch specifiedRemoteBranch)
{ {
_repo = repo; _repo = repo;
_current = repo.CurrentBranch; Current = repo.CurrentBranch;
if (specifiedRemoteBranch != null) if (specifiedRemoteBranch != null)
{ {
@ -84,12 +84,12 @@ namespace SourceGit.ViewModels
else else
{ {
var autoSelectedRemote = null as Models.Remote; var autoSelectedRemote = null as Models.Remote;
if (!string.IsNullOrEmpty(_current.Upstream)) if (!string.IsNullOrEmpty(Current.Upstream))
{ {
var remoteNameEndIdx = _current.Upstream.IndexOf('/', 13); var remoteNameEndIdx = Current.Upstream.IndexOf('/', 13);
if (remoteNameEndIdx > 0) if (remoteNameEndIdx > 0)
{ {
var remoteName = _current.Upstream.Substring(13, remoteNameEndIdx - 13); var remoteName = Current.Upstream.Substring(13, remoteNameEndIdx - 13);
autoSelectedRemote = _repo.Remotes.Find(x => x.Name == remoteName); autoSelectedRemote = _repo.Remotes.Find(x => x.Name == remoteName);
} }
} }
@ -146,7 +146,7 @@ namespace SourceGit.ViewModels
bool rs = new Commands.Pull( bool rs = new Commands.Pull(
_repo.FullPath, _repo.FullPath,
_selectedRemote.Name, _selectedRemote.Name,
!string.IsNullOrEmpty(_current.Upstream) && _current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name, !string.IsNullOrEmpty(Current.Upstream) && Current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name,
UseRebase).Use(log).Exec(); UseRebase).Use(log).Exec();
if (rs) if (rs)
@ -188,12 +188,12 @@ namespace SourceGit.ViewModels
RemoteBranches = branches; RemoteBranches = branches;
var autoSelectedBranch = false; var autoSelectedBranch = false;
if (!string.IsNullOrEmpty(_current.Upstream) && if (!string.IsNullOrEmpty(Current.Upstream) &&
_current.Upstream.StartsWith($"refs/remotes/{remoteName}/", System.StringComparison.Ordinal)) Current.Upstream.StartsWith($"refs/remotes/{remoteName}/", System.StringComparison.Ordinal))
{ {
foreach (var branch in branches) foreach (var branch in branches)
{ {
if (_current.Upstream == branch.FullName) if (Current.Upstream == branch.FullName)
{ {
SelectedBranch = branch; SelectedBranch = branch;
autoSelectedBranch = true; autoSelectedBranch = true;
@ -206,7 +206,7 @@ namespace SourceGit.ViewModels
{ {
foreach (var branch in branches) foreach (var branch in branches)
{ {
if (_current.Name == branch.Name) if (Current.Name == branch.Name)
{ {
SelectedBranch = branch; SelectedBranch = branch;
autoSelectedBranch = true; autoSelectedBranch = true;
@ -220,7 +220,6 @@ namespace SourceGit.ViewModels
} }
private readonly Repository _repo = null; private readonly Repository _repo = null;
private readonly Models.Branch _current = null;
private Models.Remote _selectedRemote = null; private Models.Remote _selectedRemote = null;
private List<Models.Branch> _remoteBranches = null; private List<Models.Branch> _remoteBranches = null;
private Models.Branch _selectedBranch = null; private Models.Branch _selectedBranch = null;

View file

@ -1424,17 +1424,14 @@ namespace SourceGit.ViewModels
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule)); var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
var normalizedPath = root.Replace('\\', '/').TrimEnd('/'); var normalizedPath = root.Replace('\\', '/').TrimEnd('/');
var node = Preferences.Instance.FindNode(normalizedPath); var node = Preferences.Instance.FindNode(normalizedPath) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = normalizedPath, Id = normalizedPath,
Name = Path.GetFileName(normalizedPath), Name = Path.GetFileName(normalizedPath),
Bookmark = selfPage.Node.Bookmark, Bookmark = selfPage.Node.Bookmark,
IsRepository = true, IsRepository = true,
}; };
}
App.GetLauncher().OpenRepositoryInTab(node, null); App.GetLauncher().OpenRepositoryInTab(node, null);
} }
@ -1453,17 +1450,14 @@ namespace SourceGit.ViewModels
public void OpenWorktree(Models.Worktree worktree) public void OpenWorktree(Models.Worktree worktree)
{ {
var node = Preferences.Instance.FindNode(worktree.FullPath); var node = Preferences.Instance.FindNode(worktree.FullPath) ??
if (node == null) new RepositoryNode
{
node = new RepositoryNode()
{ {
Id = worktree.FullPath, Id = worktree.FullPath,
Name = Path.GetFileName(worktree.FullPath), Name = Path.GetFileName(worktree.FullPath),
Bookmark = 0, Bookmark = 0,
IsRepository = true, IsRepository = true,
}; };
}
App.GetLauncher()?.OpenRepositoryInTab(node, null); App.GetLauncher()?.OpenRepositoryInTab(node, null);
} }

View file

@ -24,10 +24,7 @@ namespace SourceGit.ViewModels
private set => SetProperty(ref _endPoint, value); private set => SetProperty(ref _endPoint, value);
} }
public bool CanSaveAsPatch public bool CanSaveAsPatch { get; }
{
get => _canSaveAsPatch;
}
public List<Models.Change> VisibleChanges public List<Models.Change> VisibleChanges
{ {
@ -78,7 +75,7 @@ namespace SourceGit.ViewModels
_repo = repo; _repo = repo;
_startPoint = (object)startPoint ?? new Models.Null(); _startPoint = (object)startPoint ?? new Models.Null();
_endPoint = (object)endPoint ?? new Models.Null(); _endPoint = (object)endPoint ?? new Models.Null();
_canSaveAsPatch = startPoint != null && endPoint != null; CanSaveAsPatch = startPoint != null && endPoint != null;
Task.Run(Refresh); Task.Run(Refresh);
} }
@ -138,7 +135,7 @@ namespace SourceGit.ViewModels
public ContextMenu CreateChangeContextMenu() public ContextMenu CreateChangeContextMenu()
{ {
if (_selectedChanges == null || _selectedChanges.Count != 1) if (_selectedChanges is not { Count: 1 })
return null; return null;
var change = _selectedChanges[0]; var change = _selectedChanges[0];
@ -244,7 +241,6 @@ namespace SourceGit.ViewModels
private string _repo; private string _repo;
private object _startPoint = null; private object _startPoint = null;
private object _endPoint = null; private object _endPoint = null;
private bool _canSaveAsPatch = false;
private List<Models.Change> _changes = null; private List<Models.Change> _changes = null;
private List<Models.Change> _visibleChanges = null; private List<Models.Change> _visibleChanges = null;
private List<Models.Change> _selectedChanges = null; private List<Models.Change> _selectedChanges = null;

View file

@ -11,7 +11,7 @@ namespace SourceGit.ViewModels
{ {
public class Welcome : ObservableObject public class Welcome : ObservableObject
{ {
public static Welcome Instance => _instance; public static Welcome Instance { get; } = new();
public AvaloniaList<RepositoryNode> Rows public AvaloniaList<RepositoryNode> Rows
{ {
@ -354,7 +354,6 @@ namespace SourceGit.ViewModels
} }
} }
private static Welcome _instance = new Welcome();
private string _searchFilter = string.Empty; private string _searchFilter = string.Empty;
} }
} }

View file

@ -12,13 +12,7 @@
Icon="/App.ico" Icon="/App.ico"
Title="{DynamicResource Text.Blame}" Title="{DynamicResource Text.Blame}"
MinWidth="1280" MinHeight="720"> MinWidth="1280" MinHeight="720">
<Grid> <Grid RowDefinitions="Auto,24,*">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="24"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border --> <!-- Bottom border -->

View file

@ -306,7 +306,7 @@ namespace SourceGit.Views
return; return;
var view = TextArea.TextView; var view = TextArea.TextView;
if (view == null || !view.VisualLinesValid) if (view is not { VisualLinesValid: true })
return; return;
var color = (Color)this.FindResource("SystemAccentColor")!; var color = (Color)this.FindResource("SystemAccentColor")!;

View file

@ -13,13 +13,7 @@
Title="{DynamicResource Text.BranchCompare}" Title="{DynamicResource Text.BranchCompare}"
MinWidth="1280" MinHeight="720" MinWidth="1280" MinHeight="720"
WindowStartupLocation="CenterOwner"> WindowStartupLocation="CenterOwner">
<Grid> <Grid RowDefinitions="Auto,64,*">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="64"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border --> <!-- Bottom border -->

View file

@ -10,7 +10,7 @@ namespace SourceGit.Views
public class ColorPicker : Control public class ColorPicker : Control
{ {
public static readonly StyledProperty<uint> ValueProperty = public static readonly StyledProperty<uint> ValueProperty =
AvaloniaProperty.Register<ColorPicker, uint>(nameof(Value), 0); AvaloniaProperty.Register<ColorPicker, uint>(nameof(Value));
public uint Value public uint Value
{ {

View file

@ -11,7 +11,7 @@ namespace SourceGit.Views
public class CommandLogTime : TextBlock public class CommandLogTime : TextBlock
{ {
public static readonly StyledProperty<ViewModels.CommandLog> LogProperty = public static readonly StyledProperty<ViewModels.CommandLog> LogProperty =
AvaloniaProperty.Register<CommandLogTime, ViewModels.CommandLog>(nameof(Log), null); AvaloniaProperty.Register<CommandLogTime, ViewModels.CommandLog>(nameof(Log));
public ViewModels.CommandLog Log public ViewModels.CommandLog Log
{ {

View file

@ -57,7 +57,7 @@ namespace SourceGit.Views
} }
public static readonly StyledProperty<bool> ShowAdvancedOptionsProperty = public static readonly StyledProperty<bool> ShowAdvancedOptionsProperty =
AvaloniaProperty.Register<CommitMessageTextBox, bool>(nameof(ShowAdvancedOptions), false); AvaloniaProperty.Register<CommitMessageTextBox, bool>(nameof(ShowAdvancedOptions));
public static readonly StyledProperty<string> TextProperty = public static readonly StyledProperty<string> TextProperty =
AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Text), string.Empty); AvaloniaProperty.Register<CommitMessageTextBox, string>(nameof(Text), string.Empty);
@ -182,7 +182,7 @@ namespace SourceGit.Views
{ {
var menu = vm.CreateContextMenuForCommitMessages(); var menu = vm.CreateContextMenuForCommitMessages();
menu.Placement = PlacementMode.TopEdgeAlignedLeft; menu.Placement = PlacementMode.TopEdgeAlignedLeft;
menu?.Open(button); menu.Open(button);
} }
e.Handled = true; e.Handled = true;

View file

@ -19,7 +19,7 @@ namespace SourceGit.Views
} }
public static readonly StyledProperty<int> DateTimeFormatProperty = public static readonly StyledProperty<int> DateTimeFormatProperty =
AvaloniaProperty.Register<CommitTimeTextBlock, int>(nameof(DateTimeFormat), 0); AvaloniaProperty.Register<CommitTimeTextBlock, int>(nameof(DateTimeFormat));
public int DateTimeFormat public int DateTimeFormat
{ {

View file

@ -112,7 +112,7 @@
</Grid> </Grid>
</Border> </Border>
<StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel Margin="0,8,0,0" Orientation="Horizontal" HorizontalAlignment="Center">
<Button Classes="flat" Margin="0,0,0,0" Command="{Binding UseTheirs}"> <Button Classes="flat" Margin="0,0,0,0" Command="{Binding UseTheirs}">
<StackPanel Orientation="Horizontal"> <StackPanel Orientation="Horizontal">
<Path Width="12" Height="12" Data="{StaticResource Icons.Incoming}"/> <Path Width="12" Height="12" Data="{StaticResource Icons.Incoming}"/>

View file

@ -13,12 +13,7 @@
Icon="/App.ico" Icon="/App.ico"
Title="{DynamicResource Text.FileHistory}" Title="{DynamicResource Text.FileHistory}"
MinWidth="1280" MinHeight="720"> MinWidth="1280" MinHeight="720">
<Grid> <Grid RowDefinitions="Auto,*">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- TitleBar --> <!-- TitleBar -->
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}"> <Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<!-- Bottom border --> <!-- Bottom border -->

View file

@ -12,7 +12,7 @@ namespace SourceGit.Views
public class HistoriesLayout : Grid public class HistoriesLayout : Grid
{ {
public static readonly StyledProperty<bool> UseHorizontalProperty = public static readonly StyledProperty<bool> UseHorizontalProperty =
AvaloniaProperty.Register<HistoriesLayout, bool>(nameof(UseHorizontal), false); AvaloniaProperty.Register<HistoriesLayout, bool>(nameof(UseHorizontal));
public bool UseHorizontal public bool UseHorizontal
{ {

View file

@ -55,7 +55,7 @@ namespace SourceGit.Views
{ {
if (sender is ContentPresenter presenter) if (sender is ContentPresenter presenter)
{ {
if (presenter.DataContext == null || presenter.DataContext is not ViewModels.Popup) if (presenter.DataContext is not ViewModels.Popup)
{ {
presenter.Content = null; presenter.Content = null;
return; return;

View file

@ -84,7 +84,7 @@ namespace SourceGit.Views
return; return;
var geo = new StreamGeometry(); var geo = new StreamGeometry();
var angle = Math.PI / 2; const double angle = Math.PI / 2;
var y = height + 0.5; var y = height + 0.5;
using (var ctx = geo.Open()) using (var ctx = geo.Open())
{ {

View file

@ -1,12 +1,11 @@
using Avalonia; using Avalonia;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Data;
namespace SourceGit.Views namespace SourceGit.Views
{ {
public class MenuItemExtension : AvaloniaObject public class MenuItemExtension : AvaloniaObject
{ {
public static readonly AttachedProperty<string> CommandProperty = public static readonly AttachedProperty<string> CommandProperty =
AvaloniaProperty.RegisterAttached<MenuItemExtension, MenuItem, string>("Command", string.Empty, false, BindingMode.OneWay); AvaloniaProperty.RegisterAttached<MenuItemExtension, MenuItem, string>("Command", string.Empty);
} }
} }

View file

@ -12,7 +12,7 @@ namespace SourceGit.Views
public class CounterPresenter : Control public class CounterPresenter : Control
{ {
public static readonly StyledProperty<int> CountProperty = public static readonly StyledProperty<int> CountProperty =
AvaloniaProperty.Register<CounterPresenter, int>(nameof(Count), 0); AvaloniaProperty.Register<CounterPresenter, int>(nameof(Count));
public int Count public int Count
{ {

View file

@ -155,7 +155,7 @@ namespace SourceGit.Views
private void NavigateToHead(object sender, RoutedEventArgs e) private void NavigateToHead(object sender, RoutedEventArgs e)
{ {
if (DataContext is ViewModels.Repository { CurrentBranch: { } } repo) if (DataContext is ViewModels.Repository { CurrentBranch: not null } repo)
{ {
repo.NavigateToCommit(repo.CurrentBranch.Head); repo.NavigateToCommit(repo.CurrentBranch.Head);
e.Handled = true; e.Handled = true;

View file

@ -136,8 +136,7 @@ namespace SourceGit.Views
{ {
if (UseSyntaxHighlighting) if (UseSyntaxHighlighting)
{ {
if (_textMate == null) _textMate ??= Models.TextMateHelper.CreateForEditor(this);
_textMate = Models.TextMateHelper.CreateForEditor(this);
if (DataContext is Models.RevisionTextFile file) if (DataContext is Models.RevisionTextFile file)
Models.TextMateHelper.SetGrammarByFileName(_textMate, file.FileName); Models.TextMateHelper.SetGrammarByFileName(_textMate, file.FileName);

View file

@ -134,10 +134,7 @@ namespace SourceGit.Views
set => SetValue(RevisionProperty, value); set => SetValue(RevisionProperty, value);
} }
public AvaloniaList<ViewModels.RevisionFileTreeNode> Rows public AvaloniaList<ViewModels.RevisionFileTreeNode> Rows { get; } = [];
{
get => _rows;
}
public RevisionFileTreeView() public RevisionFileTreeView()
{ {
@ -146,7 +143,7 @@ namespace SourceGit.Views
public void SetSearchResult(string file) public void SetSearchResult(string file)
{ {
_rows.Clear(); Rows.Clear();
_searchResult.Clear(); _searchResult.Clear();
var rows = new List<ViewModels.RevisionFileTreeNode>(); var rows = new List<ViewModels.RevisionFileTreeNode>();
@ -161,10 +158,10 @@ namespace SourceGit.Views
return; return;
var objects = vm.GetRevisionFilesUnderFolder(file); var objects = vm.GetRevisionFilesUnderFolder(file);
if (objects == null || objects.Count != 1) if (objects is not { Count: 1 })
return; return;
var routes = file.Split('/', StringSplitOptions.None); var routes = file.Split('/');
if (routes.Length == 1) if (routes.Length == 1)
{ {
_searchResult.Add(new ViewModels.RevisionFileTreeNode _searchResult.Add(new ViewModels.RevisionFileTreeNode
@ -202,7 +199,7 @@ namespace SourceGit.Views
MakeRows(rows, _searchResult, 0); MakeRows(rows, _searchResult, 0);
} }
_rows.AddRange(rows); Rows.AddRange(rows);
GC.Collect(); GC.Collect();
} }
@ -212,7 +209,7 @@ namespace SourceGit.Views
node.IsExpanded = !node.IsExpanded; node.IsExpanded = !node.IsExpanded;
var depth = node.Depth; var depth = node.Depth;
var idx = _rows.IndexOf(node); var idx = Rows.IndexOf(node);
if (idx == -1) if (idx == -1)
return; return;
@ -223,21 +220,21 @@ namespace SourceGit.Views
{ {
var subrows = new List<ViewModels.RevisionFileTreeNode>(); var subrows = new List<ViewModels.RevisionFileTreeNode>();
MakeRows(subrows, subtree, depth + 1); MakeRows(subrows, subtree, depth + 1);
_rows.InsertRange(idx + 1, subrows); Rows.InsertRange(idx + 1, subrows);
} }
} }
else else
{ {
var removeCount = 0; var removeCount = 0;
for (int i = idx + 1; i < _rows.Count; i++) for (int i = idx + 1; i < Rows.Count; i++)
{ {
var row = _rows[i]; var row = Rows[i];
if (row.Depth <= depth) if (row.Depth <= depth)
break; break;
removeCount++; removeCount++;
} }
_rows.RemoveRange(idx + 1, removeCount); Rows.RemoveRange(idx + 1, removeCount);
} }
_disableSelectionChangingEvent = false; _disableSelectionChangingEvent = false;
@ -250,7 +247,7 @@ namespace SourceGit.Views
if (change.Property == RevisionProperty) if (change.Property == RevisionProperty)
{ {
_tree.Clear(); _tree.Clear();
_rows.Clear(); Rows.Clear();
_searchResult.Clear(); _searchResult.Clear();
var vm = DataContext as ViewModels.CommitDetail; var vm = DataContext as ViewModels.CommitDetail;
@ -274,7 +271,7 @@ namespace SourceGit.Views
var topTree = new List<ViewModels.RevisionFileTreeNode>(); var topTree = new List<ViewModels.RevisionFileTreeNode>();
MakeRows(topTree, _tree, 0); MakeRows(topTree, _tree, 0);
_rows.AddRange(topTree); Rows.AddRange(topTree);
GC.Collect(); GC.Collect();
} }
} }
@ -365,7 +362,6 @@ namespace SourceGit.Views
} }
private List<ViewModels.RevisionFileTreeNode> _tree = []; private List<ViewModels.RevisionFileTreeNode> _tree = [];
private AvaloniaList<ViewModels.RevisionFileTreeNode> _rows = [];
private bool _disableSelectionChangingEvent = false; private bool _disableSelectionChangingEvent = false;
private List<ViewModels.RevisionFileTreeNode> _searchResult = []; private List<ViewModels.RevisionFileTreeNode> _searchResult = [];
} }

View file

@ -348,16 +348,11 @@ namespace SourceGit.Views
private ThemedTextDiffPresenter _presenter = null; private ThemedTextDiffPresenter _presenter = null;
} }
public class LineStyleTransformer : DocumentColorizingTransformer public class LineStyleTransformer(ThemedTextDiffPresenter presenter) : DocumentColorizingTransformer
{ {
public LineStyleTransformer(ThemedTextDiffPresenter presenter)
{
_presenter = presenter;
}
protected override void ColorizeLine(DocumentLine line) protected override void ColorizeLine(DocumentLine line)
{ {
var lines = _presenter.GetLines(); var lines = presenter.GetLines();
var idx = line.LineNumber; var idx = line.LineNumber;
if (idx > lines.Count) if (idx > lines.Count)
return; return;
@ -367,13 +362,11 @@ namespace SourceGit.Views
{ {
ChangeLinePart(line.Offset, line.EndOffset, v => ChangeLinePart(line.Offset, line.EndOffset, v =>
{ {
v.TextRunProperties.SetForegroundBrush(_presenter.IndicatorForeground); v.TextRunProperties.SetForegroundBrush(presenter.IndicatorForeground);
v.TextRunProperties.SetTypeface(new Typeface(_presenter.FontFamily, FontStyle.Italic)); v.TextRunProperties.SetTypeface(new Typeface(presenter.FontFamily, FontStyle.Italic));
}); });
} }
} }
private readonly ThemedTextDiffPresenter _presenter;
} }
public static readonly StyledProperty<string> FileNameProperty = public static readonly StyledProperty<string> FileNameProperty =