-
-
Notifications
You must be signed in to change notification settings - Fork 45
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add navigation view and separate settings
- Loading branch information
Showing
18 changed files
with
1,465 additions
and
475 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
using System.Windows.Controls; | ||
using GenshinLyreMidiPlayer.ModernWPF.Animation; | ||
using GenshinLyreMidiPlayer.ViewModels; | ||
|
||
namespace GenshinLyreMidiPlayer.ModernWPF | ||
{ | ||
public class AnimatedContentControl : ContentControl | ||
{ | ||
private static Transition Transition => SettingsPageViewModel.Transition.Object; | ||
|
||
protected override void OnContentChanged(object? oldContent, object? newContent) | ||
{ | ||
if (oldContent != null) | ||
{ | ||
var exit = Transition.GetExitAnimation(oldContent, false); | ||
exit?.Begin(); | ||
} | ||
|
||
if (newContent != null) | ||
{ | ||
var enter = Transition.GetEnterAnimation(newContent, false); | ||
enter?.Begin(); | ||
} | ||
|
||
base.OnContentChanged(oldContent, newContent); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
using System; | ||
using System.Windows; | ||
using System.Windows.Media; | ||
using System.Windows.Media.Animation; | ||
|
||
namespace GenshinLyreMidiPlayer.ModernWPF.Animation | ||
{ | ||
public class Animation | ||
{ | ||
private static readonly BitmapCache _defaultBitmapCache; | ||
private readonly FrameworkElement _element; | ||
private readonly Storyboard _storyboard; | ||
private ClockState _currentState = ClockState.Stopped; | ||
|
||
static Animation() | ||
{ | ||
_defaultBitmapCache = new BitmapCache(); | ||
_defaultBitmapCache.Freeze(); | ||
} | ||
|
||
public Animation(FrameworkElement element, Storyboard storyboard) | ||
{ | ||
_element = element; | ||
_storyboard = storyboard; | ||
_storyboard.CurrentStateInvalidated += OnCurrentStateInvalidated; | ||
_storyboard.Completed += OnCompleted; | ||
} | ||
|
||
public event EventHandler Completed; | ||
|
||
public void Begin() | ||
{ | ||
if (!(_element.CacheMode is BitmapCache)) | ||
_element.SetCurrentValue(UIElement.CacheModeProperty, GetBitmapCache()); | ||
_storyboard.Begin(_element, true); | ||
} | ||
|
||
public void Stop() | ||
{ | ||
if (_currentState != ClockState.Stopped) _storyboard.Stop(_element); | ||
_element.InvalidateProperty(UIElement.CacheModeProperty); | ||
_element.InvalidateProperty(UIElement.RenderTransformProperty); | ||
_element.InvalidateProperty(UIElement.RenderTransformOriginProperty); | ||
} | ||
|
||
private void OnCurrentStateInvalidated(object sender, EventArgs e) | ||
{ | ||
if (sender is Clock clock) _currentState = clock.CurrentState; | ||
} | ||
|
||
private void OnCompleted(object sender, EventArgs e) | ||
{ | ||
Completed?.Invoke(this, EventArgs.Empty); | ||
} | ||
|
||
private BitmapCache GetBitmapCache() | ||
{ | ||
#if NETCOREAPP || NET462 | ||
return new BitmapCache(VisualTreeHelper.GetDpi(_element).PixelsPerDip); | ||
#else | ||
return _defaultBitmapCache; | ||
#endif | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
using System; | ||
using System.Windows; | ||
using System.Windows.Media.Animation; | ||
|
||
namespace GenshinLyreMidiPlayer.ModernWPF.Animation | ||
{ | ||
/// <summary> | ||
/// Provides parameter info for the Frame.Navigate method. Controls how the transition | ||
/// animation runs during the navigation action. | ||
/// </summary> | ||
public class Transition : DependencyObject | ||
{ | ||
internal static readonly KeySpline AccelerateKeySpline; | ||
internal static readonly KeySpline DecelerateKeySpline; | ||
internal static readonly PropertyPath OpacityPath = new PropertyPath(UIElement.OpacityProperty); | ||
|
||
internal static readonly PropertyPath TranslateXPath = | ||
new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"); | ||
|
||
internal static readonly PropertyPath TranslateYPath = | ||
new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"); | ||
|
||
internal static readonly PropertyPath ScaleXPath = | ||
new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleX)"); | ||
|
||
internal static readonly PropertyPath ScaleYPath = | ||
new PropertyPath("(UIElement.RenderTransform).(ScaleTransform.ScaleY)"); | ||
|
||
internal static readonly TimeSpan ExitDuration = TimeSpan.FromMilliseconds(150); | ||
internal static readonly TimeSpan EnterDuration = TimeSpan.FromMilliseconds(300); | ||
internal static readonly TimeSpan MaxMoveDuration = TimeSpan.FromMilliseconds(500); | ||
|
||
static Transition() | ||
{ | ||
AccelerateKeySpline = new KeySpline(0.7, 0, 1, 0.5); | ||
AccelerateKeySpline.Freeze(); | ||
|
||
DecelerateKeySpline = new KeySpline(0.1, 0.9, 0.2, 1); | ||
DecelerateKeySpline.Freeze(); | ||
} | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the Transition class. | ||
/// </summary> | ||
protected Transition() | ||
{ | ||
} | ||
|
||
//protected virtual string GetNavigationStateCore(); | ||
//protected virtual void SetNavigationStateCore(string navigationState); | ||
|
||
protected virtual Animation GetEnterAnimation(FrameworkElement element, bool movingBackwards) | ||
{ | ||
return null; | ||
} | ||
|
||
protected virtual Animation GetExitAnimation(FrameworkElement element, bool movingBackwards) | ||
{ | ||
return null; | ||
} | ||
|
||
public Animation GetEnterAnimation(object element, bool movingBackwards) | ||
{ | ||
return GetEnterAnimation( | ||
(FrameworkElement) element, movingBackwards); | ||
} | ||
|
||
public Animation GetExitAnimation(object element, bool movingBackwards) | ||
{ | ||
return GetExitAnimation( | ||
(FrameworkElement) element, movingBackwards); | ||
} | ||
} | ||
} |
18 changes: 18 additions & 0 deletions
18
GenshinLyreMidiPlayer/ModernWPF/Animation/TransitionCollection.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
using System.Collections.Generic; | ||
using GenshinLyreMidiPlayer.ModernWPF.Animation.Transitions; | ||
|
||
namespace GenshinLyreMidiPlayer.ModernWPF.Animation | ||
{ | ||
public class TransitionCollection : List<CaptionedObject<Transition>> | ||
{ | ||
public TransitionCollection() | ||
{ | ||
Add(new CaptionedObject<Transition>(new EntranceTransition(), "Entrance")); | ||
Add(new CaptionedObject<Transition>(new DrillInTransition(), "Drill in")); | ||
Add(new CaptionedObject<Transition>(new SlideTransition(Direction.FromLeft), "Slide from Left")); | ||
Add(new CaptionedObject<Transition>(new SlideTransition(Direction.FromRight), "Slide from Right")); | ||
Add(new CaptionedObject<Transition>(new SlideTransition(Direction.FromBottom), "Slide from Bottom")); | ||
Add(new CaptionedObject<Transition>(new SuppressTransition(), "Suppress")); | ||
} | ||
} | ||
} |
113 changes: 113 additions & 0 deletions
113
GenshinLyreMidiPlayer/ModernWPF/Animation/Transitions/DrillInTransition.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
using System; | ||
using System.Windows; | ||
using System.Windows.Media; | ||
using System.Windows.Media.Animation; | ||
|
||
namespace GenshinLyreMidiPlayer.ModernWPF.Animation.Transitions | ||
{ | ||
/// <summary> | ||
/// Specifies the animation to run when a user navigates forward in a logical hierarchy, | ||
/// like from a master list to a detail page. | ||
/// </summary> | ||
public sealed class DrillInTransition : Transition | ||
{ | ||
protected override Animation GetEnterAnimation(FrameworkElement element, bool movingBackwards) | ||
{ | ||
var storyboard = new Storyboard(); | ||
|
||
if (movingBackwards) | ||
{ | ||
var scaleXAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(1.15, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(1, EnterDuration, DecelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(scaleXAnim, ScaleXPath); | ||
storyboard.Children.Add(scaleXAnim); | ||
|
||
var scaleYAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(1.15, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(1, EnterDuration, DecelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(scaleYAnim, ScaleYPath); | ||
storyboard.Children.Add(scaleYAnim); | ||
|
||
var opacityAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(0, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(1, EnterDuration, DecelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(opacityAnim, OpacityPath); | ||
storyboard.Children.Add(opacityAnim); | ||
} | ||
else | ||
{ | ||
var scaleXAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(0.9, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(1, MaxMoveDuration, DecelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(scaleXAnim, ScaleXPath); | ||
storyboard.Children.Add(scaleXAnim); | ||
|
||
var scaleYAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(0.9, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(1, MaxMoveDuration, DecelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(scaleYAnim, ScaleYPath); | ||
storyboard.Children.Add(scaleYAnim); | ||
|
||
var opacityAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(0, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(1, MaxMoveDuration, DecelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(opacityAnim, OpacityPath); | ||
storyboard.Children.Add(opacityAnim); | ||
} | ||
|
||
element.SetCurrentValue(UIElement.RenderTransformProperty, new ScaleTransform()); | ||
element.SetCurrentValue(UIElement.RenderTransformOriginProperty, new Point(0.5, 0.5)); | ||
|
||
return new Animation(element, storyboard); | ||
} | ||
|
||
protected override Animation GetExitAnimation(FrameworkElement element, bool movingBackwards) | ||
{ | ||
var storyboard = new Storyboard(); | ||
|
||
var opacityAnim = new DoubleAnimationUsingKeyFrames | ||
{ | ||
KeyFrames = | ||
{ | ||
new DiscreteDoubleKeyFrame(1, TimeSpan.Zero), | ||
new SplineDoubleKeyFrame(0, ExitDuration, AccelerateKeySpline) | ||
} | ||
}; | ||
Storyboard.SetTargetProperty(opacityAnim, OpacityPath); | ||
storyboard.Children.Add(opacityAnim); | ||
|
||
return new Animation(element, storyboard); | ||
} | ||
} | ||
} |
Oops, something went wrong.