Skip to content

Allow text wrapping in WPF controls #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions DiffPlex.Wpf.Demo/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<Button Width="100" Height="20" x:Name="DiffButton" Content="Switch Mode" Click="DiffButton_Click" BorderBrush="{x:Null}" BorderThickness="0" Margin="16,0,1,0" />
<Button Width="20" Height="20" x:Name="FutherActionsButton" Content="…" Click="FutherActionsButton_Click" BorderBrush="{x:Null}" BorderThickness="0" Margin="0,0,31,0" />
<CheckBox Width="120" Height="20" VerticalContentAlignment="Center" IsChecked="{Binding IsSideBySide, ElementName=DiffView}" Content="Is_SideBySide" Foreground="{Binding Foreground, ElementName=DiffView}" />
<CheckBox Width="120" Height="20" VerticalContentAlignment="Center" IsChecked="{Binding IsTextWrapEnabled, ElementName=DiffView}" Content="Is_Wrapped" Foreground="{Binding Foreground, ElementName=DiffView}" />
<CheckBox Height="20" VerticalContentAlignment="Center" x:Name="IgnoreUnchangedCheckBox" IsChecked="{Binding IgnoreUnchanged, ElementName=DiffView}" Content="IgnoreUnchanged" Margin="0,0,24,0" Foreground="{Binding Foreground, ElementName=DiffView}" />
<Label Height="20" VerticalContentAlignment="Center" Padding="0,0,8,0" x:Name="MarginLineCountLabel" Target="{Binding ElementName=MarginLineCount}" Foreground="{Binding Foreground, ElementName=DiffView}">LinesContext</Label>
<TextBox Width="100" Height="20" VerticalContentAlignment="Center" x:Name="MarginLineCount" Padding="8,0,8,0" Text="{Binding LinesContext, ElementName=DiffView, UpdateSourceTrigger=PropertyChanged}" Foreground="{Binding Foreground, ElementName=DiffView}" Background="{x:Null}" Margin="0,0,32,0" />
Expand Down
24 changes: 24 additions & 0 deletions DiffPlex.Wpf/Controls/BooleanToScrollBarVisibilityConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Globalization;
using System.Windows.Controls;
using System.Windows.Data;

namespace DiffPlex.Wpf.Controls
{
public class BooleanToScrollBarVisibilityConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value is bool isTextWrapEnabled)
{
return isTextWrapEnabled ? ScrollBarVisibility.Hidden : ScrollBarVisibility.Auto;
}
return ScrollBarVisibility.Auto;
}

public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}
2 changes: 1 addition & 1 deletion DiffPlex.Wpf/Controls/DiffViewer.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,4 @@
<TextBlock x:Name="RightHeaderText" HorizontalAlignment="Center" VerticalAlignment="Center" Grid.Row="1" Grid.Column="1" />
<local:InternalLinesViewer x:Name="RightContentPanel" ScrollChanged="RightContentPanel_ScrollChanged" Grid.Row="2" Grid.Column="1" />
</Grid>
</UserControl>
</UserControl>
29 changes: 26 additions & 3 deletions DiffPlex.Wpf/Controls/DiffViewer.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace DiffPlex.Wpf.Controls;
/// <summary>
/// The diff control for text.
/// </summary>
public partial class DiffViewer : UserControl
public partial class DiffViewer : UserControl, IDiffViewer
{
/// <summary>
/// The event arguments of view mode changed.
Expand Down Expand Up @@ -80,6 +80,11 @@ public ViewModeChangedEventArgs(bool isSideBySide)
/// </summary>
public static readonly DependencyProperty LineNumberForegroundProperty = RegisterDependencyProperty<Brush>(nameof(LineNumberForeground), new SolidColorBrush(Color.FromArgb(255, 64, 128, 160)));

/// <summary>
/// The property of text wrapping state.
/// </summary>
public static readonly DependencyProperty IsTextWrapEnabledProperty = RegisterRefreshDependencyProperty(nameof(IsTextWrapEnabled), false);

/// <summary>
/// The property of line number width.
/// </summary>
Expand Down Expand Up @@ -651,6 +656,17 @@ public int LinesContext
set => SetValue(LinesContextProperty, value);
}

/// <summary>
/// Gets or sets the value indicating whether is wrap text.
/// </summary>
[Bindable(true)]
[Category("Appearance")]
public bool IsTextWrapEnabled
{
get => (bool)GetValue(IsTextWrapEnabledProperty);
set => SetValue(IsTextWrapEnabledProperty, value);
}

/// <summary>
/// Gets or sets the display name of inline mode toggle.
/// </summary>
Expand Down Expand Up @@ -1142,7 +1158,7 @@ private void RenderSideBySideDiffs()
var m = sideBySideResult;
CollapseUnchangedSectionsToggle.IsChecked = IgnoreUnchanged;
if (m == null) return;
var contextLineCount = IgnoreUnchanged ? LinesContext: -1;
var contextLineCount = IgnoreUnchanged ? LinesContext : -1;
Helper.InsertLines(LeftContentPanel, m.OldText?.Lines, true, this, contextLineCount);
Helper.InsertLines(RightContentPanel, m.NewText.Lines, false, this, contextLineCount);
}
Expand Down Expand Up @@ -1306,6 +1322,13 @@ public DiffPiece NextDiff()
return line;
}

public void ToggleTextWrapping()
{
IsTextWrapEnabled = !IsTextWrapEnabled;

this.Refresh();
}

private string GenerateHeader(FileInfo file)
{
if (file == null || !file.Exists) return Resource.Empty;
Expand Down Expand Up @@ -1488,4 +1511,4 @@ private static DependencyProperty RegisterRefreshDependencyProperty<T>(string na
c.Refresh();
}));
}
}
}
24 changes: 18 additions & 6 deletions DiffPlex.Wpf/Controls/Helper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,11 @@ internal static class Helper
/// <summary>
/// Updates the inline diffs view.
/// </summary>
internal static void RenderInlineDiffs(InternalLinesViewer viewer, ICollection<DiffPiece> lines, UIElement source, int contextLineCount)
internal static void RenderInlineDiffs(InternalLinesViewer viewer, ICollection<DiffPiece> lines, IDiffViewer source, int contextLineCount)
{
viewer.Clear();
var diffViewer = source as DiffViewer;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this work also for InlineDiffviewer too? If so, we can make a common interface for both to pass into this instead of UIElement.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been pushed


if (lines == null) return;
if (lines.Any() == false) return;
var disableSubPieces = lines.Count > MaxCount; // For performance.
Expand All @@ -50,6 +52,7 @@ internal static void RenderInlineDiffs(InternalLinesViewer viewer, ICollection<D
{
var c = viewer.Add(null, null, null as string, ChangeType.Unchanged.ToString(), source);
c.Tag = line;

continue;
}

Expand All @@ -65,8 +68,10 @@ internal static void RenderInlineDiffs(InternalLinesViewer viewer, ICollection<D
if (line.SubPieces != null && line.SubPieces.Count > 1 && !disableSubPieces)
{
var details = GetSubPiecesInfo(line, true);

var c = viewer.Add(line.Position, "+", details, changeType.ToString(), source);
c.Tag = line;

hasAdded = true;
}

Expand All @@ -75,8 +80,10 @@ internal static void RenderInlineDiffs(InternalLinesViewer viewer, ICollection<D
if (line.SubPieces != null && line.SubPieces.Count > 1 && !disableSubPieces)
{
var details = GetSubPiecesInfo(line, false);

var c = viewer.Add(line.Position, "-", details, changeType.ToString(), source);
c.Tag = line;

hasAdded = true;
}

Expand Down Expand Up @@ -105,7 +112,7 @@ internal static void RenderInlineDiffs(InternalLinesViewer viewer, ICollection<D
viewer.AdjustScrollView();
}

internal static void InsertLines(InternalLinesViewer panel, List<DiffPiece> lines, bool isOld, UIElement source, int contextLineCount)
internal static void InsertLines(InternalLinesViewer panel, List<DiffPiece> lines, bool isOld, IDiffViewer source, int contextLineCount)
{
if (lines == null || panel == null) return;
var guid = panel.TrackingId = Guid.NewGuid();
Expand All @@ -119,7 +126,7 @@ internal static void InsertLines(InternalLinesViewer panel, List<DiffPiece> line
_ = InsertLinesAsync(guid, panel, lines, isOld, source, contextLineCount);
}

private static async Task InsertLinesAsync(Guid guid, InternalLinesViewer panel, List<DiffPiece> lines, bool isOld, UIElement source, int contextLineCount)
private static async Task InsertLinesAsync(Guid guid, InternalLinesViewer panel, List<DiffPiece> lines, bool isOld, IDiffViewer source, int contextLineCount)
{ // For performance.
if (lines == null || panel == null) return;
var disablePieces = lines.Count > MaxCount;
Expand Down Expand Up @@ -231,7 +238,7 @@ internal static bool GoTo(InternalLinesViewer panel, int lineIndex)
catch (InvalidOperationException)
{
}

return false;
}

Expand Down Expand Up @@ -476,14 +483,17 @@ private static List<KeyValuePair<string, string>> GetSubPiecesInfo(DiffPiece lin
return details;
}

private static void InsertLinesInteral(InternalLinesViewer panel, List<DiffPiece> lines, bool isOld, UIElement source, bool disableSubPieces = false)
private static void InsertLinesInteral(InternalLinesViewer panel, List<DiffPiece> lines, bool isOld, IDiffViewer source, bool disableSubPieces = false)
{
var diffViewer = source as DiffViewer;

foreach (var line in lines)
{
if (line == null)
{
var c = panel.Add(null, null, null as string, ChangeType.Unchanged.ToString(), source);
c.Tag = line;

continue;
}

Expand All @@ -497,8 +507,10 @@ private static void InsertLinesInteral(InternalLinesViewer panel, List<DiffPiece
if (line.SubPieces != null && line.SubPieces.Count > 1 && !disableSubPieces)
{
var details = GetSubPiecesInfo(line, isOld);

var c = panel.Add(line.Position, isOld ? "-" : "+", details, changeType.ToString(), source);
c.Tag = line;

hasAdded = true;
}

Expand Down Expand Up @@ -527,4 +539,4 @@ private static void InsertLinesInteral(InternalLinesViewer panel, List<DiffPiece

panel.AdjustScrollView();
}
}
}
15 changes: 15 additions & 0 deletions DiffPlex.Wpf/Controls/IDiffViewer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;

namespace DiffPlex.Wpf.Controls
{
public interface IDiffViewer
{
bool IsTextWrapEnabled { get; set; }
}

}
15 changes: 14 additions & 1 deletion DiffPlex.Wpf/Controls/InlineDiffViewer.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ namespace DiffPlex.Wpf.Controls;
/// The inline diff control for text.
/// Interaction logic for InlineDiffViewer.xaml
/// </summary>
public partial class InlineDiffViewer : UserControl
public partial class InlineDiffViewer : UserControl, IDiffViewer
{
/// <summary>
/// The property of diff model.
Expand Down Expand Up @@ -58,6 +58,11 @@ public partial class InlineDiffViewer : UserControl
c.ContentPanel.LineNumberWidth = n;
});

/// <summary>
/// The property of text wrapping state.
/// </summary>
public static readonly DependencyProperty IsTextWrapEnabledProperty = RegisterDependencyProperty(nameof(IsTextWrapEnabled), false);

/// <summary>
/// The property of change type symbol foreground brush.
/// </summary>
Expand Down Expand Up @@ -339,6 +344,14 @@ public int LinesContext
set => SetValue(LinesContextProperty, value);
}

[Bindable(true)]
[Category("Appearance")]
public bool IsTextWrapEnabled
{
get => (bool)GetValue(IsTextWrapEnabledProperty);
set => SetValue(IsTextWrapEnabledProperty, value);
}

/// <summary>
/// Sets a new diff model.
/// </summary>
Expand Down
Loading