mirror of
https://github.com/Hofknecht/SystemTrayMenu.git
synced 2024-10-03 10:36:30 +13:00
Refactored menu window fading
Improve TaskbarLogo (still flickers on load but only very shortly)
This commit is contained in:
parent
813912d08c
commit
81e20d618b
5 changed files with 135 additions and 263 deletions
|
@ -386,6 +386,16 @@ namespace SystemTrayMenu.Business
|
|||
return menuData;
|
||||
}
|
||||
|
||||
internal static void OpenFolder(string? path = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Config.Path;
|
||||
}
|
||||
|
||||
Log.ProcessStart(path);
|
||||
}
|
||||
|
||||
internal void SwitchOpenCloseByTaskbarItem()
|
||||
{
|
||||
SwitchOpenClose(true);
|
||||
|
@ -476,16 +486,6 @@ namespace SystemTrayMenu.Business
|
|||
}
|
||||
}
|
||||
|
||||
internal static void OpenFolder(string? path = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(path))
|
||||
{
|
||||
path = Config.Path;
|
||||
}
|
||||
|
||||
Log.ProcessStart(path);
|
||||
}
|
||||
|
||||
private static void LoadMenu(object senderDoWork, DoWorkEventArgs eDoWork)
|
||||
{
|
||||
string path;
|
||||
|
@ -1000,21 +1000,24 @@ namespace SystemTrayMenu.Business
|
|||
if (menuPrevious != null)
|
||||
{
|
||||
// Clean up menu status IsMenuOpen for previous one
|
||||
ListView dgvPrevious = menuPrevious.GetDataGridView();
|
||||
foreach (ListViewItemData item in dgvPrevious.Items)
|
||||
ListView? dgvPrevious = menuPrevious.GetDataGridView();
|
||||
if (dgvPrevious != null)
|
||||
{
|
||||
RowData rowDataToClear = item.data;
|
||||
if (rowDataToClear == (RowData)menuToShow.Tag)
|
||||
foreach (ListViewItemData item in dgvPrevious.Items)
|
||||
{
|
||||
rowDataToClear.IsMenuOpen = keepOrSetIsMenuOpen;
|
||||
RowData rowDataToClear = item.data;
|
||||
if (rowDataToClear == (RowData)menuToShow.Tag)
|
||||
{
|
||||
rowDataToClear.IsMenuOpen = keepOrSetIsMenuOpen;
|
||||
}
|
||||
else
|
||||
{
|
||||
rowDataToClear.IsMenuOpen = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
rowDataToClear.IsMenuOpen = false;
|
||||
}
|
||||
}
|
||||
|
||||
RefreshSelection(dgvPrevious);
|
||||
RefreshSelection(dgvPrevious);
|
||||
}
|
||||
|
||||
// Hide old menu
|
||||
foreach (Menu menuToClose in menus.Where(
|
||||
|
|
|
@ -1,157 +0,0 @@
|
|||
// <copyright file="Fading.cs" company="PlaceholderCompany">
|
||||
// Copyright (c) PlaceholderCompany. All rights reserved.
|
||||
// </copyright>
|
||||
|
||||
namespace SystemTrayMenu.Helper
|
||||
{
|
||||
using System;
|
||||
using System.Windows.Threading;
|
||||
|
||||
public class Fading
|
||||
{
|
||||
private const int Interval100FPS = 10; // 100fps=>1s/100fps=~10ms
|
||||
|
||||
private const double StepIn = 0.20;
|
||||
private const double StepOut = 0.10;
|
||||
private const double Transparent = 0.80;
|
||||
private const double TransparentMinus = 0.60; // Transparent - StepIn
|
||||
private const double TransparentPlus = 0.85; // Transparent + StepOut
|
||||
private const double Shown = 1.00;
|
||||
private const double ShownMinus = 0.80; // Shown - StepIn
|
||||
|
||||
private readonly DispatcherTimer timer = new(DispatcherPriority.Render);
|
||||
private FadingState state = FadingState.Idle;
|
||||
private double opacity;
|
||||
private bool visible;
|
||||
|
||||
internal Fading()
|
||||
{
|
||||
timer.Interval = TimeSpan.FromMilliseconds(Interval100FPS);
|
||||
timer.Tick += (sender, e) => FadeStep();
|
||||
}
|
||||
|
||||
internal event Action Hide;
|
||||
|
||||
internal event Action Show;
|
||||
|
||||
internal event EventHandler<double> ChangeOpacity;
|
||||
|
||||
internal enum FadingState
|
||||
{
|
||||
Idle,
|
||||
Show,
|
||||
ShowTransparent,
|
||||
Hide,
|
||||
}
|
||||
|
||||
internal bool IsHiding => state == FadingState.Hide;
|
||||
|
||||
internal void Fade(FadingState state)
|
||||
{
|
||||
StartStopTimer(state);
|
||||
}
|
||||
|
||||
private void StartStopTimer(FadingState newState)
|
||||
{
|
||||
if (newState == FadingState.Idle)
|
||||
{
|
||||
state = newState;
|
||||
timer.Stop();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = newState;
|
||||
timer.Start();
|
||||
}
|
||||
}
|
||||
|
||||
private void FadeStep()
|
||||
{
|
||||
switch (state)
|
||||
{
|
||||
case FadingState.Show:
|
||||
if (!visible)
|
||||
{
|
||||
visible = true;
|
||||
Show?.Invoke();
|
||||
opacity = 0;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
else if (Properties.Settings.Default.UseFading &&
|
||||
opacity < ShownMinus)
|
||||
{
|
||||
opacity += StepIn;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!Properties.Settings.Default.UseFading)
|
||||
{
|
||||
// #393 provoke a redraw for the CS_DROPSHADOW to work
|
||||
opacity = ShownMinus;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
|
||||
opacity = Shown;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
StartStopTimer(FadingState.Idle);
|
||||
}
|
||||
|
||||
break;
|
||||
case FadingState.ShowTransparent:
|
||||
if (!visible)
|
||||
{
|
||||
visible = true;
|
||||
Show?.Invoke();
|
||||
opacity = 0;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
else if (Properties.Settings.Default.UseFading &&
|
||||
opacity < TransparentMinus)
|
||||
{
|
||||
opacity += StepIn;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
else if (Properties.Settings.Default.UseFading &&
|
||||
opacity > TransparentPlus)
|
||||
{
|
||||
opacity -= StepOut;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
else
|
||||
{
|
||||
opacity = Transparent;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
StartStopTimer(FadingState.Idle);
|
||||
}
|
||||
|
||||
break;
|
||||
case FadingState.Hide:
|
||||
if (Properties.Settings.Default.UseFading &&
|
||||
opacity > StepOut)
|
||||
{
|
||||
opacity -= StepOut;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
}
|
||||
else if (visible)
|
||||
{
|
||||
opacity = 0;
|
||||
ChangeOpacity?.Invoke(this, opacity);
|
||||
visible = false;
|
||||
Hide?.Invoke();
|
||||
StartStopTimer(FadingState.Idle);
|
||||
}
|
||||
else
|
||||
{
|
||||
StartStopTimer(FadingState.Idle);
|
||||
}
|
||||
|
||||
break;
|
||||
case FadingState.Idle:
|
||||
default:
|
||||
StartStopTimer(FadingState.Idle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -16,13 +16,23 @@
|
|||
</Window.Effect>
|
||||
|
||||
<Window.Triggers>
|
||||
<EventTrigger RoutedEvent="Loaded">
|
||||
<EventTrigger RoutedEvent="local:Menu.FadeIn">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0.0" To="1.0" Duration="0:0:1" />
|
||||
<!-- Completed="fadeCompleted" -->
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="0.0" To="1.0" Duration="0:0:0.5"
|
||||
Completed="FadeIn_Completed"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
<EventTrigger RoutedEvent="local:Menu.FadeOut">
|
||||
<BeginStoryboard>
|
||||
<Storyboard>
|
||||
<DoubleAnimation
|
||||
Storyboard.TargetProperty="Opacity"
|
||||
From="1.0" To="0.0" Duration="0:0:0.25"
|
||||
Completed="FadeOut_Completed"/>
|
||||
</Storyboard>
|
||||
</BeginStoryboard>
|
||||
</EventTrigger>
|
||||
|
|
|
@ -26,13 +26,18 @@ namespace SystemTrayMenu.UserInterface
|
|||
/// </summary>
|
||||
public partial class Menu : Window
|
||||
{
|
||||
private const int CornerRadius = 10;
|
||||
|
||||
private static readonly RoutedEvent FadeInEvent = EventManager.RegisterRoutedEvent(
|
||||
nameof(FadeIn), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Menu));
|
||||
|
||||
private static readonly RoutedEvent FadeOutEvent = EventManager.RegisterRoutedEvent(
|
||||
nameof(FadeOut), RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(Menu));
|
||||
|
||||
#if TODO // SEARCH
|
||||
public const string RowFilterShowAll = "[SortIndex] LIKE '%0%'";
|
||||
#endif
|
||||
private const int CornerRadius = 10;
|
||||
|
||||
private readonly Fading fading = new();
|
||||
private bool isShowing;
|
||||
private bool isFading;
|
||||
private bool directionToRight;
|
||||
private bool mouseDown;
|
||||
private Point lastLocation;
|
||||
|
@ -48,56 +53,10 @@ namespace SystemTrayMenu.UserInterface
|
|||
timerUpdateIcons.Tick += TimerUpdateIcons_Tick;
|
||||
Closed += (_, _) =>
|
||||
{
|
||||
fading.Fade(Fading.FadingState.Idle);
|
||||
timerUpdateIcons.Stop();
|
||||
isClosed = true; // TODO WPF Replace Forms wrapper
|
||||
};
|
||||
|
||||
Opacity = 0D;
|
||||
fading.ChangeOpacity += Fading_ChangeOpacity;
|
||||
void Fading_ChangeOpacity(object? sender, double newOpacity)
|
||||
{
|
||||
if (newOpacity != Opacity && !IsDisposed && !Disposing)
|
||||
{
|
||||
Opacity = newOpacity;
|
||||
}
|
||||
}
|
||||
|
||||
fading.Show += Fading_Show;
|
||||
void Fading_Show()
|
||||
{
|
||||
try
|
||||
{
|
||||
isShowing = true;
|
||||
Visibility = Visibility.Visible;
|
||||
isShowing = false;
|
||||
timerUpdateIcons.Start();
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
{
|
||||
Visibility = Visibility.Hidden;
|
||||
isShowing = false;
|
||||
Log.Info($"Could not open menu, old menu was disposing," +
|
||||
$" IsDisposed={IsDisposed}");
|
||||
}
|
||||
|
||||
if (Visibility == Visibility.Visible)
|
||||
{
|
||||
if (Level == 0)
|
||||
{
|
||||
Activate();
|
||||
Show();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowActivated = false;
|
||||
Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fading.Hide += Hide;
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
Level = level;
|
||||
|
@ -220,6 +179,8 @@ namespace SystemTrayMenu.UserInterface
|
|||
Loaded += (sender, e) =>
|
||||
{
|
||||
NativeMethods.HideFromAltTab(this);
|
||||
|
||||
RaiseEvent(new(routedEvent: FadeInEvent));
|
||||
};
|
||||
|
||||
Closed += (sender, e) =>
|
||||
|
@ -263,6 +224,18 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
internal event Action<ListView, int, MouseButtonEventArgs>? CellMouseClick;
|
||||
|
||||
private event RoutedEventHandler FadeIn
|
||||
{
|
||||
add { AddHandler(FadeInEvent, value); }
|
||||
remove { RemoveHandler(FadeInEvent, value); }
|
||||
}
|
||||
|
||||
private event RoutedEventHandler FadeOut
|
||||
{
|
||||
add { AddHandler(FadeOutEvent, value); }
|
||||
remove { RemoveHandler(FadeOutEvent, value); }
|
||||
}
|
||||
|
||||
internal enum StartLocation
|
||||
{
|
||||
Predecessor,
|
||||
|
@ -283,13 +256,14 @@ namespace SystemTrayMenu.UserInterface
|
|||
|
||||
internal string? FolderPath { get; set; }
|
||||
|
||||
internal bool IsUsable => Visibility == Visibility.Visible && !fading.IsHiding && !IsDisposed && !Disposing;
|
||||
internal bool IsUsable => Visibility == Visibility.Visible && !isFading && !IsDisposed && !Disposing;
|
||||
|
||||
#if TODO // TOUCH
|
||||
internal bool ScrollbarVisible { get; private set; }
|
||||
|
||||
private ListView tableLayoutPanelDgvAndScrollbar => dgv; // TODO WPF Remove and replace with dgv
|
||||
#endif
|
||||
|
||||
internal void ResetSearchText()
|
||||
{
|
||||
textBoxSearch.Text = string.Empty;
|
||||
|
@ -450,21 +424,58 @@ namespace SystemTrayMenu.UserInterface
|
|||
}
|
||||
}
|
||||
|
||||
internal void ShowWithFade()
|
||||
{
|
||||
fading.Fade(Fading.FadingState.Show);
|
||||
}
|
||||
internal void ShowWithFade() => Fading_Show(false);
|
||||
|
||||
internal void ShowTransparent()
|
||||
internal void ShowTransparent() => Fading_Show(true);
|
||||
|
||||
internal void Fading_Show(bool transparency)
|
||||
{
|
||||
fading.Fade(Fading.FadingState.ShowTransparent);
|
||||
timerUpdateIcons.Start();
|
||||
|
||||
if (Level == 0)
|
||||
{
|
||||
Activate();
|
||||
}
|
||||
else
|
||||
{
|
||||
ShowActivated = false;
|
||||
}
|
||||
|
||||
Opacity = 0D;
|
||||
Show();
|
||||
|
||||
if (Settings.Default.UseFading)
|
||||
{
|
||||
isFading = true;
|
||||
if (transparency)
|
||||
{
|
||||
// TODO: FADING: Instead setting of opacity 100% only go up to 80% (Temporarily go to 100% as well)
|
||||
RaiseEvent(new(routedEvent: FadeInEvent));
|
||||
}
|
||||
else
|
||||
{
|
||||
RaiseEvent(new(routedEvent: FadeInEvent));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Opacity = transparency ? 0.80D : 1D;
|
||||
FadeIn_Completed(this, new());
|
||||
}
|
||||
}
|
||||
|
||||
internal void HideWithFade()
|
||||
{
|
||||
if (!isShowing)
|
||||
if (Settings.Default.UseFading)
|
||||
{
|
||||
fading.Fade(Fading.FadingState.Hide);
|
||||
isFading = true;
|
||||
|
||||
// TODO: FADING: Instead starting at opacity 100% it should start with 80% due to transparency setting
|
||||
RaiseEvent(new(routedEvent: FadeOutEvent));
|
||||
}
|
||||
else
|
||||
{
|
||||
FadeOut_Completed(this, new());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,7 +656,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
case StartLocation.Predecessor:
|
||||
|
||||
RowData trigger = (RowData)Tag;
|
||||
ListView dgv = menuPredecessor!.GetDataGridView()!;
|
||||
ListView dgv = menuPredecessor!.GetDataGridView() !;
|
||||
|
||||
// Set position on same height as the selected row from predecessor
|
||||
y = menuPredecessor.Location.Y;
|
||||
|
@ -758,7 +769,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
UpdateLayout();
|
||||
SizeToContent = SizeToContent.Manual;
|
||||
#if TODO // SEARCH
|
||||
dgvHeightSet = false;
|
||||
dgvHeightSet = false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
@ -770,9 +781,20 @@ namespace SystemTrayMenu.UserInterface
|
|||
labelStatus.Content = $"{filesAndFoldersCount} {Translator.GetText(elements)}";
|
||||
}
|
||||
|
||||
private void FadeIn_Completed(object sender, EventArgs e)
|
||||
{
|
||||
isFading = false;
|
||||
}
|
||||
|
||||
private void FadeOut_Completed(object sender, EventArgs e)
|
||||
{
|
||||
isFading = false;
|
||||
Hide();
|
||||
}
|
||||
|
||||
private void HandlePreviewKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
searchPanel.Visibility= Visibility.Visible;
|
||||
searchPanel.Visibility = Visibility.Visible;
|
||||
|
||||
ModifierKeys modifiers = Keyboard.Modifiers;
|
||||
switch (e.Key)
|
||||
|
@ -881,6 +903,7 @@ namespace SystemTrayMenu.UserInterface
|
|||
}
|
||||
|
||||
double factorIconSizeInPercent = Properties.Settings.Default.IconSizeInPercent / 100f;
|
||||
|
||||
// IcoWidth 100% = 21px, 175% is 33, +3+2 is padding from ColumnIcon
|
||||
double icoWidth = (16 * Scaling.FactorByDpi) + 5;
|
||||
Resources["ColumnIconWidth"] = (double)(int)((icoWidth * factorIconSizeInPercent * Scaling.Factor) + 0.5);
|
||||
|
|
|
@ -12,15 +12,12 @@ namespace SystemTrayMenu.UserInterface
|
|||
using System.Windows;
|
||||
using System.Windows.Interop;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Threading;
|
||||
|
||||
/// <summary>
|
||||
/// Logic of Taskbar window.
|
||||
/// </summary>
|
||||
public partial class TaskbarLogo : Window
|
||||
{
|
||||
private DispatcherTimer? moveOutOfScreenTimer = null;
|
||||
|
||||
public TaskbarLogo()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
@ -49,32 +46,28 @@ namespace SystemTrayMenu.UserInterface
|
|||
Title = myname;
|
||||
|
||||
Closed += (_, _) => Application.Current.Shutdown();
|
||||
Deactivated += (_, _) => SetStateNormal();
|
||||
Activated += (_, _) =>
|
||||
Deactivated += SetStateNormal;
|
||||
Activated += (object? sender, EventArgs e) =>
|
||||
{
|
||||
SetStateNormal();
|
||||
SetStateNormal(sender, e);
|
||||
Activate();
|
||||
UpdateLayout();
|
||||
Focus();
|
||||
moveOutOfScreenTimer = new DispatcherTimer(
|
||||
TimeSpan.FromMilliseconds(500),
|
||||
DispatcherPriority.Loaded,
|
||||
(s, e) =>
|
||||
{
|
||||
// Do this after loading because Top may be invalid at the beginning
|
||||
// and when initial rendering is out of screen it will never be actually painted.
|
||||
// This makes sure logo is rendered once and then window is moved.
|
||||
Top += SystemParameters.VirtualScreenHeight;
|
||||
((DispatcherTimer)s!).IsEnabled = false; // only once
|
||||
},
|
||||
Dispatcher.CurrentDispatcher);
|
||||
};
|
||||
ContentRendered += MoveOutOfScreen;
|
||||
}
|
||||
|
||||
private void MoveOutOfScreen(object? sender, EventArgs e)
|
||||
{
|
||||
// Do this only once
|
||||
ContentRendered -= MoveOutOfScreen;
|
||||
Top += SystemParameters.VirtualScreenHeight;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This ensures that next click on taskbaritem works as activate event/click event.
|
||||
/// </summary>
|
||||
private void SetStateNormal()
|
||||
private void SetStateNormal(object? sender, EventArgs e)
|
||||
{
|
||||
if (IsActive)
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue