Compare commits
28 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
04b9f7b5c1 | ||
![]() |
1d7c95a822 | ||
![]() |
e4ab7d0a32 | ||
![]() |
6027a387b0 | ||
![]() |
3e2336a63d | ||
![]() |
1260afb2c4 | ||
![]() |
dbee403b59 | ||
![]() |
7676d5867b | ||
![]() |
6bae00361b | ||
![]() |
1c18890fbf | ||
![]() |
8e400e7ee5 | ||
![]() |
cd9b713c41 | ||
![]() |
9ce0776d53 | ||
![]() |
346ec59ea5 | ||
![]() |
bc533f3d18 | ||
![]() |
efaca311fc | ||
![]() |
2b3338cc43 | ||
![]() |
56cb31fd2a | ||
![]() |
5b97e7ef60 | ||
![]() |
3a20245304 | ||
![]() |
768425ad0f | ||
![]() |
60cd782c64 | ||
![]() |
8d59e7138c | ||
![]() |
e79de6c36d | ||
![]() |
810de851ff | ||
![]() |
15af258db0 | ||
![]() |
15d94d2c4b | ||
![]() |
dae2a3a512 |
@@ -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>
|
||||
|
@@ -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>
|
||||
|
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 2.7 KiB |
BIN
Build/Assets/LargeTile.scale-125.png
Normal file
After Width: | Height: | Size: 3.4 KiB |
BIN
Build/Assets/LargeTile.scale-150.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 5.8 KiB |
Before Width: | Height: | Size: 30 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 811 B |
BIN
Build/Assets/SmallTile.scale-125.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
Build/Assets/SmallTile.scale-150.png
Normal file
After Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 1.5 KiB |
Before Width: | Height: | Size: 7.6 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.3 KiB |
BIN
Build/Assets/Square150x150Logo.scale-125.png
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
Build/Assets/Square150x150Logo.scale-150.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
Before Width: | Height: | Size: 5.8 KiB After Width: | Height: | Size: 2.6 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 5.7 KiB |
Before Width: | Height: | Size: 786 B After Width: | Height: | Size: 15 KiB |
BIN
Build/Assets/Square44x44Logo.altform-unplated_targetsize-24.png
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 21 KiB |
BIN
Build/Assets/Square44x44Logo.altform-unplated_targetsize-32.png
Normal file
After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 465 B |
BIN
Build/Assets/Square44x44Logo.scale-125.png
Normal file
After Width: | Height: | Size: 592 B |
BIN
Build/Assets/Square44x44Logo.scale-150.png
Normal file
After Width: | Height: | Size: 702 B |
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 854 B |
Before Width: | Height: | Size: 6.5 KiB After Width: | Height: | Size: 1.6 KiB |
Before Width: | Height: | Size: 584 B After Width: | Height: | Size: 15 KiB |
BIN
Build/Assets/Square44x44Logo.targetsize-24.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 18 KiB |
BIN
Build/Assets/Square44x44Logo.targetsize-32.png
Normal file
After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 15 KiB |
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.5 KiB |
BIN
Build/Assets/Wide310x150Logo.scale-125.png
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
Build/Assets/Wide310x150Logo.scale-150.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
Before Width: | Height: | Size: 6.3 KiB After Width: | Height: | Size: 3.1 KiB |
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 16 KiB |
BIN
Build/Assets/storelogo.scale-125.png
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
Build/Assets/storelogo.scale-150.png
Normal file
After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 4.9 KiB After Width: | Height: | Size: 17 KiB |
Before Width: | Height: | Size: 9.6 KiB After Width: | Height: | Size: 20 KiB |
@@ -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
|
||||
|
@@ -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());
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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)
|
||||
|
@@ -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; }
|
||||
}
|
||||
}
|
@@ -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)
|
||||
|
@@ -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>
|
||||
|
@@ -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()
|
||||
|
@@ -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;
|
||||
}
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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;
|
||||
|
@@ -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"
|
||||
|
@@ -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);
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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>
|
After Width: | Height: | Size: 15 KiB |
@@ -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];
|
||||
|
@@ -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)
|
||||
|
@@ -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; }
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
@@ -18,6 +18,7 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Windows.Data;
|
||||
using QuickLook.ExtensionMethods;
|
||||
|
||||
namespace QuickLook.Plugin.PDFViewer
|
||||
{
|
||||
|
@@ -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>
|
@@ -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();
|
||||
|
@@ -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()
|
||||
|
@@ -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" />
|
||||
|
@@ -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)
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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>
|
||||
|
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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>
|
Before Width: | Height: | Size: 22 KiB |
After Width: | Height: | Size: 24 KiB |
@@ -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>
|
@@ -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="" />
|
||||
<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="" />
|
||||
</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="" />
|
||||
</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>
|
@@ -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)
|
||||
{
|
||||
|
@@ -1,5 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<packages>
|
||||
<package id="FontAwesome.WPF" version="4.7.0.9" targetFramework="net452" />
|
||||
</packages>
|
@@ -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>
|
||||
|
@@ -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>
|
@@ -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)
|
||||
|
@@ -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();
|
||||
|
@@ -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();
|
||||
|
@@ -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);
|
||||
}
|
||||
|
@@ -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">
|
||||

|
||||
</busyDecorator:SpinIcon>
|
||||
</ControlTemplate>
|
||||
</Setter.Value>
|
||||
</Setter>
|
97
QuickLook/Controls/BusyDecorator/ControlExtensions.cs
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@@ -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; }
|
||||
}
|
||||
}
|
90
QuickLook/Controls/BusyDecorator/SpinIcon.cs
Normal 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
|
||||
}
|
||||
}
|
@@ -18,7 +18,7 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace QuickLook.Controls
|
||||
namespace QuickLook.Controls.BusyDecorator
|
||||
{
|
||||
public class VisualTargetPresentationSource : PresentationSource
|
||||
{
|
BIN
QuickLook/Controls/GlassLayer/100-50-5-monochrome.png
Normal file
After Width: | Height: | Size: 15 KiB |
47
QuickLook/Controls/GlassLayer/ElementCoordinateConverter.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
}
|