Compare commits

..

28 Commits
0.2.5 ... 0.3.0

Author SHA1 Message Date
Paddy Xu
04b9f7b5c1 update readme 2017-08-13 01:08:41 +03:00
Paddy Xu
1d7c95a822 update tile images 2017-08-13 00:20:01 +03:00
Paddy Xu
e4ab7d0a32 new icons 2017-08-12 23:31:50 +03:00
Paddy Xu
6027a387b0 Fix ZoomToFit 2017-08-12 21:21:16 +03:00
Paddy Xu
3e2336a63d Fix #63: add Netpbm formats 2017-08-12 21:20:57 +03:00
Paddy Xu
1260afb2c4 Merge pull request #67 from xupefei/fluent
Redesigned UI according to the Fluent design system
2017-08-12 20:58:35 +03:00
Paddy Xu
dbee403b59 Merge branch 'master' into fluent 2017-08-12 20:55:33 +03:00
Paddy Xu
7676d5867b all operations pass though Pipe 2017-08-12 18:20:29 +03:00
Paddy Xu
6bae00361b minor zoom improvements 2017-08-12 01:19:10 +03:00
Paddy Xu
1c18890fbf add Segoe MDL2 font as assets: this font allows editable embedding 2017-08-11 23:16:35 +03:00
Paddy Xu
8e400e7ee5 fix blur coordinate error 2017-08-11 20:14:45 +03:00
Paddy Xu
cd9b713c41 Finish ViedoViewer (except volume slider) 2017-08-11 00:29:24 +03:00
Paddy Xu
9ce0776d53 almost done videoviewer. WIP modify app style to per-window one. 2017-08-10 01:15:32 +03:00
Paddy Xu
346ec59ea5 Merge pull request #64 from KrasnayaPloshchad/patch-3
Minor fix for zh-TW translation
2017-08-10 01:14:50 +03:00
Krasnaya Ploshchad’
bc533f3d18 Minor fix for zh-TW translation 2017-08-09 19:05:05 +08:00
Paddy Xu
efaca311fc wip videoviewer 2017-08-08 23:19:46 +03:00
Paddy Xu
2b3338cc43 dark theme; wip videopleyer 2017-08-06 23:33:01 +03:00
Paddy Xu
56cb31fd2a finish auto-hide 2017-08-06 21:01:02 +03:00
Paddy Xu
5b97e7ef60 wip 2 2017-08-06 17:27:30 +03:00
Paddy Xu
3a20245304 wip 2017-08-06 15:06:55 +03:00
Paddy Xu
768425ad0f add inner padding 2017-08-06 00:39:41 +03:00
Paddy Xu
60cd782c64 WIP: more new styles 2017-08-06 00:17:51 +03:00
Paddy Xu
8d59e7138c WIP #56: adjust shadows; add Gaussian blur, try out the new InfoPanel 2017-08-04 22:07:42 +03:00
Paddy Xu
e79de6c36d use native rotate method suggested by @dlemstra 2017-08-04 22:07:02 +03:00
Paddy Xu
810de851ff Merge pull request #60 from KrasnayaPloshchad/patch-3
Improve font family for zh-TW locale
2017-08-04 18:58:58 +03:00
Krasnaya Ploshchad’
15af258db0 Improve zh-TW font family
zh-TW locale generally does not use SimSun, use MingLiU instead.
2017-08-04 23:23:24 +08:00
Paddy Xu
15d94d2c4b Merge pull request #59 from KrasnayaPloshchad/patch-1
TextViewer: Add Korean fonts used for Korean locale
2017-08-04 16:50:59 +03:00
Krasnaya Ploshchad’
dae2a3a512 Add Korean fonts 2017-08-04 21:05:55 +08:00
161 changed files with 2311 additions and 2111 deletions

View File

@@ -14,6 +14,8 @@
<Resources>
<Resource Language="en-us" />
<Resource uap:Scale="100" />
<Resource uap:Scale="125" />
<Resource uap:Scale="150" />
<Resource uap:Scale="200" />
<Resource uap:Scale="400" />
</Resources>

View File

@@ -13,6 +13,8 @@
<Resources>
<Resource Language="en-us" />
<Resource uap:Scale="100" />
<Resource uap:Scale="125" />
<Resource uap:Scale="150" />
<Resource uap:Scale="200" />
<Resource uap:Scale="400" />
</Resources>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 811 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.6 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 786 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 465 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 592 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 702 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 854 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 584 B

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.6 KiB

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -1,24 +1,40 @@
Assets\LargeTile.scale-100.png
Assets\LargeTile.scale-125.png
Assets\LargeTile.scale-150.png
Assets\LargeTile.scale-200.png
Assets\LargeTile.scale-400.png
Assets\SmallTile.scale-100.png
Assets\SmallTile.scale-125.png
Assets\SmallTile.scale-150.png
Assets\SmallTile.scale-200.png
Assets\SmallTile.scale-400.png
Assets\Square150x150Logo.scale-100.png
Assets\Square150x150Logo.scale-125.png
Assets\Square150x150Logo.scale-150.png
Assets\Square150x150Logo.scale-200.png
Assets\Square150x150Logo.scale-400.png
Assets\Square44x44Logo.altform-unplated_targetsize-16.png
Assets\Square44x44Logo.altform-unplated_targetsize-256.png
Assets\Square44x44Logo.altform-unplated_targetsize-24.png
Assets\Square44x44Logo.altform-unplated_targetsize-32.png
Assets\Square44x44Logo.altform-unplated_targetsize-48.png
Assets\Square44x44Logo.altform-unplated_targetsize-256.png
Assets\Square44x44Logo.scale-100.png
Assets\Square44x44Logo.scale-125.png
Assets\Square44x44Logo.scale-150.png
Assets\Square44x44Logo.scale-200.png
Assets\Square44x44Logo.scale-400.png
Assets\Square44x44Logo.targetsize-16.png
Assets\Square44x44Logo.targetsize-256.png
Assets\Square44x44Logo.targetsize-24.png
Assets\Square44x44Logo.targetsize-32.png
Assets\Square44x44Logo.targetsize-48.png
Assets\Square44x44Logo.targetsize-256.png
Assets\storelogo.scale-100.png
Assets\storelogo.scale-125.png
Assets\storelogo.scale-150.png
Assets\storelogo.scale-200.png
Assets\storelogo.scale-400.png
Assets\Wide310x150Logo.scale-100.png
Assets\Wide310x150Logo.scale-125.png
Assets\Wide310x150Logo.scale-150.png
Assets\Wide310x150Logo.scale-200.png
Assets\Wide310x150Logo.scale-400.png

View File

@@ -20,6 +20,7 @@ using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows.Controls;
using QuickLook.ExtensionMethods;
using SharpCompress.Archives;
using SharpCompress.Common;
using SharpCompress.Readers;
@@ -88,8 +89,9 @@ namespace QuickLook.Plugin.ArchiveViewer
archiveCount.Content =
$"{_type} archive{t}";
archiveSizeC.Content = $"Compressed size {_totalZippedSize.ToPrettySize(2)}";
archiveSizeU.Content = $"Uncompressed size {sizeU.ToPrettySize(2)}";
archiveSizeC.Content =
$"Compressed size {((long) _totalZippedSize).ToPrettySize(2)}";
archiveSizeU.Content = $"Uncompressed size {((long) sizeU).ToPrettySize(2)}";
}
private void LoadItemsFromArchive(string path)
@@ -99,7 +101,7 @@ namespace QuickLook.Plugin.ArchiveViewer
// ReaderFactory is slow... so limit its usage
string[] useReader = {".tar.gz", ".tgz", ".tar.bz2", ".tar.lz", ".tar.xz"};
if (useReader.Any(i => path.EndsWith(i)))
if (useReader.Any(path.ToLower().EndsWith))
{
var reader = ReaderFactory.Open(stream, new ChardetReaderOptions());

View File

@@ -19,6 +19,7 @@ using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using QuickLook.ExtensionMethods;
namespace QuickLook.Plugin.ArchiveViewer
{
@@ -77,7 +78,7 @@ namespace QuickLook.Plugin.ArchiveViewer
var size = (ulong) values[0];
var isFolder = (bool) values[1];
return isFolder ? "" : size.ToPrettySize(2);
return isFolder ? "" : ((long) size).ToPrettySize(2);
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)

View File

@@ -49,29 +49,5 @@ namespace QuickLook.Plugin.ArchiveViewer
}
return foundElement;
}
public static string ToPrettySize(this ulong value, int decimalPlaces = 0)
{
const long OneKb = 1024;
const long OneMb = OneKb * 1024;
const long OneGb = OneMb * 1024;
const long OneTb = OneGb * 1024;
var asTb = Math.Round((double) value / OneTb, decimalPlaces);
var asGb = Math.Round((double) value / OneGb, decimalPlaces);
var asMb = Math.Round((double) value / OneMb, decimalPlaces);
var asKb = Math.Round((double) value / OneKb, decimalPlaces);
var chosenValue = asTb > 1
? $"{asTb} TB"
: asGb > 1
? $"{asGb} GB"
: asMb > 1
? $"{asMb} MB"
: asKb > 1
? $"{asKb} KB"
: $"{Math.Round((double) value, decimalPlaces)} bytes";
return chosenValue;
}
}
}

View File

@@ -17,12 +17,16 @@
using System;
using System.IO;
using System.Linq;
using System.Windows;
namespace QuickLook.Plugin.ArchiveViewer
{
public class Plugin : IViewer
{
private static readonly string[] Extensions =
{".rar", ".zip", ".tar", ".tgz", ".gz", ".bz2", ".lz", ".xz", ".7z"};
private ArchiveInfoPanel _panel;
public int Priority => 0;
@@ -34,25 +38,7 @@ namespace QuickLook.Plugin.ArchiveViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".rar":
case ".zip":
case ".tar":
case ".tgz":
case ".gz":
case ".bz2":
case ".lz":
case ".xz":
case ".7z":
return true;
default:
return false;
}
return !Directory.Exists(path) && Extensions.Any(path.ToLower().EndsWith);
}
public void Prepare(string path, ContextObject context)

View File

@@ -34,10 +34,7 @@ namespace QuickLook.Plugin.CsvViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
return Path.GetExtension(path).ToLower() == ".csv";
return !Directory.Exists(path) && path.ToLower().EndsWith(".csv");
}
public void Prepare(string path, ContextObject context)

View File

@@ -1,63 +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 <http://www.gnu.org/licenses/>.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace QuickLook.Plugin.HtmlViewer
{
internal static class DpiHelper
{
public enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90
}
public const float DEFAULT_DPI = 96;
public static Dpi GetCurrentDpi()
{
var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc();
var dpi = new Dpi
{
HorizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX),
VerticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY)
};
return dpi;
}
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
}
internal class Dpi
{
public float HorizontalDpi { get; set; }
public float VerticalDpi { get; set; }
}
}

View File

@@ -17,6 +17,7 @@
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Threading;
@@ -24,6 +25,8 @@ namespace QuickLook.Plugin.HtmlViewer
{
public class Plugin : IViewer
{
private static readonly string[] Extensions = {".mht", ".mhtml", ".htm", ".html"};
private WebpagePanel _panel;
public int Priority => int.MaxValue;
@@ -36,27 +39,12 @@ namespace QuickLook.Plugin.HtmlViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".mht":
case ".mhtml":
case ".html":
case ".htm":
return true;
default:
return false;
}
return !Directory.Exists(path) && Extensions.Any(path.ToLower().EndsWith);
}
public void Prepare(string path, ContextObject context)
{
context.PreferredSize = new Size(1000, 600);
context.CanFocus = true;
}
public void View(string path, ContextObject context)

View File

@@ -72,7 +72,6 @@
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<Compile Include="DpiHelpers.cs" />
<Compile Include="WpfBrowserWrapper.cs" />
<Page Include="WebpagePanel.xaml">
<Generator>MSBuild:Compile</Generator>

View File

@@ -20,6 +20,7 @@ using System.IO;
using System.Text;
using System.Windows.Controls;
using System.Windows.Threading;
using QuickLook.Helpers;
namespace QuickLook.Plugin.HtmlViewer
{
@@ -32,7 +33,7 @@ namespace QuickLook.Plugin.HtmlViewer
{
InitializeComponent();
browser.Zoom = (int) (100 * DpiHelper.GetCurrentDpi().HorizontalDpi / DpiHelper.DEFAULT_DPI);
browser.Zoom = (int) (100 * DpiHelper.GetCurrentScaleFactor().Vertical);
}
public void Dispose()

View File

@@ -17,12 +17,22 @@
using System;
using System.IO;
using System.Linq;
using System.Windows;
namespace QuickLook.Plugin.IPreviewHandlers
{
public class Plugin : IViewer
{
private static readonly string[] Extensions =
{
".doc", ".docx", ".docm",
".xls", ".xlsx", ".xlsm", ".xlsb",
/*".vsd", ".vsdx",*/
".ppt", ".pptx",
".odt", ".ods", ".odp"
};
private PreviewPanel _panel;
public int Priority => int.MaxValue;
@@ -37,29 +47,8 @@ namespace QuickLook.Plugin.IPreviewHandlers
if (Directory.Exists(path))
return false;
switch (Path.GetExtension(path).ToLower())
{
// Word
case ".doc":
case ".docx":
case ".docm":
// Excel
case ".xls":
case ".xlsx":
case ".xlsm":
case ".xlsb":
// Visio Viewer will not quit after preview, which cause serious memory issue
//case ".vsd":
//case ".vsdx":
// PowerPoint
case ".ppt":
case ".pptx":
// OpenDocument
case ".odt":
case ".ods":
case ".odp":
return PreviewHandlerHost.GetPreviewHandlerGUID(path) != Guid.Empty;
}
if (Extensions.Any(path.ToLower().EndsWith))
return PreviewHandlerHost.GetPreviewHandlerGUID(path) != Guid.Empty;
return false;
}

View File

@@ -17,6 +17,7 @@
using System;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Threading;
@@ -36,7 +37,7 @@ namespace QuickLook.Plugin.IPreviewHandlers
public void Dispose()
{
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
presenter.Child = null;
presenter?.Dispose();
@@ -48,7 +49,7 @@ namespace QuickLook.Plugin.IPreviewHandlers
public void PreviewFile(string file, ContextObject context)
{
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
Application.Current.Dispatcher.BeginInvoke(new Action(() =>
{
_control = new PreviewHandlerHost();
presenter.Child = _control;

View File

@@ -21,6 +21,7 @@ using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using LibAPNG;
using QuickLook.Helpers;
namespace QuickLook.Plugin.ImageViewer.AnimatedImage
{
@@ -99,7 +100,7 @@ namespace QuickLook.Plugin.ImageViewer.AnimatedImage
var bitmap = new RenderTargetBitmap(
header.Width, header.Height,
96, 96,
DpiHelper.DefaultDpi, DpiHelper.DefaultDpi,
PixelFormats.Pbgra32);
bitmap.Render(visual);
return bitmap;

View File

@@ -33,18 +33,7 @@ namespace QuickLook.Plugin.ImageViewer.AnimatedImage
using (var image = new MagickImage(path))
{
switch (image.Orientation)
{
case OrientationType.RightTop:
image.Rotate(90);
break;
case OrientationType.BottomRight:
image.Rotate(180);
break;
case OrientationType.LeftBotom:
image.Rotate(270);
break;
}
image.AutoOrient();
animator.KeyFrames.Add(new DiscreteObjectKeyFrame(image.ToBitmapSource(), TimeSpan.Zero));
animator.Duration = Duration.Forever;

View File

@@ -9,6 +9,13 @@
x:Name="imagePanel"
d:DesignHeight="300" d:DesignWidth="300">
<Grid>
<Rectangle Visibility="{Binding BackgroundVisibility, ElementName=imagePanel}">
<Rectangle.Fill>
<ImageBrush x:Name="backgroundBrush" ImageSource="Resources/background.png" AlignmentY="Top"
Viewport="0,0,32,32"
ViewportUnits="Absolute" Stretch="UniformToFill" TileMode="Tile" />
</Rectangle.Fill>
</Rectangle>
<ScrollViewer x:Name="viewPanel" BorderThickness="0" HorizontalScrollBarVisibility="Auto"
VerticalScrollBarVisibility="Auto" Focusable="False" IsManipulationEnabled="True">
<animatedImage:AnimatedImage x:Name="viewPanelImage" Stretch="None"

View File

@@ -28,6 +28,7 @@ using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;
using QuickLook.Annotations;
using QuickLook.Helpers;
namespace QuickLook.Plugin.ImageViewer
{
@@ -36,6 +37,7 @@ namespace QuickLook.Plugin.ImageViewer
/// </summary>
public partial class ImagePanel : UserControl, INotifyPropertyChanged, IDisposable
{
private Visibility _backgroundVisibility = Visibility.Visible;
private Point? _dragInitPos;
private Uri _imageSource;
private DateTime _lastZoomTime = DateTime.MinValue;
@@ -46,11 +48,17 @@ namespace QuickLook.Plugin.ImageViewer
private double _zoomFactor = 1d;
private bool _zoomToFit = true;
private double _zoomToFitFactor;
public ImagePanel()
{
InitializeComponent();
var scale = DpiHelper.GetCurrentScaleFactor();
backgroundBrush.Viewport = new Rect(new Size(
backgroundBrush.ImageSource.Width / scale.Horizontal,
backgroundBrush.ImageSource.Height / scale.Vertical));
SizeChanged += ImagePanel_SizeChanged;
viewPanel.PreviewMouseWheel += ViewPanel_PreviewMouseWheel;
@@ -82,6 +90,16 @@ namespace QuickLook.Plugin.ImageViewer
}
}
public Visibility BackgroundVisibility
{
get => _backgroundVisibility;
set
{
_backgroundVisibility = value;
OnPropertyChanged();
}
}
public double MinZoomFactor
{
get => _minZoomFactor;
@@ -102,6 +120,16 @@ namespace QuickLook.Plugin.ImageViewer
}
}
public double ZoomToFitFactor
{
get => _zoomToFitFactor;
private set
{
_zoomToFitFactor = value;
OnPropertyChanged();
}
}
public double ZoomFactor
{
get => _zoomFactor;
@@ -173,7 +201,7 @@ namespace QuickLook.Plugin.ImageViewer
var newZoom = ZoomFactor + ZoomFactor * (delta.Scale.X - 1);
Zoom(newZoom, false);
Zoom(newZoom);
viewPanel.ScrollToHorizontalOffset(viewPanel.HorizontalOffset - delta.Translation.X);
viewPanel.ScrollToVerticalOffset(viewPanel.VerticalOffset - delta.Translation.Y);
@@ -208,8 +236,6 @@ namespace QuickLook.Plugin.ImageViewer
var delta = _dragInitPos.Value - e.GetPosition(viewPanel);
Debug.WriteLine(_dragInitPos.Value);
viewPanel.ScrollToHorizontalOffset(delta.X);
viewPanel.ScrollToVerticalOffset(delta.Y);
}
@@ -231,7 +257,7 @@ namespace QuickLook.Plugin.ImageViewer
// zoom
var newZoom = ZoomFactor + ZoomFactor * e.Delta / 120 * 0.1;
Zoom(newZoom, false);
Zoom(newZoom);
}
public Size GetScrollSize()
@@ -258,28 +284,39 @@ namespace QuickLook.Plugin.ImageViewer
var factor = Math.Min(viewPanel.ActualWidth / viewPanelImage.Source.Width,
viewPanel.ActualHeight / viewPanelImage.Source.Height);
Zoom(factor, true);
ZoomToFitFactor = factor;
Zoom(factor, false, true);
}
public void ResetZoom()
{
Zoom(1d, false, true);
Zoom(1d, true);
}
public void Zoom(double factor, bool toFit, bool suppressEvent = false)
public void Zoom(double factor, bool suppressEvent = false, bool isToFit = false)
{
if (viewPanelImage.Source == null)
return;
if (ZoomFactor < ZoomToFitFactor && factor > ZoomToFitFactor
|| ZoomFactor > ZoomToFitFactor && factor < ZoomToFitFactor)
{
factor = ZoomToFitFactor;
ZoomToFit = true;
}
else
{
if (!isToFit)
ZoomToFit = false;
}
factor = Math.Max(factor, MinZoomFactor);
factor = Math.Min(factor, MaxZoomFactor);
ZoomFactor = factor;
if (!toFit)
ZoomToFit = false;
var position = toFit
var position = ZoomToFit
? new Point(viewPanelImage.Source.Width / 2, viewPanelImage.Source.Height / 2)
: Mouse.GetPosition(viewPanelImage);

View File

@@ -25,7 +25,7 @@ namespace QuickLook.Plugin.ImageViewer
{
public class Plugin : IViewer
{
private static readonly string[] _formats =
private static readonly string[] Formats =
{
// camera raw
".3fr", ".ari", ".arw", ".bay", ".crw", ".cr2", ".cap", ".data", ".dcs", ".dcr", ".dng", ".drf", ".eip",
@@ -34,7 +34,7 @@ namespace QuickLook.Plugin.ImageViewer
".tif", ".x3f",
// normal
".bmp", ".ico", ".icon", ".jpg", ".jpeg", ".psd", ".svg", ".wdp", ".tif", ".tiff", ".tga",
".webp",
".webp", ".pbm", ".pgm", ".ppm", ".pnm",
// animated
".png", ".apng", ".gif"
};
@@ -51,10 +51,7 @@ namespace QuickLook.Plugin.ImageViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
return _formats.Contains(Path.GetExtension(path).ToLower());
return !Directory.Exists(path) && Formats.Any(path.ToLower().EndsWith);
}
public void Prepare(string path, ContextObject context)
@@ -67,6 +64,9 @@ namespace QuickLook.Plugin.ImageViewer
context.PreferredSize = new Size(1024, 768);
Directory.SetCurrentDirectory(App.AppPath);
context.TitlebarOverlap = true;
context.TitlebarAutoHide = true;
}
public void View(string path, ContextObject context)

View File

@@ -112,6 +112,7 @@
<Content Include="dcraw.exe">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Resource Include="Resources\background.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -17,6 +17,7 @@
using System;
using System.IO;
using System.Linq;
using System.Windows;
using System.Windows.Threading;
using MsgReader;
@@ -27,7 +28,7 @@ namespace QuickLook.Plugin.MailViewer
public class Plugin : IViewer
{
private WebpagePanel _panel;
private string tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
private string _tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
public int Priority => int.MaxValue;
public bool AllowsTransparency => false;
@@ -38,18 +39,7 @@ namespace QuickLook.Plugin.MailViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".eml":
case ".msg":
return true;
default:
return false;
}
return !Directory.Exists(path) && new[] {".eml", ".msg"}.Any(path.ToLower().EndsWith);
}
public void Prepare(string path, ContextObject context)
@@ -74,18 +64,18 @@ namespace QuickLook.Plugin.MailViewer
_panel?.Dispose();
_panel = null;
if (Directory.Exists(tmpDir))
Directory.Delete(tmpDir, true);
if (Directory.Exists(_tmpDir))
Directory.Delete(_tmpDir, true);
}
private string ExtractMailBody(string path)
{
tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(tmpDir);
_tmpDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
Directory.CreateDirectory(_tmpDir);
var msg = new Reader();
var files = msg.ExtractToFolder(path, tmpDir, true);
var files = msg.ExtractToFolder(path, _tmpDir, true);
if (files.Length > 0 && !string.IsNullOrEmpty(files[0]))
return files[0];

View File

@@ -17,6 +17,7 @@
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Threading;
@@ -37,26 +38,12 @@ namespace QuickLook.Plugin.MarkdownViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
switch (Path.GetExtension(path).ToLower())
{
case ".markdown":
case ".md":
case ".rmd":
return true;
default:
return false;
}
return !Directory.Exists(path) && new[] {".md", ".rmd", ".maekdown"}.Any(path.ToLower().EndsWith);
}
public void Prepare(string path, ContextObject context)
{
context.PreferredSize = new Size(1000, 600);
context.CanFocus = true;
}
public void View(string path, ContextObject context)

View File

@@ -1,63 +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 <http://www.gnu.org/licenses/>.
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace QuickLook.Plugin.PDFViewer
{
internal static class DpiHelper
{
public enum DeviceCap
{
/// <summary>
/// Logical pixels inch in X
/// </summary>
LOGPIXELSX = 88,
/// <summary>
/// Logical pixels inch in Y
/// </summary>
LOGPIXELSY = 90
}
public const float DEFAULT_DPI = 96;
public static Dpi GetCurrentDpi()
{
var g = Graphics.FromHwnd(IntPtr.Zero);
var desktop = g.GetHdc();
var dpi = new Dpi
{
HorizontalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSX),
VerticalDpi = GetDeviceCaps(desktop, (int) DeviceCap.LOGPIXELSY)
};
return dpi;
}
[DllImport("gdi32.dll", CharSet = CharSet.Auto, SetLastError = true, ExactSpelling = true)]
public static extern int GetDeviceCaps(IntPtr hDC, int nIndex);
}
internal class Dpi
{
public float HorizontalDpi { get; set; }
public float VerticalDpi { get; set; }
}
}

View File

@@ -1,80 +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 <http://www.gnu.org/licenses/>.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Imaging;
namespace QuickLook.Plugin.PDFViewer
{
public static class Extensions
{
public static void ForEach<T>(this IEnumerable<T> enumeration, Action<T> action)
{
foreach (var item in enumeration)
action(item);
}
public static T GetDescendantByType<T>(this Visual element) where T : class
{
if (element == null)
return default(T);
if (element.GetType() == typeof(T))
return element as T;
T foundElement = null;
(element as FrameworkElement)?.ApplyTemplate();
for (var i = 0; i < VisualTreeHelper.GetChildrenCount(element); i++)
{
var visual = VisualTreeHelper.GetChild(element, i) as Visual;
foundElement = visual.GetDescendantByType<T>();
if (foundElement != null)
break;
}
return foundElement;
}
public static BitmapSource ToBitmapSource(this Bitmap source)
{
BitmapSource bs = null;
try
{
var data = source.LockBits(new Rectangle(0, 0, source.Width, source.Height),
ImageLockMode.ReadOnly, source.PixelFormat);
bs = BitmapSource.Create(source.Width, source.Height, source.HorizontalResolution,
source.VerticalResolution, PixelFormats.Bgr24, null,
data.Scan0, data.Stride * source.Height, data.Stride);
source.UnlockBits(data);
bs.Freeze();
}
catch
{
// ignored
}
return bs;
}
}
}

View File

@@ -19,6 +19,7 @@ using System;
using System.Drawing;
using System.Drawing.Imaging;
using System.Runtime.InteropServices;
using QuickLook.Helpers;
namespace QuickLook.Plugin.PDFViewer
{
@@ -37,9 +38,9 @@ namespace QuickLook.Plugin.PDFViewer
else
NativeMethods.BoundPage_32(document, page, ref pageBound);
var currentDpi = DpiHelper.GetCurrentDpi();
var zoomX = zoomFactor * (currentDpi.HorizontalDpi / DpiHelper.DEFAULT_DPI);
var zoomY = zoomFactor * (currentDpi.VerticalDpi / DpiHelper.DEFAULT_DPI);
var scale = DpiHelper.GetCurrentScaleFactor();
var zoomX = zoomFactor * scale.Horizontal;
var zoomY = zoomFactor * scale.Vertical;
// gets the size of the page and multiplies it with zoom factors
var width = (int) (pageBound.Width * zoomX);
@@ -119,7 +120,7 @@ namespace QuickLook.Plugin.PDFViewer
else
NativeMethods.DropPixmap_32(context, pix);
bmp.SetResolution(currentDpi.HorizontalDpi, currentDpi.VerticalDpi);
bmp.SetResolution(scale.Horizontal * DpiHelper.DefaultDpi, scale.Vertical * DpiHelper.DefaultDpi);
return bmp;
}

View File

@@ -18,6 +18,7 @@
using System;
using System.Globalization;
using System.Windows.Data;
using QuickLook.ExtensionMethods;
namespace QuickLook.Plugin.PDFViewer
{

View File

@@ -70,7 +70,7 @@
</ListBox.ItemTemplate>
</ListBox>
<Grid Grid.Column="1" Background="#00EFEFEF">
<imageViewer:ImagePanel x:Name="pagePanel" RenderMode="NearestNeighbor" />
<imageViewer:ImagePanel x:Name="pagePanel" RenderMode="NearestNeighbor" BackgroundVisibility="Collapsed" />
</Grid>
</Grid>
</UserControl>

View File

@@ -212,7 +212,7 @@ namespace QuickLook.Plugin.PDFViewer
// fill thumbnails list
Enumerable.Range(0, PdfHandle.TotalPages).ForEach(PageIds.Add);
OnPropertyChanged("PageIds");
OnPropertyChanged(nameof(PageIds));
CurrentPage = 0;
pagePanel.DoZoomToFit();

View File

@@ -24,6 +24,8 @@ namespace QuickLook.Plugin.PDFViewer
{
public class Plugin : IViewer
{
private ContextObject _context;
private string _path;
private PdfViewerControl _pdfControl;
public int Priority => int.MaxValue;
@@ -50,6 +52,9 @@ namespace QuickLook.Plugin.PDFViewer
public void Prepare(string path, ContextObject context)
{
_context = context;
_path = path;
var desiredSize = PdfViewerControl.GetDesiredControlSizeByFirstPage(path);
context.SetPreferredSizeFit(desiredSize, 0.8);
@@ -69,8 +74,8 @@ namespace QuickLook.Plugin.PDFViewer
_pdfControl.LoadPdf(path);
context.Title = $"{Path.GetFileName(path)} (1 / {_pdfControl.TotalPages})";
_pdfControl.CurrentPageChanged += (sender2, e2) => context.Title =
$"{Path.GetFileName(path)} ({_pdfControl.CurrentPage + 1} / {_pdfControl.TotalPages})";
_pdfControl.CurrentPageChanged += UpdateVindowCaption;
context.IsBusy = false;
}
catch (Exception e)
@@ -87,8 +92,17 @@ namespace QuickLook.Plugin.PDFViewer
{
GC.SuppressFinalize(this);
if (_pdfControl != null)
_pdfControl.CurrentPageChanged -= UpdateVindowCaption;
_pdfControl?.Dispose();
_pdfControl = null;
_context = null;
}
private void UpdateVindowCaption(object sender, EventArgs e2)
{
_context.Title = $"{Path.GetFileName(_path)} ({_pdfControl.CurrentPage + 1} / {_pdfControl.TotalPages})";
}
~Plugin()

View File

@@ -76,8 +76,6 @@
<DependentUpon>PdfViewerControl.xaml</DependentUpon>
</Compile>
<Compile Include="Plugin.cs" />
<Compile Include="DpiHelpers.cs" />
<Compile Include="Extensions.cs" />
<Compile Include="LibMuPdf.cs" />
<Compile Include="PageIdToImageConverter.cs" />
<Compile Include="PdfFile.cs" />

View File

@@ -37,14 +37,14 @@ namespace QuickLook.Plugin.TextViewer
if (Directory.Exists(path))
return false;
const long MAX_SIZE = 20 * 1024 * 1024;
const long maxSize = 20 * 1024 * 1024;
if (Path.GetExtension(path).ToLower() == ".txt")
return new FileInfo(path).Length <= MAX_SIZE;
if (path.ToLower().EndsWith(".txt"))
return new FileInfo(path).Length <= maxSize;
// 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 <= MAX_SIZE;
return new FileInfo(path).Length <= maxSize;
// otherwise, read the first 512KB, check if we can get something.
using (var s = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
@@ -53,14 +53,13 @@ namespace QuickLook.Plugin.TextViewer
var buffer = new byte[bufferLength];
var size = s.Read(buffer, 0, bufferLength);
return IsText(buffer, size) && new FileInfo(path).Length <= MAX_SIZE;
return IsText(buffer, size) && new FileInfo(path).Length <= maxSize;
}
}
public void Prepare(string path, ContextObject context)
{
context.PreferredSize = new Size {Width = 800, Height = 600};
context.CanFocus = true;
}
public void View(string path, ContextObject context)

View File

@@ -41,7 +41,7 @@ namespace QuickLook.Plugin.TextViewer
viewer.PreviewMouseWheel += Viewer_MouseWheel;
viewer.FontFamily =
new FontFamily(context.GetString("Editor_FontFamily", failsafe: "Consolas"));
new FontFamily(context.GetString("Editor_FontFamily"));
LoadFile(path);
}

View File

@@ -8,11 +8,14 @@
<Editor_FontFamily>Consolas,Microsoft Yahei UI,Microsoft Yahei,SimSun</Editor_FontFamily>
</zh-CN>
<zh-TW>
<Editor_FontFamily>Segoe UI,Microsoft JhengHei UI,Microsoft JhengHei,SimSun</Editor_FontFamily>
<Editor_FontFamily>Consolas,Microsoft JhengHei UI,Microsoft JhengHei,MingLiU</Editor_FontFamily>
</zh-TW>
<ja-JP>
<Editor_FontFamily>Consolas,Meiryo UI,MS UI Gothic,MS Gothic</Editor_FontFamily>
</ja-JP>
<ko-KR>
<Editor_FontFamily>Consolas,Malgun Gothic,Batang</Editor_FontFamily>
</ko-KR>
<es-ES>
<Editor_FontFamily>Consolas</Editor_FontFamily>
</es-ES>

View File

@@ -22,16 +22,22 @@ using System.Windows.Data;
namespace QuickLook.Plugin.VideoViewer
{
public sealed class BooleanToVisibilityHiddenConverter : DependencyObject, IValueConverter
public sealed class TimeSpanToShortStringConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Visibility.Collapsed;
return "00:00";
var v = (bool) value;
var v = (TimeSpan) value;
return v ? Visibility.Collapsed : Visibility.Visible;
var s = string.Empty;
if (v.Hours > 0)
s += $"{v.Hours:D2}:";
s += $"{v.Minutes:D2}:{v.Seconds:D2}";
return s;
}
object IValueConverter.ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
@@ -39,4 +45,28 @@ namespace QuickLook.Plugin.VideoViewer
throw new NotImplementedException();
}
}
public sealed class VolumeToIconConverter : DependencyObject, IValueConverter
{
private static readonly string[] Volumes = {"\xE992", "\xE993", "\xE994", "\xE995"};
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return Volumes[0];
var v = (int) value;
if (v == 0)
return Volumes[0];
v = Math.Min(v, 100);
return Volumes[1 + v / 34];
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

View File

@@ -28,7 +28,18 @@ namespace QuickLook.Plugin.VideoViewer
{
public class Plugin : IViewer
{
private Size _mediaSize = Size.Empty;
private static readonly string[] Formats =
{
// video
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".asf", ".avi", ".flv", ".m2ts", ".m4v", ".mkv",
".mov", ".mp4", ".mp4v", ".mpeg", ".mpg", ".ogv", ".qt", ".vob", ".webm", ".wmv",
// audio
".3gp", ".aa", ".aac", ".aax", ".act", ".aiff", ".amr", ".ape", ".au", ".awb", ".dct", ".dss", ".dvf",
".flac", ".gsm", ".iklax", ".ivs", ".m4a", ".m4b", ".m4p", ".mmf", ".mp3", ".mpc", ".msv", ".ogg",
".oga", ".mogg", ".opus", ".ra", ".rm", ".raw", ".tta", ".vox", ".wav", ".wma", ".wv", ".webm"
};
private ContextObject _context;
private ViewerPanel _vp;
public int Priority => 0 - 10; // make it lower than TextViewer
@@ -41,34 +52,35 @@ namespace QuickLook.Plugin.VideoViewer
public bool CanHandle(string path)
{
if (Directory.Exists(path))
return false;
var formats = new[]
{
// video
".3g2", ".3gp", ".3gp2", ".3gpp", ".amv", ".asf", ".asf", ".avi", ".flv", ".m2ts", ".m4v", ".mkv",
".mov", ".mp4", ".mp4v", ".mpeg", ".mpg", ".ogv", ".qt", ".vob", ".webm", ".wmv",
// audio
".3gp", ".aa", ".aac", ".aax", ".act", ".aiff", ".amr", ".ape", ".au", ".awb", ".dct", ".dss", ".dvf",
".flac", ".gsm", ".iklax", ".ivs", ".m4a", ".m4b", ".m4p", ".mmf", ".mp3", ".mpc", ".msv", ".ogg",
".oga", ".mogg", ".opus", ".ra", ".rm", ".raw", ".tta", ".vox", ".wav", ".wma", ".wv", ".webm"
};
return formats.Contains(Path.GetExtension(path).ToLower());
return !Directory.Exists(path) && Formats.Contains(Path.GetExtension(path).ToLower());
}
public void Prepare(string path, ContextObject context)
{
var def = new Size(450, 450);
_context = context;
_mediaSize = GetMediaSizeWithVlc(path);
var def = new Size(500, 300);
var windowSize = _mediaSize == Size.Empty ? def : _mediaSize;
var hasVideo = HasVideoStream(path, out Size mediaSize);
var windowSize = mediaSize == Size.Empty ? def : mediaSize;
windowSize.Width = Math.Max(def.Width, windowSize.Width);
windowSize.Height = Math.Max(def.Height, windowSize.Height);
context.SetPreferredSizeFit(windowSize, 0.6);
context.TitlebarOverlap = true;
if (!hasVideo)
{
context.CanResize = false;
context.TitlebarAutoHide = false;
context.TitlebarBlurVisibility = false;
context.TitlebarColourVisibility = false;
}
else
{
context.TitlebarAutoHide = true;
context.UseDarkTheme = true;
}
}
public void View(string path, ContextObject context)
@@ -77,23 +89,29 @@ namespace QuickLook.Plugin.VideoViewer
context.ViewerContent = _vp;
_vp.mediaElement.VlcMediaPlayer.Opening += (sender, e) => context.IsBusy = false;
_vp.mediaElement.VlcMediaPlayer.Opening += MarkReady;
_vp.LoadAndPlay(path);
var info = _mediaSize == Size.Empty ? "Audio" : $"{_mediaSize.Width}×{_mediaSize.Height}";
context.Title =
$"{Path.GetFileName(path)} ({info})";
context.Title = $"{Path.GetFileName(path)}";
}
public void Cleanup()
{
if (_vp != null)
_vp.mediaElement.VlcMediaPlayer.Opening -= MarkReady;
_vp?.Dispose();
_vp = null;
_context = null;
}
private Size GetMediaSizeWithVlc(string path)
private void MarkReady(object sender, ObjectEventArgs<MediaState> e)
{
_context.IsBusy = false;
}
private bool HasVideoStream(string path, out Size size)
{
using (var vlc = new Vlc(VlcSettings.VlcOptions))
{
@@ -103,7 +121,9 @@ namespace QuickLook.Plugin.VideoViewer
var tracks = media.GetTracks();
var video = tracks.FirstOrDefault(mt => mt.Type == TrackType.Video) as VideoTrack;
return video == null ? Size.Empty : new Size(video.Width, video.Height);
size = video == null ? Size.Empty : new Size(video.Width, video.Height);
return video != null;
}
}
}

View File

@@ -59,9 +59,6 @@
<AssemblyOriginatorKeyFile>key.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Reference Include="FontAwesome.WPF, Version=4.7.0.37774, Culture=neutral, PublicKeyToken=0758b07a11a4f466, processorArchitecture=MSIL">
<HintPath>..\..\packages\FontAwesome.WPF.4.7.0.9\lib\net40\FontAwesome.WPF.dll</HintPath>
</Reference>
<Reference Include="Meta.Vlc">
<HintPath>.\Meta.Vlc.dll</HintPath>
</Reference>
@@ -70,6 +67,7 @@
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
@@ -102,7 +100,6 @@
<SubType>Code</SubType>
</Compile>
<None Include="key.snk" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\QuickLook\QuickLook.csproj">
@@ -111,15 +108,11 @@
<Private>False</Private>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="Resources\compact-disc.png">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Resource>
</ItemGroup>
<ItemGroup>
<Content Include="LibVlc\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Resource Include="Resources\empty.png" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -1,44 +1,32 @@
<!--
This file is a part of unosquare/ffmediaelement project: <https://github.com/unosquare/ffmediaelement>
-->
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style x:Key="ControlButtonStyle" TargetType="Grid">
<Setter Property="Height" Value="35" />
<Setter Property="Width" Value="35" />
<Setter Property="Cursor" Value="Hand" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="Background" Value="Transparent" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#22FFFFFF" />
</Trigger>
</Style.Triggers>
</Style>
<ResourceDictionary.MergedDictionaries>
<!-- only for design -->
<ResourceDictionary Source="/QuickLook;component/Styles/MainWindowStyles.xaml" />
</ResourceDictionary.MergedDictionaries>
<SolidColorBrush x:Key="CustomSliderForegroundBrush" Color="#FFEFEFEF" />
<SolidColorBrush x:Key="CustomSliderBackgroundBrush" Color="#55ffffff" />
<SolidColorBrush x:Key="CustomSliderHighlightBrush" Color="#FFEFEFEF" />
<Style x:Key="ControlButtonStyle" TargetType="Button" BasedOn="{StaticResource CaptionButtonStyle}">
<Setter Property="Width" Value="32" />
</Style>
<!-- Postion Slider Control -->
<ControlTemplate x:Key="PositionSliderThumbTemplate" TargetType="{x:Type Thumb}">
<Grid HorizontalAlignment="Center" UseLayoutRounding="True" VerticalAlignment="Center">
<Path x:Name="grip" Data="M 0,0 A 180,180 180 1 1 1,1 Z" Fill="Transparent" Stretch="Fill"
Stroke="{StaticResource CustomSliderForegroundBrush}" StrokeThickness="2.5" UseLayoutRounding="True"
Stroke="{DynamicResource WindowTextForeground}" StrokeThickness="1" UseLayoutRounding="True"
VerticalAlignment="Center"
Margin="-1,-1" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="true">
<Setter Property="Fill" TargetName="grip" Value="{StaticResource CustomSliderForegroundBrush}" />
<Setter Property="Stroke" TargetName="grip" Value="{StaticResource CustomSliderForegroundBrush}" />
<Setter Property="Fill" TargetName="grip" Value="{DynamicResource WindowTextForeground}" />
<Setter Property="Stroke" TargetName="grip" Value="{DynamicResource WindowTextForeground}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Visibility" TargetName="grip" Value="Hidden" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Fill" TargetName="grip" Value="{StaticResource CustomSliderForegroundBrush}" />
<Setter Property="Fill" TargetName="grip" Value="{DynamicResource WindowTextForeground}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
@@ -49,13 +37,13 @@
<RowDefinition Height="{TemplateBinding MinHeight}" />
</Grid.RowDefinitions>
<DockPanel LastChildFill="True">
<Border ClipToBounds="True" x:Name="PART_SelectionRange" Height="3" Visibility="Visible">
<Border ClipToBounds="True" x:Name="PART_SelectionRange" Height="1" Visibility="Visible">
<Rectangle RadiusX="1" RadiusY="1" Margin="10,0,-10,0"
Fill="{StaticResource CustomSliderForegroundBrush}" />
Fill="{DynamicResource WindowTextForeground}" />
</Border>
<Border ClipToBounds="True" Height="3" Visibility="Visible">
<Rectangle RadiusX="1" RadiusY="1" Margin="20,0,10,0"
Fill="{StaticResource CustomSliderBackgroundBrush}" />
<Border ClipToBounds="True" Height="1" Visibility="Visible">
<Rectangle RadiusX="1" RadiusY="1" Margin="10,0,10,0"
Fill="{DynamicResource WindowTextForegroundAlternative}" />
</Border>
</DockPanel>
<Track x:Name="PART_Track">
@@ -73,10 +61,11 @@
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="MinHeight" Value="20" />
<Setter Property="MaxHeight" Value="20" />
<Setter Property="Height" Value="20" />
<Setter Property="MinHeight" Value="10" />
<Setter Property="MaxHeight" Value="10" />
<Setter Property="Height" Value="10" />
<Setter Property="Minimum" Value="0" />
<Setter Property="Focusable" Value="False" />
<Setter Property="AutoToolTipPlacement" Value="None" />
<Setter Property="IsMoveToPointEnabled" Value="True" />
<Setter Property="VerticalAlignment" Value="Center" />
@@ -88,20 +77,20 @@
<!-- Custom Slider Control -->
<ControlTemplate x:Key="CustomSliderThumbTemplate" TargetType="{x:Type Thumb}">
<Grid HorizontalAlignment="Center" UseLayoutRounding="True" VerticalAlignment="Center">
<Rectangle x:Name="grip" Fill="{StaticResource CustomSliderForegroundBrush}" Width="8"
<Rectangle x:Name="grip" Fill="{DynamicResource WindowTextForeground}" Width="8"
Height="{Binding Path=Height, RelativeSource={RelativeSource TemplatedParent}}"
StrokeThickness="0"
UseLayoutRounding="True" Stretch="Fill" RadiusX="3" RadiusY="3" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsDragging" Value="true">
<Setter Property="Fill" TargetName="grip" Value="{StaticResource CustomSliderHighlightBrush}" />
<Setter Property="Fill" TargetName="grip" Value="{DynamicResource WindowTextForeground}" />
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Fill" TargetName="grip" Value="{StaticResource CustomSliderBackgroundBrush}" />
<Setter Property="Fill" TargetName="grip" Value="{DynamicResource MainWindowBackground}" />
</Trigger>
<Trigger Property="IsKeyboardFocused" Value="true">
<Setter Property="Fill" TargetName="grip" Value="{StaticResource CustomSliderForegroundBrush}" />
<Trigger Property="IsKeyboardFocused" Value="False">
<Setter Property="Fill" TargetName="grip" Value="{DynamicResource WindowTextForeground}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
@@ -114,11 +103,11 @@
<DockPanel LastChildFill="True">
<Border ClipToBounds="True" x:Name="PART_SelectionRange" Height="3" Visibility="Visible">
<Rectangle RadiusX="1" RadiusY="1" Margin="4,0,-4,0"
Fill="{StaticResource CustomSliderForegroundBrush}" />
Fill="{DynamicResource WindowTextForeground}" />
</Border>
<Border ClipToBounds="True" Height="3" Visibility="Visible">
<Rectangle x:Name="PART_NegativeSelection" RadiusX="1" RadiusY="1" Margin="8,0,4,0"
Fill="{StaticResource CustomSliderBackgroundBrush}" />
Fill="{DynamicResource MainWindowBackground}" />
</Border>
</DockPanel>
<Track x:Name="PART_Track">
@@ -135,13 +124,14 @@
<Setter Property="Stylus.IsPressAndHoldEnabled" Value="false" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="BorderBrush" Value="Transparent" />
<Setter Property="MinHeight" Value="26" />
<Setter Property="MaxHeight" Value="26" />
<Setter Property="Height" Value="26" />
<Setter Property="MinHeight" Value="16" />
<Setter Property="MaxHeight" Value="16" />
<Setter Property="Height" Value="16" />
<Setter Property="Minimum" Value="0" />
<Setter Property="IsSnapToTickEnabled" Value="True" />
<Setter Property="SmallChange" Value="0.01" />
<Setter Property="LargeChange" Value="0.01" />
<Setter Property="Focusable" Value="False" />
<Setter Property="TickFrequency" Value="0.01" />
<Setter Property="AutoToolTipPlacement" Value="None" />
<Setter Property="IsMoveToPointEnabled" Value="True" />
@@ -150,79 +140,4 @@
<Setter Property="SelectionEnd" Value="{Binding Path=Value, RelativeSource={RelativeSource Self}}" />
<Setter Property="Template" Value="{StaticResource CustomSliderTemplate}" />
</Style>
<Style x:Key="NetworkProgressBarStyle" TargetType="{x:Type ProgressBar}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Height" Value="3" />
<Setter Property="Margin" Value="10,0" />
<Setter Property="Minimum" Value="0" />
<Setter Property="Maximum" Value="1" />
<Setter Property="Background" Value="{StaticResource CustomSliderBackgroundBrush}" />
</Style>
<Style x:Key="ModernToggleButtonStyle" TargetType="ToggleButton">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#22FFFFFF" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#44FFFFFF" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Background" Value="#44FFFFFF" />
</Trigger>
</Style.Triggers>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Width" Value="45" />
<Setter Property="Height" Value="45" />
<Setter Property="Padding" Value="12" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource CustomSliderHighlightBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Border Background="{TemplateBinding Background}" BorderThickness="0"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ModernButtonStyle" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#22FFFFFF" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#44FFFFFF" />
</Trigger>
</Style.Triggers>
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Width" Value="45" />
<Setter Property="Height" Value="45" />
<Setter Property="Padding" Value="12" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{StaticResource CustomSliderHighlightBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}" BorderThickness="0"
Padding="{TemplateBinding Padding}">
<ContentPresenter x:Name="contentPresenter" HorizontalAlignment="Center"
VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="ControlsGridStyle" TargetType="{x:Type Grid}">
<Setter Property="VerticalAlignment" Value="Bottom" />
<Setter Property="Height" Value="250" />
<Setter Property="Background" Value="{DynamicResource ShadedBackgroundBrush}" />
</Style>
</ResourceDictionary>

View File

@@ -3,168 +3,210 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:vlc="clr-namespace:Meta.Vlc.Wpf;assembly=Meta.Vlc.Wpf"
xmlns:local="clr-namespace:QuickLook.Plugin.VideoViewer"
xmlns:glassLayer="clr-namespace:QuickLook.Controls.GlassLayer;assembly=QuickLook"
mc:Ignorable="d"
x:Name="viewerPanel"
Background="#CC4E4E4E"
d:DesignHeight="450" d:DesignWidth="450">
d:DesignHeight="300" d:DesignWidth="500">
<UserControl.Resources>
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" />
<local:TimeSpanToShortStringConverter x:Key="TimeSpanToShortStringConverter" />
<local:VolumeToIconConverter x:Key="VolumeToIconConverter" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<Grid>
<Grid.Resources>
<ResourceDictionary>
<local:BooleanToVisibilityHiddenConverter x:Key="BooleanToVisibilityHiddenConverter" />
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Grid.Resources>
<vlc:VlcPlayer x:Name="mediaElement" LibVlcPath="{Binding LibVlcPath, ElementName=viewerPanel}"
VlcOption="{Binding VlcOption, ElementName=viewerPanel}" />
<Image>
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding CoverArt, ElementName=viewerPanel}" />
<Grid x:Name="coverArtPersenter" ClipToBounds="True" Background="{StaticResource MainWindowBackground}">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Visibility" Value="Collapsed" />
<Style.Triggers>
<DataTrigger Binding="{Binding HasVideo, ElementName=viewerPanel}" Value="False">
<Setter Property="Visibility" Value="Visible" />
</DataTrigger>
<DataTrigger
Binding="{Binding CoverArt.Length, ElementName=viewerPanel, FallbackValue=0, TargetNullValue=0}"
Value="0">
<Setter Property="Source" Value="Resources/compact-disc.png" />
<Setter Property="Margin" Value="50" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Grid HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="100">
<Grid.Background>
<LinearGradientBrush EndPoint="0,1" StartPoint="0,0">
<GradientStop Offset="0.0" Color="#00000000" />
<GradientStop Offset="0.25" Color="#66000000" />
<GradientStop Offset="1" Color="#D6000000" />
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="30" />
<RowDefinition Height="75" />
</Grid.RowDefinitions>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding Path=IsMouseOver, RelativeSource={RelativeSource Self}}"
Value="True" />
<Condition Binding="{Binding HasVideo, ElementName=viewerPanel}" Value="True" />
</MultiDataTrigger.Conditions>
<MultiDataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="1"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.EnterActions>
<MultiDataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity" To="0"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</MultiDataTrigger.ExitActions>
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="4*" />
<ColumnDefinition Width="6*" />
</Grid.ColumnDefinitions>
<Rectangle Margin="-50" Grid.Column="0" Grid.ColumnSpan="2">
<Rectangle.Effect>
<BlurEffect Radius="100" />
</Rectangle.Effect>
<Rectangle.Fill>
<ImageBrush ImageSource="{Binding ElementName=viewerPanel, Path=CoverArt}" Stretch="UniformToFill"
Opacity="0.9" />
</Rectangle.Fill>
</Rectangle>
<Image Grid.Column="0" x:Name="imageCoverArt" Margin="20,40,20,40">
<Image.Effect>
<DropShadowEffect Direction="0" BlurRadius="6" Color="#FF898989" ShadowDepth="0" />
</Image.Effect>
<Image.Style>
<Style TargetType="Image">
<Setter Property="Source" Value="{Binding CoverArt, ElementName=viewerPanel}" />
<Style.Triggers>
<DataTrigger
Binding="{Binding CoverArt, ElementName=viewerPanel, FallbackValue=0, TargetNullValue=0}"
Value="0">
<Setter Property="Source" Value="Resources/empty.png" />
</DataTrigger>
</Style.Triggers>
</Style>
</Image.Style>
</Image>
<Grid Grid.Column="1">
<Grid.Effect>
<DropShadowEffect ShadowDepth="0" BlurRadius="2" Opacity="0.7" Color="#B2FFFFFF" />
</Grid.Effect>
<Grid.RowDefinitions>
<RowDefinition Height="70" />
<RowDefinition Height="Auto" />
<RowDefinition Height="10" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock x:Name="metaTitle" Grid.Row="1" FontSize="22" Padding="3"
TextWrapping="Wrap"
LineHeight="28" MaxHeight="80" TextTrimming="CharacterEllipsis">
ときめきポポロン♪
</TextBlock>
<TextBlock x:Name="metaArtists" Grid.Row="3" FontSize="14" Padding="3" TextTrimming="CharacterEllipsis"
Foreground="{DynamicResource WindowTextForeground}">
チマメ隊
</TextBlock>
<TextBlock x:Name="metaAlbum" Grid.Row="4" FontSize="14" Padding="3" TextTrimming="CharacterEllipsis"
Foreground="{DynamicResource WindowTextForeground}">
ときめきポポロン♪
</TextBlock>
<TextBlock x:Name="metaLength" Grid.Row="5" FontSize="14" Padding="3" TextTrimming="CharacterEllipsis"
Foreground="{DynamicResource WindowTextForeground}"
Text="{Binding ElementName=mediaElement, Path=Length, Converter={StaticResource TimeSpanToShortStringConverter}}" />
</Grid>
</Grid>
<Slider Grid.Row="1" x:Name="sliderProgress" Style="{StaticResource PositionSliderStyle}"
SmallChange="0.00001" LargeChange="0.01" Maximum="1"
Value="{Binding Position, ElementName=mediaElement}" />
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="149" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" VerticalAlignment="Center" Orientation="Horizontal" Margin="10,0,0,0">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Setter Property="Visibility" Value="Visible" />
<Grid x:Name="videoControlContainer" HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Height="32">
<Grid.Resources>
<Storyboard x:Key="ShowControlStoryboard" Completed="AutoHideViedoControlContainer">
<DoubleAnimation
Storyboard.Target="{Binding Source={x:Reference videoControlContainer}}"
Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.05" />
</Storyboard>
<Storyboard x:Key="HideControlStoryboard">
<DoubleAnimationUsingKeyFrames
Storyboard.Target="{Binding Source={x:Reference videoControlContainer}}"
Storyboard.TargetProperty="Opacity">
<DoubleAnimationUsingKeyFrames.KeyFrames>
<LinearDoubleKeyFrame Value="1" KeyTime="0:0:0" />
<LinearDoubleKeyFrame Value="1" KeyTime="0:0:3" />
<LinearDoubleKeyFrame Value="0" KeyTime="0:0:3.05" />
</DoubleAnimationUsingKeyFrames.KeyFrames>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Grid.Resources>
<glassLayer:GlassLayer OverlayColor="{DynamicResource CaptionBackground}"
GlassVisibility="{Binding ElementName=viewerPanel, Path=HasVideo,Converter={StaticResource BooleanToVisibilityConverter}}"
ColorOverlayVisibility="{Binding ElementName=viewerPanel, Path=HasVideo,Converter={StaticResource BooleanToVisibilityConverter}}">
<glassLayer:GlassLayer.Style>
<Style TargetType="glassLayer:GlassLayer">
<Setter Property="BlurredElement" Value="{Binding ElementName=mediaElement}" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=viewerPanel,Path=HasVideo}" Value="True">
<Setter Property="BlurredElement" Value="{Binding ElementName=mediaElement}" />
</DataTrigger>
</Style.Triggers>
</Style>
</glassLayer:GlassLayer.Style>
</glassLayer:GlassLayer>
<DockPanel>
<Button x:Name="buttonPlayPause" DockPanel.Dock="Left">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource ControlButtonStyle}">
<Setter Property="Content" Value="&#xE769;" />
<Style.Triggers>
<DataTrigger Binding="{Binding HasAudio, ElementName=viewerPanel}" Value="False">
<Setter Property="Visibility" Value="Hidden" />
<DataTrigger Binding="{Binding IsPlaying, ElementName=viewerPanel}"
Value="False">
<Setter Property="Content" Value="&#xE768;" />
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<Grid x:Name="buttonMute" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Height="23" Width="23" Foreground="#FFEFEFEF">
<fa:ImageAwesome.Style>
<Style TargetType="fa:ImageAwesome">
<Setter Property="Icon" Value="VolumeOff" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMuted, ElementName=viewerPanel}"
Value="False">
<Setter Property="Icon" Value="VolumeUp" />
</DataTrigger>
</Style.Triggers>
</Style>
</fa:ImageAwesome.Style>
</fa:ImageAwesome>
</Grid>
<Slider Style="{StaticResource CustomSliderStyle}" Width="75" Maximum="100"
Value="{Binding Volume, ElementName=mediaElement}"
Visibility="{Binding IsMuted, ElementName=viewerPanel, Converter={StaticResource BooleanToVisibilityHiddenConverter}}"
BorderThickness="0,0,5,0" />
</StackPanel>
<StackPanel Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Center">
<Grid x:Name="buttonBackward" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Icon="Backward" Height="23" Width="23" Foreground="#FFEFEFEF" />
</Grid>
<Grid Width="3" />
<Grid x:Name="buttonPlayPause" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Height="23" Width="23" Foreground="#FFEFEFEF">
<fa:ImageAwesome.Style>
<Style>
<Setter Property="fa:ImageAwesome.Icon" Value="Pause" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsPlaying, ElementName=viewerPanel}"
Value="False">
<Setter Property="fa:ImageAwesome.Icon" Value="Play" />
</DataTrigger>
</Style.Triggers>
</Style>
</fa:ImageAwesome.Style>
</fa:ImageAwesome>
</Grid>
<Grid Width="3" />
<Grid x:Name="buttonStop" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Icon="Stop" Height="21" Width="21" Foreground="#FFEFEFEF" />
</Grid>
<Grid Width="3" />
<Grid x:Name="buttonForward" Style="{StaticResource ControlButtonStyle}">
<fa:ImageAwesome Icon="Forward" Height="23" Width="23" Foreground="#FFEFEFEF" />
</Grid>
</StackPanel>
<StackPanel Grid.Column="2" HorizontalAlignment="Right" VerticalAlignment="Center"
Orientation="Horizontal" Margin="0,0,10,0">
<TextBlock FontSize="14" Foreground="#FFEFEFEF"
Text="{Binding Time, StringFormat=hh\\:mm\\:ss, ElementName=mediaElement}" />
<TextBlock FontSize="14" Text=" / " Foreground="#FFEFEFEF" />
<TextBlock FontSize="14" Foreground="#FFEFEFEF"
Text="{Binding Length, StringFormat=hh\\:mm\\:ss, ElementName=mediaElement}" />
</StackPanel>
</Grid>
</Button.Style>
</Button>
<Button x:Name="buttonMute" DockPanel.Dock="Right">
<Button.Style>
<Style TargetType="Button" BasedOn="{StaticResource ControlButtonStyle}">
<Setter Property="Content"
Value="{Binding ElementName=mediaElement, Path=Volume, Converter={StaticResource VolumeToIconConverter}}" />
<Style.Triggers>
<DataTrigger Binding="{Binding IsMuted, ElementName=viewerPanel}"
Value="True">
<Setter Property="Content" Value="&#xE74F;" />
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<Button x:Name="buttonTime" Width="37" Style="{StaticResource ControlButtonStyle}" DockPanel.Dock="Right" Tag="Time">
<TextBlock VerticalAlignment="Center" FontSize="11"
FontFamily="{Binding ElementName=viewerPanel, Path=FontFamily}"
Foreground="{DynamicResource CaptionButtonIconForeground}">
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=buttonTime, Path=Tag}" Value="Time">
<Setter Property="Text"
Value="{Binding ElementName=mediaElement, Path=Time, Converter={StaticResource TimeSpanToShortStringConverter}}" />
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=buttonTime, Path=Tag}" Value="Length">
<Setter Property="Text"
Value="{Binding ElementName=mediaElement, Path=Length, Converter={StaticResource TimeSpanToShortStringConverter}}" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</Button>
<Slider x:Name="sliderProgress" Style="{StaticResource PositionSliderStyle}"
SmallChange="0.00001" LargeChange="0.01" Maximum="1"
Value="{Binding Position, ElementName=mediaElement}" />
</DockPanel>
</Grid>
<!--<Grid Height="32" Width="100" HorizontalAlignment="Right" VerticalAlignment="Bottom"
Background="{DynamicResource CaptionBackground}" Margin="0,0,0,32">
<Grid.Style>
<Style TargetType="Grid">
<Setter Property="Opacity" Value="0" />
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=buttonMute, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation To="1" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard TargetProperty="Opacity">
<DoubleAnimation To="0" Duration="0:0:0.1" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Slider Style="{StaticResource CustomSliderStyle}" Width="100" Maximum="100" Value="{Binding ElementName=mediaElement, Path=Volume}" />
</Grid>-->
</Grid>
</UserControl>

View File

@@ -18,13 +18,17 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
using Meta.Vlc;
using Meta.Vlc.Interop.Media;
using QuickLook.Annotations;
using QuickLook.ExtensionMethods;
using MediaState = Meta.Vlc.Interop.Media.MediaState;
namespace QuickLook.Plugin.VideoViewer
@@ -36,7 +40,7 @@ namespace QuickLook.Plugin.VideoViewer
{
private readonly ContextObject _context;
private string _coverArt;
private Uri _coverArt;
private bool _hasAudio;
private bool _hasEnded;
private bool _hasVideo;
@@ -48,21 +52,20 @@ namespace QuickLook.Plugin.VideoViewer
{
InitializeComponent();
// apply global theme
Resources.MergedDictionaries[0].MergedDictionaries.Clear();
ShowViedoControlContainer(null, null);
viewerPanel.PreviewMouseMove += ShowViedoControlContainer;
mediaElement.PropertyChanged += PlayerPropertyChanged;
mediaElement.StateChanged += PlayerStateChanged;
_context = context;
buttonPlayPause.MouseLeftButtonUp += TogglePlayPause;
//buttonMute.MouseLeftButtonUp += (sender, e) =>
//{
// mediaElement.IsMuted = false;
// buttonMute.Visibility = Visibility.Collapsed;
//};
buttonMute.MouseLeftButtonUp += (sender, e) => IsMuted = !IsMuted;
buttonStop.MouseLeftButtonUp += PlayerStop;
buttonBackward.MouseLeftButtonUp += (sender, e) => Seek(TimeSpan.FromSeconds(-10));
buttonForward.MouseLeftButtonUp += (sender, e) => Seek(TimeSpan.FromSeconds(10));
buttonPlayPause.Click += TogglePlayPause;
buttonTime.Click += (sender, e) => buttonTime.Tag = (string) buttonTime.Tag == "Time" ? "Length" : "Time";
buttonMute.Click += (sender, e) => IsMuted = !IsMuted;
sliderProgress.PreviewMouseDown += (sender, e) =>
{
@@ -85,7 +88,7 @@ namespace QuickLook.Plugin.VideoViewer
}
};*/
PreviewMouseWheel += (sender, e) => ChangeVolume((double) e.Delta / 120 * 2);
PreviewMouseWheel += (sender, e) => ChangeVolume((double) e.Delta / 120 * 4);
}
public bool IsMuted
@@ -144,7 +147,7 @@ namespace QuickLook.Plugin.VideoViewer
}
}
public string CoverArt
public Uri CoverArt
{
get => _coverArt;
private set
@@ -178,6 +181,26 @@ namespace QuickLook.Plugin.VideoViewer
public event PropertyChangedEventHandler PropertyChanged;
private void ShowViedoControlContainer(object sender, MouseEventArgs e)
{
var show = (Storyboard) videoControlContainer.FindResource("ShowControlStoryboard");
if (videoControlContainer.Opacity == 0 || videoControlContainer.Opacity == 1)
show.Begin();
}
private void AutoHideViedoControlContainer(object sender, EventArgs e)
{
if (!HasVideo)
return;
if (videoControlContainer.IsMouseOver)
return;
var hide = (Storyboard) videoControlContainer.FindResource("HideControlStoryboard");
hide.Begin();
}
private void PlayerStop(object sender, MouseButtonEventArgs e)
{
HasEnded = false;
@@ -209,8 +232,8 @@ namespace QuickLook.Plugin.VideoViewer
HasAudio = mediaElement.VlcMediaPlayer.AudioTrackCount > 0;
break;
case MediaState.Playing:
CoverArt = mediaElement.VlcMediaPlayer.Media.GetMeta(
MetaDataType.ArtworkUrl);
UpdateMeta();
DetermineTheme();
HasVideo = mediaElement.VlcMediaPlayer.VideoTrackCount > 0;
HasAudio = mediaElement.VlcMediaPlayer.AudioTrackCount > 0;
IsPlaying = true;
@@ -228,6 +251,44 @@ namespace QuickLook.Plugin.VideoViewer
}
}
private void UpdateMeta()
{
if (HasVideo)
return;
var path = mediaElement.VlcMediaPlayer.Media.GetMeta(MetaDataType.ArtworkUrl);
if (!string.IsNullOrEmpty(path))
CoverArt = new Uri(path);
metaTitle.Text = mediaElement.VlcMediaPlayer.Media.GetMeta(MetaDataType.Title);
metaArtists.Text = mediaElement.VlcMediaPlayer.Media.GetMeta(MetaDataType.Artist);
metaAlbum.Text = mediaElement.VlcMediaPlayer.Media.GetMeta(MetaDataType.Album);
metaArtists.Visibility = string.IsNullOrEmpty(metaArtists.Text)
? Visibility.Collapsed
: Visibility.Visible;
metaAlbum.Visibility = string.IsNullOrEmpty(metaAlbum.Text)
? Visibility.Collapsed
: Visibility.Visible;
}
private void DetermineTheme()
{
if (HasVideo)
return;
if (CoverArt == null)
return;
var dark = false;
using (var bitmap = new Bitmap(CoverArt.LocalPath))
{
dark = bitmap.IsDarkImage();
}
_context.UseDarkTheme = dark;
}
private void ChangeVolume(double delta)
{
IsMuted = false;
@@ -249,7 +310,7 @@ namespace QuickLook.Plugin.VideoViewer
if (_wasPlaying) mediaElement.Play();
}
private void TogglePlayPause(object sender, MouseButtonEventArgs e)
private void TogglePlayPause(object sender, EventArgs e)
{
if (mediaElement.VlcMediaPlayer.IsPlaying)
{

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net452" />
</packages>

View File

@@ -2,8 +2,11 @@
<configuration>
<configSections>
<sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
<section name="QuickLook.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
<sectionGroup name="userSettings"
type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="QuickLook.Properties.Settings"
type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
allowExeDefinition="MachineToLocalUser" requirePermission="false" />
</sectionGroup>
</configSections>
<startup>

View File

@@ -9,8 +9,8 @@
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Styles/ScrollBarStyleDictionary.xaml" />
<ResourceDictionary Source="Styles/BusyDecorator.xaml" />
</ResourceDictionary.MergedDictionaries>
<FontFamily x:Key="SegoeMDL2">./Fonts/#Segoe MDL2 Assets</FontFamily>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -22,7 +22,6 @@ using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Threading;
using QuickLook.Helpers;
using QuickLook.Properties;
@@ -103,26 +102,23 @@ namespace QuickLook
private void RemoteCallShowPreview(StartupEventArgs e)
{
PipeServerManager.SendMessage(e.Args.First());
PipeServerManager.SendMessage(PipeMessages.Toggle, e.Args.First());
}
private void RunListener(StartupEventArgs e)
{
TrayIconManager.GetInstance();
if (!e.Args.Contains("/autorun") && !IsUWP)
TrayIconManager.GetInstance()
.ShowNotification("", TranslationHelper.GetString("APP_START"));
TrayIconManager.ShowNotification("", TranslationHelper.GetString("APP_START"));
if (e.Args.Contains("/first"))
AutoStartupHelper.CreateAutorunShortcut();
NativeMethods.QuickLook.Init();
PluginManager.GetInstance();
ViewWindowManager.GetInstance();
BackgroundListener.GetInstance();
PipeServerManager.GetInstance().MessageReceived +=
(msg, ea) => Dispatcher.BeginInvoke(
new Action(() => ViewWindowManager.GetInstance().InvokeViewer(msg as string, true)),
DispatcherPriority.ApplicationIdle);
PipeServerManager.GetInstance();
}
private void App_OnExit(object sender, ExitEventArgs e)

View File

@@ -16,8 +16,8 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Diagnostics;
using System.Windows.Forms;
using System.Windows.Threading;
using QuickLook.Helpers;
namespace QuickLook
@@ -60,22 +60,50 @@ namespace QuickLook
{
_isKeyDownInDesktopOrShell = NativeMethods.QuickLook.GetFocusedWindowType() !=
NativeMethods.QuickLook.FocusedWindowType.Invalid;
_isKeyDownInDesktopOrShell |= WindowHelper.IsForegroundWindowBelongToSelf();
}
// call InvokeRoutine only when the KeyDown is valid
if (_isKeyDownInDesktopOrShell)
Dispatcher.CurrentDispatcher.BeginInvoke(
new Action<bool>(down =>
ViewWindowManager.GetInstance().InvokeRoutine(e, down)),
DispatcherPriority.ApplicationIdle,
isKeyDown);
InvokeRoutine(e.KeyCode, isKeyDown);
// reset variable only when KeyUp
if (!isKeyDown)
_isKeyDownInDesktopOrShell = false;
}
private void InvokeRoutine(Keys key, bool isKeyDown)
{
var path = NativeMethods.QuickLook.GetCurrentSelection();
Debug.WriteLine($"InvokeRoutine: key={key},down={isKeyDown}");
if (isKeyDown)
switch (key)
{
case Keys.Enter:
PipeServerManager.SendMessage(PipeMessages.RunAndClose);
break;
}
else
switch (key)
{
case Keys.Up:
case Keys.Down:
case Keys.Left:
case Keys.Right:
PipeServerManager.SendMessage(PipeMessages.Invoke, path);
break;
case Keys.Space:
PipeServerManager.SendMessage(PipeMessages.Toggle, path);
break;
case Keys.Escape:
PipeServerManager.SendMessage(PipeMessages.Close);
break;
}
}
private void InstallKeyHook(KeyEventHandler downHandler, KeyEventHandler upHandler)
{
_hook = GlobalKeyboardHook.GetInstance();

View File

@@ -22,7 +22,7 @@ using System.Windows;
using System.Windows.Media;
using System.Windows.Threading;
namespace QuickLook.Controls
namespace QuickLook.Controls.BusyDecorator
{
public delegate Visual CreateContentFunction();

View File

@@ -22,13 +22,18 @@ using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Media;
namespace QuickLook.Controls
namespace QuickLook.Controls.BusyDecorator
{
[StyleTypedProperty(Property = "BusyStyle", StyleTargetType = typeof(Control))]
public class BusyDecorator : Decorator, IDisposable
{
private readonly BackgroundVisualHost _busyHost = new BackgroundVisualHost();
private readonly ResourceDictionary _styles = new ResourceDictionary
{
Source = new Uri("pack://application:,,,/QuickLook;component/Controls/BusyDecorator/BusyDecorator.xaml")
};
static BusyDecorator()
{
DefaultStyleKeyProperty.OverrideMetadata(
@@ -38,6 +43,8 @@ namespace QuickLook.Controls
public BusyDecorator()
{
Resources.MergedDictionaries.Add(_styles);
AddLogicalChild(_busyHost);
AddVisualChild(_busyHost);
@@ -85,9 +92,11 @@ namespace QuickLook.Controls
private void SetBinding(DependencyObject obj, DependencyProperty source, DependencyProperty target)
{
var b = new Binding();
b.Source = this;
b.Path = new PropertyPath(source);
var b = new Binding
{
Source = this,
Path = new PropertyPath(source)
};
BindingOperations.SetBinding(obj, target, b);
}

View File

@@ -1,18 +1,19 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:fa="http://schemas.fontawesome.io/icons/"
xmlns:local="clr-namespace:QuickLook"
xmlns:controls="clr-namespace:QuickLook.Controls">
xmlns:busyDecorator="clr-namespace:QuickLook.Controls.BusyDecorator">
<Style TargetType="{x:Type controls:BusyDecorator}">
<Style TargetType="{x:Type busyDecorator:BusyDecorator}">
<Setter Property="BusyStyle">
<Setter.Value>
<Style TargetType="{x:Type Control}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<fa:ImageAwesome Width="40" Height="40" Icon="Cog" Spin="True" SpinDuration="1" />
<busyDecorator:SpinIcon FontFamily="{StaticResource SegoeMDL2}" FontSize="40"
Spin="True">
&#xE72C;
</busyDecorator:SpinIcon>
</ControlTemplate>
</Setter.Value>
</Setter>

View File

@@ -0,0 +1,97 @@
// 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 <http://www.gnu.org/licenses/>.
using System;
using System.Linq;
using System.Windows;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace QuickLook.Controls.BusyDecorator
{
/// <summary>
/// Control extensions
/// </summary>
internal static class ControlExtensions
{
/// <summary>
/// The key used for storing the spinner Storyboard.
/// </summary>
private static readonly string SpinnerStoryBoardName = $"{typeof(FrameworkElement).Name}Spinner";
/// <summary>
/// Start the spinning animation
/// </summary>
/// <typeparam name="T">FrameworkElement and ISpinable</typeparam>
/// <param name="control">Control to apply the rotation </param>
public static void BeginSpin<T>(this T control)
where T : FrameworkElement, ISpinable
{
var transformGroup = control.RenderTransform as TransformGroup ?? new TransformGroup();
var rotateTransform = transformGroup.Children.OfType<RotateTransform>().FirstOrDefault();
if (rotateTransform != null)
{
rotateTransform.Angle = 0;
}
else
{
transformGroup.Children.Add(new RotateTransform(0.0));
control.RenderTransform = transformGroup;
control.RenderTransformOrigin = new Point(0.5, 0.5);
}
var storyboard = new Storyboard();
var animation = new DoubleAnimation
{
From = 0,
To = 360,
AutoReverse = false,
RepeatBehavior = RepeatBehavior.Forever,
Duration = new Duration(TimeSpan.FromSeconds(control.SpinDuration))
};
storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, control);
Storyboard.SetTargetProperty(animation,
new PropertyPath("(0).(1)[0].(2)", UIElement.RenderTransformProperty,
TransformGroup.ChildrenProperty, RotateTransform.AngleProperty));
storyboard.Begin();
control.Resources.Add(SpinnerStoryBoardName, storyboard);
}
/// <summary>
/// Stop the spinning animation
/// </summary>
/// <typeparam name="T">FrameworkElement and ISpinable</typeparam>
/// <param name="control">Control to stop the rotation.</param>
public static void StopSpin<T>(this T control)
where T : FrameworkElement, ISpinable
{
var storyboard = control.Resources[SpinnerStoryBoardName] as Storyboard;
if (storyboard == null) return;
storyboard.Stop();
control.Resources.Remove(SpinnerStoryBoardName);
}
}
}

View File

@@ -15,12 +15,21 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System.Security;
namespace QuickLook.Helpers.BlurLibrary.NativeThings
namespace QuickLook.Controls.BusyDecorator
{
[SuppressUnmanagedCodeSecurity]
internal static class NativeMethods
/// <summary>
/// Represents a spinable control
/// </summary>
internal interface ISpinable
{
/// <summary>
/// Gets or sets the current spin (angle) animation of the icon.
/// </summary>
bool Spin { get; set; }
/// <summary>
/// Gets or sets the duration of the spinning animation (in seconds). This will stop and start the spin animation.
/// </summary>
double SpinDuration { get; set; }
}
}

View File

@@ -0,0 +1,90 @@
// 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 <http://www.gnu.org/licenses/>.
using System.Windows;
using System.Windows.Controls;
namespace QuickLook.Controls.BusyDecorator
{
internal class SpinIcon : TextBlock, ISpinable
{
#region public bool Spin
/// <summary>
/// Identifies the Spin dependency property.
/// </summary>
public static DependencyProperty SpinProperty =
DependencyProperty.Register("Spin", typeof(bool), typeof(SpinIcon),
new PropertyMetadata(false, OnSpinPropertyChanged));
private static void OnSpinPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = d as SpinIcon;
if (b == null) return;
if ((bool) e.NewValue)
b.BeginSpin();
else
b.StopSpin();
}
/// <summary>
/// Gets or sets the current spin (angle) animation of the icon.
/// </summary>
public bool Spin
{
get => (bool) GetValue(SpinProperty);
set => SetValue(SpinProperty, value);
}
#endregion public bool Spin
#region public double SpinDuration
/// <summary>
/// Identifies the SpinDuration dependency property.
/// </summary>
public static DependencyProperty SpinDurationProperty =
DependencyProperty.Register("SpinDuration", typeof(double), typeof(SpinIcon),
new PropertyMetadata(1d, SpinDurationChanged));
private static void SpinDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var b = d as SpinIcon;
if (null == b || !b.Spin || !(e.NewValue is double) ||
e.NewValue.Equals(e.OldValue)) return;
b.StopSpin();
b.BeginSpin();
}
/// <summary>
/// Gets or sets the duration of the spinning animation (in seconds). This will stop and start the spin animation.
/// </summary>
public double SpinDuration
{
get => (double) GetValue(SpinDurationProperty);
set => SetValue(SpinDurationProperty, value);
}
#endregion public double SpinDuration
}
}

View File

@@ -18,7 +18,7 @@
using System.Windows;
using System.Windows.Media;
namespace QuickLook.Controls
namespace QuickLook.Controls.BusyDecorator
{
public class VisualTargetPresentationSource : PresentationSource
{

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -0,0 +1,47 @@
// 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 <http://www.gnu.org/licenses/>.
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
namespace QuickLook.Controls.GlassLayer
{
public sealed class ElementCoordinateConverter : DependencyObject, IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
var glass = value as GlassLayer;
if (glass?.BlurredElement == null)
return null;
var target = glass.BlurredElement;
var trans = glass.TransformToVisual(target);
var p = trans.Transform(new Point(0, 0));
return new Rect {X = p.X, Y = p.Y, Width = glass.ActualWidth, Height = glass.ActualHeight};
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
}

Some files were not shown because too many files have changed in this diff Show More