Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/Models/HistoryLayout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
namespace SourceGit.Models
{
public enum HistoryLayout
{
Stacked,
SideBySide,
Focused,
}
}
6 changes: 6 additions & 0 deletions src/Models/RepositoryUIStates.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ public double AuthorColumnWidth
set;
} = 120;

public double FocusedHistoryDetailsWidth
{
get;
set;
} = 340;

public bool EnableTopoOrderInHistory
{
get;
Expand Down
4 changes: 4 additions & 0 deletions src/Resources/Locales/en_US.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,8 @@
<x:String x:Key="Text.GitLFS.TrackByExtension" xml:space="preserve">Track all *{0} files</x:String>
<x:String x:Key="Text.GotoRevisionSelector" xml:space="preserve">Select Commit</x:String>
<x:String x:Key="Text.Histories.AdvancedOptions" xml:space="preserve">Advanced Options</x:String>
<x:String x:Key="Text.Histories.BackToGraph" xml:space="preserve">← Graph</x:String>
<x:String x:Key="Text.Histories.CopyCommitSHA" xml:space="preserve">Copy full commit SHA</x:String>
<x:String x:Key="Text.Histories.Header.Author" xml:space="preserve">AUTHOR</x:String>
<x:String x:Key="Text.Histories.Header.AuthorTime" xml:space="preserve">AUTHOR TIME</x:String>
<x:String x:Key="Text.Histories.Header.CommitTime" xml:space="preserve">COMMIT TIME</x:String>
Expand All @@ -527,6 +529,7 @@
<x:String x:Key="Text.Histories.HighlightsInGraph.SelectedCommitsOnly" xml:space="preserve">Selected Commits Only</x:String>
<x:String x:Key="Text.Histories.HighlightsInGraph.SelectedCommitsOnlyFirstParent" xml:space="preserve">Selected Commits (First-parent Only)</x:String>
<x:String x:Key="Text.Histories.Selected" xml:space="preserve">SELECTED {0} COMMITS</x:String>
<x:String x:Key="Text.Histories.SelectionDetails" xml:space="preserve">DETAILS</x:String>
<x:String x:Key="Text.Histories.ShowColumns" xml:space="preserve">SHOW COLUMNS</x:String>
<x:String x:Key="Text.Histories.Tips" xml:space="preserve">Hold 'Ctrl' or 'Shift' to select multiple commits.</x:String>
<x:String x:Key="Text.Histories.Tips.MacOS" xml:space="preserve">Hold ⌘ or ⇧ to select multiple commits.</x:String>
Expand Down Expand Up @@ -822,6 +825,7 @@
<x:String x:Key="Text.Repository.FilterCommits.Include" xml:space="preserve">Filter in commit graph</x:String>
<x:String x:Key="Text.Repository.FilterCommits.Summary" xml:space="preserve">filter(s) enabled</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout" xml:space="preserve">LAYOUT</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Focused" xml:space="preserve">Focused</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Horizontal" xml:space="preserve">Horizontal</x:String>
<x:String x:Key="Text.Repository.HistoriesLayout.Vertical" xml:space="preserve">Vertical</x:String>
<x:String x:Key="Text.Repository.HistoriesOrder" xml:space="preserve">COMMITS ORDER</x:String>
Expand Down
4 changes: 2 additions & 2 deletions src/ViewModels/CommitDetail.cs
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,9 @@ private void Refresh()
}, token);
}

private void UpdateDetails()
public void UpdateDetails()
{
if (ActiveTabIndex == 1 && _changeSelection is { Count: 1, HasFolder: false })
if ((ActiveTabIndex == 1 || Preferences.Instance.IsFocusedHistoryLayout) && _changeSelection is { Count: 1, HasFolder: false })
DiffContext = new DiffContext(_repo.FullPath, new Models.DiffOption(_commit, _changeSelection.Changes[0]), _diffContext);
else
DiffContext = null;
Expand Down
106 changes: 102 additions & 4 deletions src/ViewModels/Histories.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Threading.Tasks;

Expand Down Expand Up @@ -149,10 +150,92 @@ public object DetailContext
set
{
if (SetProperty(ref _detailContext, value))
{
ShowGraph();
ObserveDetailContext(value);
OnPropertyChanged(nameof(IsOpenAsStandaloneVisible));
}
}
}

public DiffContext FocusedDiff
{
get => _focusedDiff;
private set
{
if (SetProperty(ref _focusedDiff, value))
OnPropertyChanged(nameof(IsFocusedDiffVisible));
}
}

public string FocusedDiffPath
{
get => _focusedDiffPath;
private set => SetProperty(ref _focusedDiffPath, value);
}

public bool IsFocusedDiffVisible => Preferences.Instance.IsFocusedHistoryLayout && FocusedDiff != null;

public void OpenFocusedDiff()
{
if (!Preferences.Instance.IsFocusedHistoryLayout)
return;

ChangeSelection selection;
DiffContext diff;
if (DetailContext is CommitDetail detail)
{
selection = detail.ChangeSelection;
if (detail.DiffContext == null)
detail.UpdateDetails();
diff = detail.DiffContext;
}
else if (DetailContext is RevisionCompare compare)
{
selection = compare.ChangeSelection;
diff = compare.DiffContext;
}
else
{
return;
}

if (selection is { Count: 1, HasFolder: false } && diff != null)
{
FocusedDiffPath = selection.Changes[0].Path;
FocusedDiff = diff;
}
}

public void ShowGraph()
{
FocusedDiff = null;
FocusedDiffPath = string.Empty;
}

public void UpdateLayout()
{
ShowGraph();
OnPropertyChanged(nameof(RightArea));
OnPropertyChanged(nameof(BottomArea));
}

private void ObserveDetailContext(object context)
{
if (_observedDetailContext != null)
_observedDetailContext.PropertyChanged -= OnDetailContextPropertyChanged;
_observedDetailContext = context as INotifyPropertyChanged;
if (_observedDetailContext != null)
_observedDetailContext.PropertyChanged += OnDetailContextPropertyChanged;
}

private void OnDetailContextPropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName is nameof(CommitDetail.Commit) or nameof(RevisionCompare.IsLoading) or
nameof(RevisionCompare.StartPoint) or nameof(RevisionCompare.EndPoint))
ShowGraph();
}

public Models.Bisect Bisect
{
get => _bisect;
Expand Down Expand Up @@ -184,8 +267,20 @@ public GridLength LeftArea

public GridLength RightArea
{
get => _rightArea;
set => SetProperty(ref _rightArea, value);
get => Preferences.Instance.IsFocusedHistoryLayout ? new GridLength(_repo.UIStates.FocusedHistoryDetailsWidth) : _rightArea;
set
{
if (Preferences.Instance.IsFocusedHistoryLayout)
{
if (value.IsAbsolute && value.Value >= 260)
{
_repo.UIStates.FocusedHistoryDetailsWidth = value.Value;
OnPropertyChanged();
}
}
else
SetProperty(ref _rightArea, value);
}
}

public GridLength TopArea
Expand All @@ -199,7 +294,7 @@ public GridLength BottomArea
get => _isCollapseDetails ? new GridLength(28, GridUnitType.Pixel) : _bottomArea;
set
{
if (!Preferences.Instance.UseTwoColumnsLayoutInHistories && !_isCollapseDetails)
if (!Preferences.Instance.IsHorizontalHistoryLayout && !_isCollapseDetails)
SetProperty(ref _bottomArea, value);
}
}
Expand All @@ -220,7 +315,7 @@ public bool IsCollapseDetails
get => _isCollapseDetails;
set
{
if (!Preferences.Instance.UseTwoColumnsLayoutInHistories && SetProperty(ref _isCollapseDetails, value))
if (!Preferences.Instance.IsHorizontalHistoryLayout && SetProperty(ref _isCollapseDetails, value))
{
OnPropertyChanged(nameof(TopArea));
OnPropertyChanged(nameof(BottomArea));
Expand Down Expand Up @@ -588,6 +683,9 @@ private void GenerateGraph(List<Models.Commit> commits)
private Models.Bisect _bisect = null;
private object _detailContext = Models.Null.Instance;
private bool _ignoreSelectionChange = false;
private INotifyPropertyChanged _observedDetailContext = null;
private DiffContext _focusedDiff = null;
private string _focusedDiffPath = string.Empty;

private bool _isSearchingCommits = false;
private SearchCommitContext _searchCommitContext = null;
Expand Down
37 changes: 35 additions & 2 deletions src/ViewModels/Preferences.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,8 +213,40 @@ public bool UseCompactBranchNamesInGraph

public bool UseTwoColumnsLayoutInHistories
{
get => _useTwoColumnsLayoutInHistories;
set => SetProperty(ref _useTwoColumnsLayoutInHistories, value);
get => IsHorizontalHistoryLayout;
set
{
// Keep reading older preference files. The explicit layout takes precedence,
// regardless of the order of properties in the JSON document.
if (SetProperty(ref _useTwoColumnsLayoutInHistories, value) && !_historyLayout.HasValue)
NotifyHistoryLayoutChanged();
}
}

public Models.HistoryLayout HistoryLayout
{
get => _historyLayout ?? (_useTwoColumnsLayoutInHistories ? Models.HistoryLayout.SideBySide : Models.HistoryLayout.Stacked);
set
{
if (Enum.IsDefined(value) && _historyLayout != value)
{
_historyLayout = value;
NotifyHistoryLayoutChanged();
}
}
}

[JsonIgnore]
public bool IsHorizontalHistoryLayout => HistoryLayout != Models.HistoryLayout.Stacked;

[JsonIgnore]
public bool IsFocusedHistoryLayout => HistoryLayout == Models.HistoryLayout.Focused;

private void NotifyHistoryLayoutChanged()
{
OnPropertyChanged(nameof(HistoryLayout));
OnPropertyChanged(nameof(IsHorizontalHistoryLayout));
OnPropertyChanged(nameof(IsFocusedHistoryLayout));
}

public bool DisplayTimeAsPeriodInHistories
Expand Down Expand Up @@ -831,6 +863,7 @@ private bool RemoveInvalidRepositoriesRecursive(List<RepositoryNode> collection)

private bool _showTagsInGraph = true;
private bool _useTwoColumnsLayoutInHistories = false;
private Models.HistoryLayout? _historyLayout = null;
private bool _displayTimeAsPeriodInHistories = false;
private bool _useSideBySideDiff = false;
private bool _ignoreWhitespaceChangesInDiff = false;
Expand Down
7 changes: 5 additions & 2 deletions src/ViewModels/RevisionCompare.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,8 @@ _endPoint is Models.Commit e &&
hashes.Contains(e.SHA))
return;

_startPoint = l;
_endPoint = r;
StartPoint = l;
EndPoint = r;
Refresh();
}

Expand Down Expand Up @@ -343,6 +343,9 @@ private void RefreshVisible()

private void Refresh()
{
OnPropertyChanged(nameof(LeftSideDesc));
OnPropertyChanged(nameof(RightSideDesc));

Task.Run(async () =>
{
_changes = await new Commands.CompareRevisions(_repo.FullPath, GetSHA(_startPoint), GetSHA(_endPoint))
Expand Down
43 changes: 43 additions & 0 deletions src/Views/ChangeCollectionView.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,49 @@ public event EventHandler<RoutedEventArgs> ChangeDoubleTapped
public ChangeCollectionView()
{
InitializeComponent();
AddHandler(PointerReleasedEvent, OnChangePointerReleased, RoutingStrategies.Bubble, true);
AddHandler(KeyDownEvent, OnChangeKeyDown, RoutingStrategies.Bubble, true);
}

public static readonly RoutedEvent<RoutedEventArgs> ChangeActivatedEvent =
RoutedEvent.Register<ChangeCollectionView, RoutedEventArgs>(nameof(ChangeActivated), RoutingStrategies.Bubble);

public event EventHandler<RoutedEventArgs> ChangeActivated
{
add { AddHandler(ChangeActivatedEvent, value); }
remove { RemoveHandler(ChangeActivatedEvent, value); }
}

private void OnChangePointerReleased(object sender, PointerReleasedEventArgs e)
{
if (e.InitialPressMouseButton != MouseButton.Left || e.KeyModifiers != KeyModifiers.None ||
Selection is not { Count: 1, HasFolder: false })
return;

for (var source = e.Source as Control; source != null && source != this; source = source.GetVisualParent() as Control)
{
if (source is not ListBoxItem item)
continue;

var change = item.DataContext switch
{
Models.Change c => c,
ViewModels.ChangeTreeNode { IsFolder: false } node => node.Change,
_ => null,
};
if (change == Selection.Changes[0])
RaiseEvent(new RoutedEventArgs(ChangeActivatedEvent));
return;
}
}

private void OnChangeKeyDown(object sender, KeyEventArgs e)
{
if (e.KeyModifiers != KeyModifiers.None || Selection is not { Count: 1, HasFolder: false })
return;

if (e.Key is Key.Enter or Key.Space or Key.Up or Key.Down or Key.Home or Key.End or Key.PageUp or Key.PageDown)
RaiseEvent(new RoutedEventArgs(ChangeActivatedEvent));
}

public void ToggleNodeIsExpanded(ViewModels.ChangeTreeNode node)
Expand Down
59 changes: 59 additions & 0 deletions src/Views/ChangeListLayout.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
using Avalonia;
using Avalonia.Controls;

namespace SourceGit.Views
{
public class ChangeListLayout : Grid
{
public static readonly StyledProperty<bool> IsFileListOnlyProperty =
AvaloniaProperty.Register<ChangeListLayout, bool>(nameof(IsFileListOnly));

public static readonly StyledProperty<GridLength> ListWidthProperty =
AvaloniaProperty.Register<ChangeListLayout, GridLength>(nameof(ListWidth), new GridLength(256));

public bool IsFileListOnly
{
get => GetValue(IsFileListOnlyProperty);
set => SetValue(IsFileListOnlyProperty, value);
}

public GridLength ListWidth
{
get => GetValue(ListWidthProperty);
set => SetValue(ListWidthProperty, value);
}

protected override System.Type StyleKeyOverride => typeof(Grid);

public ChangeListLayout()
{
ColumnDefinitions = new ColumnDefinitions("256,4,*");
ColumnDefinitions[0].PropertyChanged += (_, e) =>
{
if (!_updating && !IsFileListOnly && e.Property == ColumnDefinition.WidthProperty)
SetCurrentValue(ListWidthProperty, ColumnDefinitions[0].Width);
};
RefreshLayout();
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == IsFileListOnlyProperty || change.Property == ListWidthProperty)
RefreshLayout();
}

private void RefreshLayout()
{
_updating = true;
ColumnDefinitions[0].MinWidth = IsFileListOnly ? 0 : 200;
ColumnDefinitions[0].Width = IsFileListOnly ? GridLength.Star : ListWidth;
ColumnDefinitions[1].Width = new GridLength(IsFileListOnly ? 0 : 4);
ColumnDefinitions[2].MinWidth = IsFileListOnly ? 0 : 100;
ColumnDefinitions[2].Width = IsFileListOnly ? new GridLength(0) : GridLength.Star;
_updating = false;
}

private bool _updating = false;
}
}
Loading