diff --git a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/Plugin.cs b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/Plugin.cs index 2f833dc..87518ec 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/Plugin.cs +++ b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/Plugin.cs @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . -using System; +using System.Collections.Generic; using System.IO; using System.Linq; using System.Reflection; @@ -35,24 +35,24 @@ namespace QuickLook.Plugin.TextViewer public void Init() { - HighlightingManager hlm = HighlightingManager.Instance; + var hlm = HighlightingManager.Instance; - string assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); + var assemblyPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); if (string.IsNullOrEmpty(assemblyPath)) return; - string syntaxPath = Path.Combine(assemblyPath, "Syntax"); + var syntaxPath = Path.Combine(assemblyPath, "Syntax"); if (!Directory.Exists(syntaxPath)) return; - foreach (string file in Directory.EnumerateFiles(syntaxPath, "*.xshd")) + foreach (var file in Directory.EnumerateFiles(syntaxPath, "*.xshd")) { - string lang = Path.GetFileNameWithoutExtension(file); + var ext = Path.GetFileNameWithoutExtension(file); using (Stream s = File.OpenRead(Path.GetFullPath(file))) - using (XmlTextReader reader = new XmlTextReader(s)) + using (var reader = new XmlTextReader(s)) { - XshdSyntaxDefinition xshd = HighlightingLoader.LoadXshd(reader); - IHighlightingDefinition highlightingDefinition = HighlightingLoader.Load(xshd, hlm); + var xshd = HighlightingLoader.LoadXshd(reader); + var highlightingDefinition = HighlightingLoader.Load(xshd, hlm); if (xshd.Extensions.Count > 0) - hlm.RegisterHighlighting(lang, xshd.Extensions.ToArray(), highlightingDefinition); + hlm.RegisterHighlighting(ext, xshd.Extensions.ToArray(), highlightingDefinition); } } } @@ -62,23 +62,21 @@ namespace QuickLook.Plugin.TextViewer if (Directory.Exists(path)) return false; - const long maxSize = 20 * 1024 * 1024; - if (path.ToLower().EndsWith(".txt")) - return new FileInfo(path).Length <= maxSize; + return true; // if there is a matched highlighting scheme (by file extension), treat it as a plain text file if (HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(path)) != null) - return new FileInfo(path).Length <= maxSize; + return true; - // otherwise, read the first 512KB, check if we can get something. - using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read)) + // otherwise, read the first 16KB, check if we can get something. + using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { - const int bufferLength = 512 * 1024; + const int bufferLength = 16 * 1024; var buffer = new byte[bufferLength]; var size = s.Read(buffer, 0, bufferLength); - return IsText(buffer, size) && new FileInfo(path).Length <= maxSize; + return IsText(buffer, size); } } @@ -93,16 +91,15 @@ namespace QuickLook.Plugin.TextViewer context.ViewerContent = _tvp; context.Title = $"{Path.GetFileName(path)}"; - - context.IsBusy = false; } public void Cleanup() { - _tvp.viewer = null; + _tvp?.Dispose(); + _tvp = null; } - private bool IsText(byte[] buffer, int size) + private static bool IsText(IReadOnlyList buffer, int size) { for (var i = 1; i < size; i++) if (buffer[i - 1] == 0 && buffer[i] == 0) diff --git a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/QuickLook.Plugin.TextViewer.csproj b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/QuickLook.Plugin.TextViewer.csproj index d5bb817..87c07f0 100644 --- a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/QuickLook.Plugin.TextViewer.csproj +++ b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/QuickLook.Plugin.TextViewer.csproj @@ -77,9 +77,7 @@ - - TextViewerPanel.xaml - + @@ -88,12 +86,6 @@ False - - - Designer - MSBuild:Compile - - diff --git a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.cs b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.cs new file mode 100644 index 0000000..6ee63a3 --- /dev/null +++ b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.cs @@ -0,0 +1,140 @@ +// Copyright © 2017 Paddy Xu +// +// This file is part of QuickLook program. +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program. If not, see . + +using System; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Threading; +using ICSharpCode.AvalonEdit; +using ICSharpCode.AvalonEdit.Document; +using ICSharpCode.AvalonEdit.Highlighting; +using QuickLook.Common.Helpers; +using QuickLook.Common.Plugin; +using UtfUnknown; + +namespace QuickLook.Plugin.TextViewer +{ + public class TextViewerPanel : TextEditor, IDisposable + { + private readonly ContextObject _context; + private bool _disposed; + + public TextViewerPanel(string path, ContextObject context) + { + _context = context; + + Background = Brushes.Transparent; + FontSize = 14; + ShowLineNumbers = true; + WordWrap = true; + IsReadOnly = true; + IsManipulationEnabled = true; + + ManipulationInertiaStarting += Viewer_ManipulationInertiaStarting; + ManipulationStarting += Viewer_ManipulationStarting; + ManipulationDelta += Viewer_ManipulationDelta; + + PreviewMouseWheel += Viewer_MouseWheel; + + FontFamily = new FontFamily(TranslationHelper.Get("Editor_FontFamily")); + + LoadFileAsync(path); + } + + public void Dispose() + { + _disposed = true; + } + + private void Viewer_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) + { + e.TranslationBehavior = new InertiaTranslationBehavior + { + InitialVelocity = e.InitialVelocities.LinearVelocity, + DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0) + }; + } + + private void Viewer_MouseWheel(object sender, MouseWheelEventArgs e) + { + e.Handled = true; + + ScrollToVerticalOffset(VerticalOffset - e.Delta); + } + + private void Viewer_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) + { + e.Handled = true; + + var delta = e.DeltaManipulation; + ScrollToVerticalOffset(VerticalOffset - delta.Translation.Y); + } + + private void Viewer_ManipulationStarting(object sender, ManipulationStartingEventArgs e) + { + e.Mode = ManipulationModes.Translate; + } + + private void LoadFileAsync(string path) + { + Task.Run(() => + { + const int maxLength = 50 * 1024 * 1024; + var buffer = new MemoryStream(); + + using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) + { + while (s.Position < s.Length && buffer.Length < maxLength) + { + if (_disposed) + break; + + var lb = new byte[8192]; + var count = s.Read(lb, 0, lb.Length); + buffer.Write(lb, 0, count); + } + } + + if (_disposed) + return; + + _context.Title += " (0 ~ 50MB)"; + + var encoding = CharsetDetector.DetectFromBytes(buffer.GetBuffer()).Detected?.Encoding ?? + Encoding.Default; + + var doc = new TextDocument(encoding.GetString(buffer.GetBuffer())); + doc.SetOwnerThread(Dispatcher.Thread); + + if (_disposed) + return; + + Dispatcher.BeginInvoke(new Action(() => + { + Encoding = encoding; + SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(path)); + Document = doc; + + _context.IsBusy = false; + }), DispatcherPriority.Render); + }); + } + } +} \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.xaml b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.xaml deleted file mode 100644 index 6514b19..0000000 --- a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.xaml +++ /dev/null @@ -1,15 +0,0 @@ - - - - - \ No newline at end of file diff --git a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.xaml.cs b/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.xaml.cs deleted file mode 100644 index d1af201..0000000 --- a/QuickLook.Plugin/QuickLook.Plugin.TextViewer/TextViewerPanel.xaml.cs +++ /dev/null @@ -1,98 +0,0 @@ -// Copyright © 2017 Paddy Xu -// -// This file is part of QuickLook program. -// -// This program is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// This program is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with this program. If not, see . - -using System.IO; -using System.Text; -using System.Windows.Controls; -using System.Windows.Input; -using System.Windows.Media; -using ICSharpCode.AvalonEdit.Highlighting; -using QuickLook.Common.Helpers; -using QuickLook.Common.Plugin; -using UtfUnknown; - -namespace QuickLook.Plugin.TextViewer -{ - /// - /// Interaction logic for TextViewerPanel.xaml - /// - public partial class TextViewerPanel : UserControl - { - public TextViewerPanel(string path, ContextObject context) - { - InitializeComponent(); - - viewer.ManipulationInertiaStarting += Viewer_ManipulationInertiaStarting; - viewer.ManipulationStarting += Viewer_ManipulationStarting; - viewer.ManipulationDelta += Viewer_ManipulationDelta; - - viewer.PreviewMouseWheel += Viewer_MouseWheel; - - viewer.FontFamily = new FontFamily(TranslationHelper.Get("Editor_FontFamily")); - - LoadFile(path); - } - - private void Viewer_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingEventArgs e) - { - e.TranslationBehavior = new InertiaTranslationBehavior - { - InitialVelocity = e.InitialVelocities.LinearVelocity, - DesiredDeceleration = 10.0 * 96.0 / (1000.0 * 1000.0) - }; - } - - private void Viewer_MouseWheel(object sender, MouseWheelEventArgs e) - { - e.Handled = true; - - viewer.ScrollToVerticalOffset(viewer.VerticalOffset - e.Delta); - } - - private void Viewer_ManipulationDelta(object sender, ManipulationDeltaEventArgs e) - { - e.Handled = true; - - var delta = e.DeltaManipulation; - viewer.ScrollToVerticalOffset(viewer.VerticalOffset - delta.Translation.Y); - } - - private void Viewer_ManipulationStarting(object sender, ManipulationStartingEventArgs e) - { - e.ManipulationContainer = this; - e.Mode = ManipulationModes.Translate; - } - - private void LoadFile(string path) - { - using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) - { - const int bufferLength = 1 * 1024 * 1024; - var buffer = new byte[bufferLength]; - s.Read(buffer, 0, bufferLength); - - viewer.Encoding = CharsetDetector.DetectFromBytes(buffer).Detected?.Encoding ?? Encoding.Default; - - s.Position = 0; - viewer.Load(s); - } - - //viewer.Load(path); - viewer.SyntaxHighlighting = HighlightingManager.Instance.GetDefinitionByExtension(Path.GetExtension(path)); - } - } -} \ No newline at end of file