mirror of
https://github.com/QL-Win/QuickLook.git
synced 2026-03-03 01:00:26 +08:00
239 lines
7.5 KiB
C#
239 lines
7.5 KiB
C#
// 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.Diagnostics;
|
|
using System.IO;
|
|
using System.Runtime.ExceptionServices;
|
|
using System.Windows;
|
|
using System.Windows.Forms;
|
|
using System.Windows.Threading;
|
|
using QuickLook.Helpers;
|
|
using QuickLook.Plugin;
|
|
|
|
namespace QuickLook
|
|
{
|
|
internal class ViewWindowManager : IDisposable
|
|
{
|
|
private static ViewWindowManager _instance;
|
|
|
|
private readonly MainWindowNoTransparent _viewWindowNoTransparent;
|
|
private readonly MainWindowTransparent _viewWindowTransparentTransparent;
|
|
private MainWindowTransparent _currentMainWindow;
|
|
|
|
private string _path = string.Empty;
|
|
|
|
internal ViewWindowManager()
|
|
{
|
|
_viewWindowTransparentTransparent = new MainWindowTransparent();
|
|
_viewWindowNoTransparent = new MainWindowNoTransparent();
|
|
|
|
_currentMainWindow = _viewWindowTransparentTransparent;
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
StopFocusMonitor();
|
|
}
|
|
|
|
internal void InvokeRoutine(KeyEventArgs kea, bool isKeyDown)
|
|
{
|
|
Debug.WriteLine($"InvokeRoutine: key={kea.KeyCode},down={isKeyDown}");
|
|
|
|
|
|
if (isKeyDown)
|
|
switch (kea.KeyCode)
|
|
{
|
|
case Keys.Enter:
|
|
RunAndClosePreview();
|
|
break;
|
|
}
|
|
else
|
|
switch (kea.KeyCode)
|
|
{
|
|
case Keys.Up:
|
|
case Keys.Down:
|
|
case Keys.Left:
|
|
case Keys.Right:
|
|
SwitchPreview();
|
|
break;
|
|
case Keys.Space:
|
|
TogglePreview();
|
|
break;
|
|
case Keys.Escape:
|
|
ClosePreview();
|
|
break;
|
|
}
|
|
}
|
|
|
|
internal void RunAndClosePreview()
|
|
{
|
|
if (_currentMainWindow.Visibility != Visibility.Visible)
|
|
return;
|
|
|
|
// if the current focus is in Desktop or explorer windows, just close the preview window and leave the task to System.
|
|
var focus = NativeMethods.QuickLook.GetFocusedWindowType();
|
|
if (focus != NativeMethods.QuickLook.FocusedWindowType.Invalid)
|
|
{
|
|
StopFocusMonitor();
|
|
_currentMainWindow.BeginHide();
|
|
return;
|
|
}
|
|
|
|
// if the focus is in the preview window, run it
|
|
if (!WindowHelper.IsForegroundWindowBelongToSelf())
|
|
return;
|
|
|
|
StopFocusMonitor();
|
|
_currentMainWindow.RunAndHide();
|
|
}
|
|
|
|
internal void ClosePreview()
|
|
{
|
|
if (_currentMainWindow.Visibility != Visibility.Visible)
|
|
return;
|
|
|
|
StopFocusMonitor();
|
|
_currentMainWindow.BeginHide();
|
|
}
|
|
|
|
private void TogglePreview()
|
|
{
|
|
if (_currentMainWindow.Visibility == Visibility.Visible)
|
|
{
|
|
ClosePreview();
|
|
}
|
|
else
|
|
{
|
|
_path = NativeMethods.QuickLook.GetCurrentSelection();
|
|
InvokeViewer();
|
|
}
|
|
}
|
|
|
|
private void SwitchPreview()
|
|
{
|
|
if (_currentMainWindow.Visibility != Visibility.Visible)
|
|
return;
|
|
|
|
// if the switch has been done by SwitchPreviewRemoteInvoke, we'll not do anything
|
|
var select = NativeMethods.QuickLook.GetCurrentSelection();
|
|
if (_path == select)
|
|
return;
|
|
|
|
_path = select;
|
|
|
|
Debug.WriteLine($"SwitchPreview: {_path}");
|
|
|
|
InvokeViewer();
|
|
}
|
|
|
|
private void SwitchPreviewRemoteInvoke(HeartbeatEventArgs e)
|
|
{
|
|
// if the switch has been done by SwitchPreview, we'll not do anything
|
|
if (e.FocusedFile == _path)
|
|
return;
|
|
|
|
Debug.WriteLine($"SwitchPreviewRemoteInvoke: {e.FocusedFile}");
|
|
|
|
if (string.IsNullOrEmpty(e.FocusedFile))
|
|
return;
|
|
|
|
_currentMainWindow?.Dispatcher.BeginInvoke(new Action(SwitchPreview), DispatcherPriority.ApplicationIdle);
|
|
}
|
|
|
|
private void RunFocusMonitor()
|
|
{
|
|
if (!FocusMonitor.GetInstance().IsRunning)
|
|
{
|
|
FocusMonitor.GetInstance().Start();
|
|
FocusMonitor.GetInstance().Heartbeat += SwitchPreviewRemoteInvoke;
|
|
}
|
|
}
|
|
|
|
private void StopFocusMonitor()
|
|
{
|
|
if (FocusMonitor.GetInstance().IsRunning)
|
|
{
|
|
FocusMonitor.GetInstance().Stop();
|
|
FocusMonitor.GetInstance().Heartbeat -= SwitchPreviewRemoteInvoke;
|
|
}
|
|
}
|
|
|
|
internal bool InvokeViewer(string path = null, bool closeIfSame = false)
|
|
{
|
|
if(closeIfSame)
|
|
if (_currentMainWindow.Visibility == Visibility.Visible && path == _path)
|
|
{
|
|
ClosePreview();
|
|
return false;
|
|
}
|
|
|
|
if (path != null)
|
|
_path = path;
|
|
|
|
if (string.IsNullOrEmpty(_path))
|
|
return false;
|
|
if (!Directory.Exists(_path) && !File.Exists(_path))
|
|
return false;
|
|
|
|
RunFocusMonitor();
|
|
|
|
var matchedPlugin = PluginManager.GetInstance().FindMatch(_path);
|
|
|
|
BeginShowNewWindow(matchedPlugin);
|
|
|
|
return true;
|
|
}
|
|
|
|
private void BeginShowNewWindow(IViewer matchedPlugin)
|
|
{
|
|
_currentMainWindow.UnloadPlugin();
|
|
|
|
// switch window
|
|
var oldWindow = _currentMainWindow;
|
|
_currentMainWindow = matchedPlugin.AllowsTransparency
|
|
? _viewWindowTransparentTransparent
|
|
: _viewWindowNoTransparent;
|
|
if (!ReferenceEquals(oldWindow, _currentMainWindow))
|
|
oldWindow.BeginHide();
|
|
|
|
_currentMainWindow.BeginShow(matchedPlugin, _path, CurrentPluginFailed);
|
|
}
|
|
|
|
private void CurrentPluginFailed(ExceptionDispatchInfo e)
|
|
{
|
|
var plugin = _currentMainWindow.Plugin.GetType();
|
|
|
|
_currentMainWindow.BeginHide();
|
|
|
|
TrayIconManager.GetInstance().ShowNotification("", $"Failed to preview {Path.GetFileName(_path)}", true);
|
|
|
|
Debug.WriteLine(e.ToString());
|
|
Debug.WriteLine(e.SourceException.StackTrace);
|
|
|
|
if (plugin != PluginManager.GetInstance().DefaultPlugin.GetType())
|
|
BeginShowNewWindow(PluginManager.GetInstance().DefaultPlugin);
|
|
else
|
|
e.Throw();
|
|
}
|
|
|
|
internal static ViewWindowManager GetInstance()
|
|
{
|
|
return _instance ?? (_instance = new ViewWindowManager());
|
|
}
|
|
}
|
|
} |