Skip to content
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

Fixes for issues 190, 208, 217, 226, and 243 #247

Merged
merged 8 commits into from
Mar 29, 2017
6 changes: 6 additions & 0 deletions dnGREP.Common/GrepApplicationSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,12 @@ public static class Key
public const string PreviewWindowWrap = "PreviewWindowWrap";
public const string PreviewWindowSize = "PreviewWindowSize";
public const string PreviewWindowPosition = "PreviewWindowPosition";
[DefaultValue(20)]
public const string MaxPathBookmarks = "MaxPathBookmarks";
[DefaultValue(20)]
public const string MaxSearchBookmarks = "MaxSearchBookmarks";
[DefaultValue(10)]
public const string MaxExtensionBookmarks = "MaxExtensionBookmarks";
}

private static GrepSettings instance;
Expand Down
2 changes: 1 addition & 1 deletion dnGREP.Common/Utils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ public static string[] SplitPath(string path)
sb.Append(splitterIndex + subSplitterIndex < path.Length ? path[splitterIndex + subSplitterIndex].ToString() : "");
}
if (!found && !string.IsNullOrWhiteSpace(paths[i]))
output.Add(paths[i]);
output.Add(paths[i].TrimStart());
}
}
return output.ToArray();
Expand Down
17 changes: 12 additions & 5 deletions dnGREP.Engines/GrepEngineBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml;
Expand All @@ -20,6 +21,7 @@ public class GrepEngineBase
protected int linesAfter = 0;
protected double fuzzyMatchThreshold = 0.5;
private GoogleMatch fuzzyMatchEngine = new GoogleMatch();
private bool verboseMatchCount;

public GrepEngineBase() { }

Expand All @@ -42,6 +44,7 @@ public virtual bool Initialize(GrepEngineInitParams param)
this.linesAfter = 0;
}
this.fuzzyMatchThreshold = param.FuzzyMatchThreshold;
verboseMatchCount = GrepSettings.Instance.Get<bool>(GrepSettings.Key.ShowVerboseMatchCount);
return true;
}

Expand Down Expand Up @@ -76,7 +79,8 @@ protected List<GrepSearchResult.GrepMatch> doFuzzySearchMultiline(string text, s
continue;
}

globalMatches.Add(new GrepSearchResult.GrepMatch(0, matchLocation + counter, matchLength));
int lineNumber = verboseMatchCount ? text.Take(matchLocation + counter).Count(c => c == '\n' || c == '\r') + 1 : 0;
globalMatches.Add(new GrepSearchResult.GrepMatch(lineNumber, matchLocation + counter, matchLength));

counter = counter + matchLocation + matchLength;
}
Expand Down Expand Up @@ -273,7 +277,7 @@ public GrepSearchResult.GrepMatch[] getFilePositions(string text, List<XPathPosi

if (xPathPositionsMatch(currPos, positions[i].Path))
{
results[i] = new GrepSearchResult.GrepMatch(0, getAbsoluteCharPosition(lineInfo.LineNumber - 1, lineInfo.LinePosition - 2, text, lineLengths, false), 0);
results[i] = new GrepSearchResult.GrepMatch(lineInfo.LineNumber - 1, getAbsoluteCharPosition(lineInfo.LineNumber - 1, lineInfo.LinePosition - 2, text, lineLengths, false), 0);
}

// If empty element (e.g.<element/>)
Expand Down Expand Up @@ -347,7 +351,8 @@ protected List<GrepSearchResult.GrepMatch> doRegexSearch(string text, string sea
List<GrepSearchResult.GrepMatch> globalMatches = new List<GrepSearchResult.GrepMatch>();
foreach (Match match in Regex.Matches(text, searchPattern, regexOptions))
{
globalMatches.Add(new GrepSearchResult.GrepMatch(0, match.Index, match.Length));
int lineNumber = verboseMatchCount ? text.Take(match.Index).Count(c => c == '\n' || c == '\r') + 1 : 0;
globalMatches.Add(new GrepSearchResult.GrepMatch(lineNumber, match.Index, match.Length));
}

return globalMatches;
Expand Down Expand Up @@ -382,7 +387,8 @@ protected List<GrepSearchResult.GrepMatch> doTextSearchCaseInsensitive(string te
continue;
}

globalMatches.Add(new GrepSearchResult.GrepMatch(0, index, searchText.Length));
int lineNumber = verboseMatchCount? text.Take(index).Count(c => c == '\n' || c == '\r') + 1 : 0;
globalMatches.Add(new GrepSearchResult.GrepMatch(lineNumber, index, searchText.Length));
index++;
}
}
Expand All @@ -408,7 +414,8 @@ protected List<GrepSearchResult.GrepMatch> doTextSearchCaseSensitive(string text
continue;
}

globalMatches.Add(new GrepSearchResult.GrepMatch(0, index, searchText.Length));
int lineNumber = verboseMatchCount ? text.Take(index).Count(c => c == '\n' || c == '\r') + 1 : 0;
globalMatches.Add(new GrepSearchResult.GrepMatch(lineNumber, index, searchText.Length));
index++;
}
}
Expand Down
25 changes: 25 additions & 0 deletions dnGREP.Engines/GrepEnginePlainText.cs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,31 @@ private bool replace(Stream inputStream, Stream outputStream, string searchPatte
string line = null;
int counter = 1;

// use first line to determine eol character(s);
line = readStream.ReadLine(true);
if (line != null)
{
if (line.EndsWith("\r\n"))
{
writeStream.NewLine = "\r\n";
line = line.Substring(0, line.Length - 2);
}
else if (line.EndsWith("\n"))
{
writeStream.NewLine = "\n";
line = line.Substring(0, line.Length - 1);
}
else if (line.EndsWith("\r"))
{
writeStream.NewLine = "\r";
line = line.Substring(0, line.Length - 1);
}

line = replaceMethod(line, searchPattern, replacePattern, searchOptions);
writeStream.WriteLine(line);
counter++;
}

while ((line = readStream.ReadLine()) != null)
{
line = replaceMethod(line, searchPattern, replacePattern, searchOptions);
Expand Down
7 changes: 1 addition & 6 deletions dnGREP.WPF/Dictionaries/Styles.xaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">

<Style x:Key="DefaultStyle">
<Setter Property="Control.FontSize" Value="12"/>
<Setter Property="Control.FontFamily" Value="Microsoft Sans Serif"/>
</Style>

<LinearGradientBrush StartPoint="0,0" EndPoint="0,1" x:Key="GradientBackground">
<GradientStop Color="White" Offset="0" />
Expand All @@ -25,7 +20,7 @@
<Setter Property="Height" Value="23" />
</Style>

<Style x:Key="GrayedOutFilePattern" TargetType="{x:Type TextBlock}" BasedOn="{StaticResource DefaultStyle}">
<Style x:Key="GrayedOutFilePattern" TargetType="{x:Type TextBlock}">
<Style.Setters>
<Setter Property="Foreground" Value="Black"/>
</Style.Setters>
Expand Down
30 changes: 30 additions & 0 deletions dnGREP.WPF/MVHelpers/ObservableGrepSearchResults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,36 @@ public bool CustomEditorConfigured
}
}

private double resultsScale = 1.0;
public double ResultsScale
{
get { return resultsScale; }
set
{
if (value == resultsScale)
return;

resultsScale = value;

base.OnPropertyChanged(new PropertyChangedEventArgs("ResultsScale"));
}
}

private double resultsMenuScale = 1.0;
public double ResultsMenuScale
{
get { return resultsMenuScale; }
set
{
if (value == resultsMenuScale)
return;

resultsMenuScale = value;

base.OnPropertyChanged(new PropertyChangedEventArgs("ResultsMenuScale"));
}
}

public event EventHandler<GrepLineEventArgs> OpenFileLineRequest;
public event EventHandler<GrepResultEventArgs> OpenFileRequest;
public event EventHandler<GrepLineEventArgs> PreviewFileLineRequest;
Expand Down
12 changes: 9 additions & 3 deletions dnGREP.WPF/UserControls/ResultsTree.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
<TreeView x:Name="tvSearchResult" ItemsSource="{Binding}" Grid.Row="3" VirtualizingStackPanel.IsVirtualizing="True"
MouseDoubleClick="tvSearchResult_MouseDoubleClick" PreviewKeyDown="treeKeyDown" SelectedItemChanged="tvSearchResults_SelectedChanged"
HorizontalContentAlignment="Stretch">
<TreeView.LayoutTransform>
<ScaleTransform ScaleX="{Binding ResultsScale}" ScaleY="{Binding ResultsScale}" />
</TreeView.LayoutTransform>
<TreeView.Resources>
<LinearGradientBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" EndPoint="0,1" StartPoint="0,0">
<GradientStop Color="#FFD9F4FF" Offset="0"/>
Expand All @@ -29,7 +32,7 @@
<HierarchicalDataTemplate DataType="{x:Type my:FormattedGrepResult}" ItemsSource="{Binding FormattedLines}" >
<StackPanel Orientation="Vertical">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding Icon}"/>
<Image Source="{Binding Icon}" Height="16" />
<TextBlock Text="{Binding Label}" Margin="3,0,0,0"/>
</StackPanel>
<Viewbox Width="20" Height="20" Visibility="{Binding IsLoading, Converter={StaticResource BooleanToVisibilityConverter}}">
Expand Down Expand Up @@ -65,14 +68,17 @@
</Style.Triggers>
</Style>
</WrapPanel.Resources>
<TextBlock Margin="-3" Width="{Binding LineNumberColumnWidth}" Text="{Binding FormattedLineNumber}"/>
<TextBlock Margin="-3" Width="{Binding LineNumberColumnWidth}" Text="{Binding FormattedLineNumber}" TextAlignment="Right" Padding="0,0,3,0"/>
<my:InlineTextBlock Margin="3,0,0,0" InlineCollection="{Binding FormattedText}" FontFamily="Consolas"/>
</WrapPanel>
</Border>
</DataTemplate>
</TreeView.Resources>
<TreeView.ContextMenu>
<ContextMenu Opened="tvContexMenuOpening">
<ContextMenu.LayoutTransform>
<ScaleTransform ScaleX="{Binding ResultsMenuScale}" ScaleY="{Binding ResultsMenuScale}" />
</ContextMenu.LayoutTransform>
<MenuItem Header="Open" Click="btnOpenFile_Click"/>
<MenuItem Visibility="{Binding CustomEditorConfigured, Converter={StaticResource BooleanToVisibilityConverter}}" Header="Open with custom editor" Click="btnOpenFileCustomEditor_Click"/>
<MenuItem Header="Open containing folder" Click="btnOpenContainingFolder_Click"/>
Expand All @@ -83,6 +89,7 @@
<MenuItem Header="Exclude from results" Click="btnExclude_Click"/>
<MenuItem Header="Expand all" Click="btnExpandAll_Click"/>
<MenuItem Header="Collapse all" Click="btnCollapseAll_Click"/>
<MenuItem Header="Reset zoom" Click="btnResetZoom_Click"/>
</ContextMenu>
</TreeView.ContextMenu>
<TreeView.ItemContainerStyle>
Expand All @@ -101,7 +108,6 @@
Event="RequestBringIntoView"
Handler="tvSearchResult_RequestBringIntoView"/>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}"/>
<Setter Property="FontSize" Value="12"/>
<Setter Property="BorderThickness" Value="1.5"/>
<Setter Property="Padding" Value="1"/>
<Setter Property="Template">
Expand Down
138 changes: 138 additions & 0 deletions dnGREP.WPF/UserControls/ResultsTree.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ public ResultsTree()
{
InitializeComponent();
this.DataContextChanged += ResultsTree_DataContextChanged;

tvSearchResult.PreviewMouseWheel += TvSearchResult_PreviewMouseWheel;
tvSearchResult.PreviewTouchDown += TvSearchResult_PreviewTouchDown;
tvSearchResult.PreviewTouchMove += TvSearchResult_PreviewTouchMove;
tvSearchResult.PreviewTouchUp += TvSearchResult_PreviewTouchUp;
Copy link
Contributor

Choose a reason for hiding this comment

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

Curious, what's the "tv" prefix stand for?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tree View, I suspect. tvSearchResult was already the name of the control.

Copy link
Contributor

Choose a reason for hiding this comment

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

Gotcha. Looks like the original author was used to hungarian notation, which is not a good fit for C#/XAML, in my experience. Feel free to avoid it if you like. No need to change this PR.

}

void ResultsTree_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
Expand Down Expand Up @@ -210,6 +215,139 @@ private void tvSearchResults_SelectedChanged(object sender, RoutedPropertyChange

#endregion

#region Zoom

private Dictionary<int, Point> touchIds = new Dictionary<int, Point>();

private void TvSearchResult_PreviewTouchDown(object sender, TouchEventArgs e)
{
IInputElement ctrl = sender as IInputElement;
if (ctrl != null && !touchIds.ContainsKey(e.TouchDevice.Id))
{
var pt = e.GetTouchPoint(ctrl).Position;
touchIds.Add(e.TouchDevice.Id, pt);
}
}

private void TvSearchResult_PreviewTouchUp(object sender, TouchEventArgs e)
{
if (touchIds.ContainsKey(e.TouchDevice.Id))
touchIds.Remove(e.TouchDevice.Id);
}

private void TvSearchResult_PreviewTouchMove(object sender, TouchEventArgs e)
{
IInputElement ctrl = sender as IInputElement;

// sometimes a PreviewTouchUp event is lost when the user is on the scrollbar or edge of the window
// if our captured touches do not match the scrollviewer, resynch to the scrollviewer
ScrollViewer scrollViewer = e.OriginalSource as ScrollViewer;
if (scrollViewer != null)
{
var svTouches = scrollViewer.TouchesCaptured.Select(t => t.Id);
var myTouches = touchIds.Keys.Select(k => k);
bool equal = svTouches.OrderBy(i => i).SequenceEqual(myTouches.OrderBy(i => i));

if (!equal)
{
touchIds.Clear();
foreach (var t in scrollViewer.TouchesCaptured)
{
var pt = t.GetTouchPoint(ctrl).Position;
touchIds.Add(t.Id, pt);
}
}
}

if (inputData != null && inputData.Count > 0 &&
ctrl != null && touchIds.ContainsKey(e.TouchDevice.Id) && touchIds.Count == 2)
{
var pNew = e.GetTouchPoint(ctrl).Position;

var otherTouchId = touchIds.Keys.Where(k => k != e.TouchDevice.Id).FirstOrDefault();
var p0 = touchIds[otherTouchId];
var p1 = touchIds[e.TouchDevice.Id];

var dx = p1.X - p0.X;
var dy = p1.Y - p0.Y;
var dist1 = dx * dx + dy * dy;

dx = pNew.X - p0.X;
dy = pNew.Y - p0.Y;
var dist2 = dx * dx + dy * dy;

if (Math.Abs(dist2 - dist1) > 200)
{
if (dist1 < dist2 && inputData.ResultsScale < 2.0)
{
inputData.ResultsScale *= 1.005;
}

if (dist1 > dist2 && inputData.ResultsScale > 0.8)
{
inputData.ResultsScale /= 1.005;
}

if (dist1 < dist2 && inputData.ResultsMenuScale < 1.5)
{
inputData.ResultsMenuScale *= 1.0025;
}

if (dist1 > dist2 && inputData.ResultsMenuScale > 1.0)
{
inputData.ResultsMenuScale /= 1.0025;
}

e.Handled = true;
}

// and update position for this touch
touchIds[e.TouchDevice.Id] = pNew;
}
}

private void TvSearchResult_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
bool handle = (Keyboard.Modifiers & ModifierKeys.Control) > 0 &&
inputData != null && inputData.Count > 0;

if (!handle)
return;

if (e.Delta > 0 && inputData.ResultsScale < 2.0)
{
inputData.ResultsScale *= 1.05;
}

if (e.Delta < 0 && inputData.ResultsScale > 0.8)
{
inputData.ResultsScale /= 1.05;
}

if (e.Delta > 0 && inputData.ResultsMenuScale < 1.5)
{
inputData.ResultsMenuScale *= 1.025;
}

if (e.Delta < 0 && inputData.ResultsMenuScale > 1.0)
{
inputData.ResultsMenuScale /= 1.025;
}

e.Handled = true;
}

private void btnResetZoom_Click(object sender, RoutedEventArgs e)
{
if (inputData != null)
{
inputData.ResultsScale = 1.0;
inputData.ResultsMenuScale = 1.0;
}
}

#endregion

#region DragDropEvents
private static UIElement _draggedElt;
private static bool _isMouseDown = false;
Expand Down