Projektdateien hinzufügen.
This commit is contained in:
726
VideoBrowser/Controls/AdornedControl/AdornedControl.cs
Normal file
726
VideoBrowser/Controls/AdornedControl/AdornedControl.cs
Normal file
@@ -0,0 +1,726 @@
|
||||
using System;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Animation;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace VideoBrowser.Controls.AdornedControl
|
||||
{
|
||||
/// <summary>
|
||||
/// A content control that allows an adorner for the content to
|
||||
/// be defined in XAML.
|
||||
/// </summary>
|
||||
public class AdornedControl : ContentControl
|
||||
{
|
||||
#region Dependency Properties
|
||||
|
||||
/// <summary>
|
||||
/// Dependency properties.
|
||||
/// </summary>
|
||||
public static readonly DependencyProperty IsAdornerVisibleProperty =
|
||||
DependencyProperty.Register("IsAdornerVisible", typeof(bool), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(IsAdornerVisible_PropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty AdornerContentProperty =
|
||||
DependencyProperty.Register("AdornerContent", typeof(FrameworkElement), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(AdornerContent_PropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty HorizontalAdornerPlacementProperty =
|
||||
DependencyProperty.Register("HorizontalAdornerPlacement", typeof(AdornerPlacement), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(AdornerPlacement.Inside));
|
||||
|
||||
public static readonly DependencyProperty VerticalAdornerPlacementProperty =
|
||||
DependencyProperty.Register("VerticalAdornerPlacement", typeof(AdornerPlacement), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(AdornerPlacement.Inside));
|
||||
|
||||
public static readonly DependencyProperty AdornerOffsetXProperty =
|
||||
DependencyProperty.Register("AdornerOffsetX", typeof(double), typeof(AdornedControl));
|
||||
|
||||
public static readonly DependencyProperty AdornerOffsetYProperty =
|
||||
DependencyProperty.Register("AdornerOffsetY", typeof(double), typeof(AdornedControl));
|
||||
|
||||
public static readonly DependencyProperty IsMouseOverShowEnabledProperty =
|
||||
DependencyProperty.Register("IsMouseOverShowEnabled", typeof(bool), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(true, IsMouseOverShowEnabled_PropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty FadeInTimeProperty =
|
||||
DependencyProperty.Register("FadeInTime", typeof(double), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(0.25));
|
||||
|
||||
public static readonly DependencyProperty FadeOutTimeProperty =
|
||||
DependencyProperty.Register("FadeOutTime", typeof(double), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(1.0));
|
||||
|
||||
public static readonly DependencyProperty CloseAdornerTimeOutProperty =
|
||||
DependencyProperty.Register("CloseAdornerTimeOut", typeof(double), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(2.0, CloseAdornerTimeOut_PropertyChanged));
|
||||
|
||||
public static readonly DependencyProperty AdornedTemplatePartNameProperty =
|
||||
DependencyProperty.Register("AdornedTemplatePartName", typeof(string), typeof(AdornedControl),
|
||||
new FrameworkPropertyMetadata(null));
|
||||
|
||||
#endregion Dependency Properties
|
||||
|
||||
#region Commands
|
||||
|
||||
/// <summary>
|
||||
/// Commands.
|
||||
/// </summary>
|
||||
public static readonly RoutedCommand ShowAdornerCommand = new RoutedCommand("ShowAdorner", typeof(AdornedControl));
|
||||
|
||||
public static readonly RoutedCommand FadeInAdornerCommand = new RoutedCommand("FadeInAdorner", typeof(AdornedControl));
|
||||
public static readonly RoutedCommand HideAdornerCommand = new RoutedCommand("HideAdorner", typeof(AdornedControl));
|
||||
public static readonly RoutedCommand FadeOutAdornerCommand = new RoutedCommand("FadeOutAdorner", typeof(AdornedControl));
|
||||
|
||||
#endregion Commands
|
||||
|
||||
public AdornedControl()
|
||||
{
|
||||
this.Focusable = false; // By default don't want 'AdornedControl' to be focusable.
|
||||
|
||||
this.DataContextChanged += new DependencyPropertyChangedEventHandler(AdornedControl_DataContextChanged);
|
||||
|
||||
closeAdornerTimer.Tick += new EventHandler(closeAdornerTimer_Tick);
|
||||
closeAdornerTimer.Interval = TimeSpan.FromSeconds(CloseAdornerTimeOut);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Show the adorner.
|
||||
/// </summary>
|
||||
public void ShowAdorner()
|
||||
{
|
||||
IsAdornerVisible = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Hide the adorner.
|
||||
/// </summary>
|
||||
public void HideAdorner()
|
||||
{
|
||||
IsAdornerVisible = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fade the adorner in and make it visible.
|
||||
/// </summary>
|
||||
public void FadeInAdorner()
|
||||
{
|
||||
if (adornerShowState == AdornerShowState.Visible ||
|
||||
adornerShowState == AdornerShowState.FadingIn)
|
||||
{
|
||||
// Already visible or fading in.
|
||||
return;
|
||||
}
|
||||
|
||||
this.ShowAdorner();
|
||||
|
||||
if (adornerShowState != AdornerShowState.FadingOut)
|
||||
{
|
||||
adorner.Opacity = 0.0;
|
||||
}
|
||||
|
||||
DoubleAnimation doubleAnimation = new DoubleAnimation(1.0, new Duration(TimeSpan.FromSeconds(FadeInTime)));
|
||||
doubleAnimation.Completed += new EventHandler(fadeInAnimation_Completed);
|
||||
doubleAnimation.Freeze();
|
||||
|
||||
adorner.BeginAnimation(FrameworkElement.OpacityProperty, doubleAnimation);
|
||||
|
||||
adornerShowState = AdornerShowState.FadingIn;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fade the adorner out and make it visible.
|
||||
/// </summary>
|
||||
public void FadeOutAdorner()
|
||||
{
|
||||
if (adornerShowState == AdornerShowState.FadingOut)
|
||||
{
|
||||
//
|
||||
// Already fading out.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
if (adornerShowState == AdornerShowState.Hidden)
|
||||
{
|
||||
//
|
||||
// Adorner has already been hidden.
|
||||
//
|
||||
return;
|
||||
}
|
||||
|
||||
DoubleAnimation fadeOutAnimation = new DoubleAnimation(0.0, new Duration(TimeSpan.FromSeconds(FadeOutTime)));
|
||||
fadeOutAnimation.Completed += new EventHandler(fadeOutAnimation_Completed);
|
||||
fadeOutAnimation.Freeze();
|
||||
|
||||
adorner.BeginAnimation(FrameworkElement.OpacityProperty, fadeOutAnimation);
|
||||
|
||||
adornerShowState = AdornerShowState.FadingOut;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shows or hides the adorner.
|
||||
/// Set to 'true' to show the adorner or 'false' to hide the adorner.
|
||||
/// </summary>
|
||||
public bool IsAdornerVisible
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)GetValue(IsAdornerVisibleProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(IsAdornerVisibleProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used in XAML to define the UI content of the adorner.
|
||||
/// </summary>
|
||||
public FrameworkElement AdornerContent
|
||||
{
|
||||
get
|
||||
{
|
||||
return (FrameworkElement)GetValue(AdornerContentProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(AdornerContentProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the horizontal placement of the adorner relative to the adorned control.
|
||||
/// </summary>
|
||||
public AdornerPlacement HorizontalAdornerPlacement
|
||||
{
|
||||
get
|
||||
{
|
||||
return (AdornerPlacement)GetValue(HorizontalAdornerPlacementProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(HorizontalAdornerPlacementProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the vertical placement of the adorner relative to the adorned control.
|
||||
/// </summary>
|
||||
public AdornerPlacement VerticalAdornerPlacement
|
||||
{
|
||||
get
|
||||
{
|
||||
return (AdornerPlacement)GetValue(VerticalAdornerPlacementProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(VerticalAdornerPlacementProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// X offset of the adorner.
|
||||
/// </summary>
|
||||
public double AdornerOffsetX
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)GetValue(AdornerOffsetXProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(AdornerOffsetXProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Y offset of the adorner.
|
||||
/// </summary>
|
||||
public double AdornerOffsetY
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)GetValue(AdornerOffsetYProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(AdornerOffsetYProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set to 'true' to make the adorner automatically fade-in and become visible when the mouse is hovered
|
||||
/// over the adorned control. Also the adorner automatically fades-out when the mouse cursor is moved
|
||||
/// aware from the adorned control (and the adorner).
|
||||
/// </summary>
|
||||
public bool IsMouseOverShowEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return (bool)GetValue(IsMouseOverShowEnabledProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(IsMouseOverShowEnabledProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the time (in seconds) it takes to fade in the adorner.
|
||||
/// </summary>
|
||||
public double FadeInTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)GetValue(FadeInTimeProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(FadeInTimeProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the time (in seconds) it takes to fade out the adorner.
|
||||
/// </summary>
|
||||
public double FadeOutTime
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)GetValue(FadeOutTimeProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(FadeOutTimeProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the time (in seconds) after the mouse cursor moves away from the
|
||||
/// adorned control (or the adorner) when the adorner begins to fade out.
|
||||
/// </summary>
|
||||
public double CloseAdornerTimeOut
|
||||
{
|
||||
get
|
||||
{
|
||||
return (double)GetValue(CloseAdornerTimeOutProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(CloseAdornerTimeOutProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// By default this property is set to null.
|
||||
/// When set to non-null it specifies the part name of a UI element
|
||||
/// in the visual tree of the AdornedControl content that is to be adorned.
|
||||
/// When this property is null it is the AdornerControl content that is adorned,
|
||||
/// however when it is set the visual-tree is searched for a UI element that has the
|
||||
/// specified part name, if the part is found then that UI element is adorned, otherwise
|
||||
/// an exception "Failed to find part ..." is thrown. ///
|
||||
/// </summary>
|
||||
public string AdornedTemplatePartName
|
||||
{
|
||||
get
|
||||
{
|
||||
return (string)GetValue(AdornedTemplatePartNameProperty);
|
||||
}
|
||||
set
|
||||
{
|
||||
SetValue(AdornedTemplatePartNameProperty, value);
|
||||
}
|
||||
}
|
||||
|
||||
#region Private Data Members
|
||||
|
||||
/// <summary>
|
||||
/// Command bindings.
|
||||
/// </summary>
|
||||
private static readonly CommandBinding ShowAdornerCommandBinding = new CommandBinding(ShowAdornerCommand, ShowAdornerCommand_Executed);
|
||||
|
||||
private static readonly CommandBinding FadeInAdornerCommandBinding = new CommandBinding(FadeInAdornerCommand, FadeInAdornerCommand_Executed);
|
||||
private static readonly CommandBinding HideAdornerCommandBinding = new CommandBinding(HideAdornerCommand, HideAdornerCommand_Executed);
|
||||
private static readonly CommandBinding FadeOutAdornerCommandBinding = new CommandBinding(FadeInAdornerCommand, FadeOutAdornerCommand_Executed);
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the current show/hide state of the adorner.
|
||||
/// </summary>
|
||||
private enum AdornerShowState
|
||||
{
|
||||
Visible,
|
||||
Hidden,
|
||||
FadingIn,
|
||||
FadingOut,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the current show/hide state of the adorner.
|
||||
/// </summary>
|
||||
private AdornerShowState adornerShowState = AdornerShowState.Hidden;
|
||||
|
||||
/// <summary>
|
||||
/// Caches the adorner layer.
|
||||
/// </summary>
|
||||
private AdornerLayer adornerLayer = null;
|
||||
|
||||
/// <summary>
|
||||
/// The actual adorner create to contain our 'adorner UI content'.
|
||||
/// </summary>
|
||||
private FrameworkElementAdorner adorner = null;
|
||||
|
||||
/// <summary>
|
||||
/// This timer is used to fade out and close the adorner.
|
||||
/// </summary>
|
||||
private DispatcherTimer closeAdornerTimer = new DispatcherTimer();
|
||||
|
||||
#endregion Private Data Members
|
||||
|
||||
#region Private/Internal Functions
|
||||
|
||||
/// <summary>
|
||||
/// Static constructor to register command bindings.
|
||||
/// </summary>
|
||||
static AdornedControl()
|
||||
{
|
||||
CommandManager.RegisterClassCommandBinding(typeof(AdornedControl), ShowAdornerCommandBinding);
|
||||
CommandManager.RegisterClassCommandBinding(typeof(AdornedControl), FadeOutAdornerCommandBinding);
|
||||
CommandManager.RegisterClassCommandBinding(typeof(AdornedControl), HideAdornerCommandBinding);
|
||||
CommandManager.RegisterClassCommandBinding(typeof(AdornedControl), FadeInAdornerCommandBinding);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the DataContext of the adorned control changes.
|
||||
/// </summary>
|
||||
private void AdornedControl_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
UpdateAdornerDataContext();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the DataContext of the adorner from the adorned control.
|
||||
/// </summary>
|
||||
private void UpdateAdornerDataContext()
|
||||
{
|
||||
if (this.AdornerContent != null)
|
||||
{
|
||||
this.AdornerContent.DataContext = this.DataContext;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the Show command is executed.
|
||||
/// </summary>
|
||||
private static void ShowAdornerCommand_Executed(object target, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)target;
|
||||
c.ShowAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the FadeIn command is executed.
|
||||
/// </summary>
|
||||
private static void FadeInAdornerCommand_Executed(object target, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)target;
|
||||
c.FadeOutAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the Hide command is executed.
|
||||
/// </summary>
|
||||
private static void HideAdornerCommand_Executed(object target, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)target;
|
||||
c.HideAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the FadeOut command is executed.
|
||||
/// </summary>
|
||||
private static void FadeOutAdornerCommand_Executed(object target, ExecutedRoutedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)target;
|
||||
c.FadeOutAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the value of IsAdornerVisible has changed.
|
||||
/// </summary>
|
||||
private static void IsAdornerVisible_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)o;
|
||||
c.ShowOrHideAdornerInternal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the IsMouseOverShowEnabled property has changed.
|
||||
/// </summary>
|
||||
private static void IsMouseOverShowEnabled_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)o;
|
||||
c.closeAdornerTimer.Stop();
|
||||
c.HideAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the CloseAdornerTimeOut property has change.
|
||||
/// </summary>
|
||||
private static void CloseAdornerTimeOut_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)o;
|
||||
c.closeAdornerTimer.Interval = TimeSpan.FromSeconds(c.CloseAdornerTimeOut);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the value of AdornerContent has changed.
|
||||
/// </summary>
|
||||
private static void AdornerContent_PropertyChanged(DependencyObject o, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
AdornedControl c = (AdornedControl)o;
|
||||
c.ShowOrHideAdornerInternal();
|
||||
|
||||
FrameworkElement oldAdornerContent = (FrameworkElement)e.OldValue;
|
||||
if (oldAdornerContent != null)
|
||||
{
|
||||
oldAdornerContent.MouseEnter -= new MouseEventHandler(c.adornerContent_MouseEnter);
|
||||
oldAdornerContent.MouseLeave -= new MouseEventHandler(c.adornerContent_MouseLeave);
|
||||
}
|
||||
|
||||
FrameworkElement newAdornerContent = (FrameworkElement)e.NewValue;
|
||||
if (newAdornerContent != null)
|
||||
{
|
||||
newAdornerContent.MouseEnter += new MouseEventHandler(c.adornerContent_MouseEnter);
|
||||
newAdornerContent.MouseLeave += new MouseEventHandler(c.adornerContent_MouseLeave);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the mouse cursor enters the area of the adorner.
|
||||
/// </summary>
|
||||
private void adornerContent_MouseEnter(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseEnterLogic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the mouse cursor leaves the area of the adorner.
|
||||
/// </summary>
|
||||
private void adornerContent_MouseLeave(object sender, MouseEventArgs e)
|
||||
{
|
||||
MouseLeaveLogic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method to show or hide the adorner based on the value of IsAdornerVisible.
|
||||
/// </summary>
|
||||
private void ShowOrHideAdornerInternal()
|
||||
{
|
||||
if (IsAdornerVisible)
|
||||
{
|
||||
ShowAdornerInternal();
|
||||
}
|
||||
else
|
||||
{
|
||||
HideAdornerInternal();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finds a child element in the visual tree that has the specified name.
|
||||
/// Returns null if no child with that name exists.
|
||||
/// </summary>
|
||||
public static FrameworkElement FindNamedChild(FrameworkElement rootElement, string childName)
|
||||
{
|
||||
int numChildren = VisualTreeHelper.GetChildrenCount(rootElement);
|
||||
for (int i = 0; i < numChildren; ++i)
|
||||
{
|
||||
DependencyObject child = VisualTreeHelper.GetChild(rootElement, i);
|
||||
FrameworkElement childElement = child as FrameworkElement;
|
||||
if (childElement != null && childElement.Name == childName)
|
||||
{
|
||||
return childElement;
|
||||
}
|
||||
|
||||
FrameworkElement foundElement = FindNamedChild(childElement, childName);
|
||||
if (foundElement != null)
|
||||
{
|
||||
return foundElement;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method to show the adorner.
|
||||
/// </summary>
|
||||
private void ShowAdornerInternal()
|
||||
{
|
||||
if (this.adorner != null)
|
||||
{
|
||||
// Already adorned.
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.AdornerContent != null)
|
||||
{
|
||||
if (this.adornerLayer == null)
|
||||
{
|
||||
this.adornerLayer = AdornerLayer.GetAdornerLayer(this);
|
||||
}
|
||||
|
||||
if (this.adornerLayer != null)
|
||||
{
|
||||
FrameworkElement adornedControl = this; // The control to be adorned defaults to 'this'.
|
||||
|
||||
if (!string.IsNullOrEmpty(this.AdornedTemplatePartName))
|
||||
{
|
||||
//
|
||||
// If 'AdornedTemplatePartName' is set to a valid string then search the visual-tree
|
||||
// for a UI element that has the specified part name. If we find it then use it as the
|
||||
// adorned control, otherwise throw an exception.
|
||||
//
|
||||
adornedControl = FindNamedChild(this, this.AdornedTemplatePartName);
|
||||
if (adornedControl == null)
|
||||
{
|
||||
throw new ApplicationException("Failed to find a FrameworkElement in the visual-tree with the part name '" + this.AdornedTemplatePartName + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
this.adorner = new FrameworkElementAdorner(this.AdornerContent, adornedControl,
|
||||
this.HorizontalAdornerPlacement, this.VerticalAdornerPlacement,
|
||||
this.AdornerOffsetX, this.AdornerOffsetY);
|
||||
this.adornerLayer.Add(this.adorner);
|
||||
|
||||
UpdateAdornerDataContext();
|
||||
}
|
||||
}
|
||||
|
||||
this.adornerShowState = AdornerShowState.Visible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Internal method to hide the adorner.
|
||||
/// </summary>
|
||||
private void HideAdornerInternal()
|
||||
{
|
||||
if (this.adornerLayer == null || this.adorner == null)
|
||||
{
|
||||
// Not already adorned.
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Stop the timer that might be about to fade out the adorner.
|
||||
//
|
||||
closeAdornerTimer.Stop();
|
||||
this.adornerLayer.Remove(this.adorner);
|
||||
this.adorner.DisconnectChild();
|
||||
|
||||
this.adorner = null;
|
||||
this.adornerLayer = null;
|
||||
|
||||
//
|
||||
// Ensure that the state of the adorned control reflects that
|
||||
// the the adorner is no longer.
|
||||
//
|
||||
this.adornerShowState = AdornerShowState.Hidden;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called to build the visual tree.
|
||||
/// </summary>
|
||||
public override void OnApplyTemplate()
|
||||
{
|
||||
base.OnApplyTemplate();
|
||||
|
||||
ShowOrHideAdornerInternal();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the mouse cursor enters the area of the adorned control.
|
||||
/// </summary>
|
||||
protected override void OnMouseEnter(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseEnter(e);
|
||||
|
||||
MouseEnterLogic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the mouse cursor leaves the area of the adorned control.
|
||||
/// </summary>
|
||||
protected override void OnMouseLeave(MouseEventArgs e)
|
||||
{
|
||||
base.OnMouseLeave(e);
|
||||
|
||||
MouseLeaveLogic();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shared mouse enter code.
|
||||
/// </summary>
|
||||
private void MouseEnterLogic()
|
||||
{
|
||||
if (!IsMouseOverShowEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
closeAdornerTimer.Stop();
|
||||
|
||||
FadeInAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Shared mouse leave code.
|
||||
/// </summary>
|
||||
private void MouseLeaveLogic()
|
||||
{
|
||||
if (!IsMouseOverShowEnabled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
closeAdornerTimer.Start();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when the close adorner time-out has ellapsed, the mouse has moved
|
||||
/// away from the adorned control and the adorner and it is time to close the adorner.
|
||||
/// </summary>
|
||||
private void closeAdornerTimer_Tick(object sender, EventArgs e)
|
||||
{
|
||||
closeAdornerTimer.Stop();
|
||||
|
||||
FadeOutAdorner();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the fade in animation has completed.
|
||||
/// </summary>
|
||||
private void fadeInAnimation_Completed(object sender, EventArgs e)
|
||||
{
|
||||
adornerShowState = AdornerShowState.Visible;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the fade-out animation has completed.
|
||||
/// </summary>
|
||||
private void fadeOutAnimation_Completed(object sender, EventArgs e)
|
||||
{
|
||||
if (adornerShowState == AdornerShowState.FadingOut)
|
||||
{
|
||||
// Still fading out, eg it wasn't aborted.
|
||||
this.HideAdorner();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Private/Internal Functions
|
||||
}
|
||||
}
|
||||
22
VideoBrowser/Controls/AdornedControl/AdornerPlacement.cs
Normal file
22
VideoBrowser/Controls/AdornedControl/AdornerPlacement.cs
Normal file
@@ -0,0 +1,22 @@
|
||||
namespace VideoBrowser.Controls.AdornedControl
|
||||
{
|
||||
#region Enums
|
||||
|
||||
/// <summary>
|
||||
/// Specifies the placement of the adorner in related to the adorned control.
|
||||
/// </summary>
|
||||
public enum AdornerPlacement
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines the Inside.
|
||||
/// </summary>
|
||||
Inside,
|
||||
|
||||
/// <summary>
|
||||
/// Defines the Outside.
|
||||
/// </summary>
|
||||
Outside
|
||||
}
|
||||
|
||||
#endregion Enums
|
||||
}
|
||||
334
VideoBrowser/Controls/AdornedControl/FrameworkElementAdorner.cs
Normal file
334
VideoBrowser/Controls/AdornedControl/FrameworkElementAdorner.cs
Normal file
@@ -0,0 +1,334 @@
|
||||
//
|
||||
// This code based on code available here:
|
||||
//
|
||||
// http://www.codeproject.com/KB/WPF/WPFJoshSmith.aspx
|
||||
//
|
||||
namespace VideoBrowser.Controls.AdornedControl
|
||||
{
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Windows;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
|
||||
//
|
||||
// This class is an adorner that allows a FrameworkElement derived class to adorn another FrameworkElement.
|
||||
//
|
||||
public class FrameworkElementAdorner : Adorner
|
||||
{
|
||||
//
|
||||
// The framework element that is the adorner.
|
||||
//
|
||||
private FrameworkElement child;
|
||||
|
||||
//
|
||||
// Placement of the child.
|
||||
//
|
||||
private readonly AdornerPlacement horizontalAdornerPlacement = AdornerPlacement.Inside;
|
||||
|
||||
private readonly AdornerPlacement verticalAdornerPlacement = AdornerPlacement.Inside;
|
||||
|
||||
//
|
||||
// Offset of the child.
|
||||
//
|
||||
private readonly double offsetX = 0.0;
|
||||
|
||||
private readonly double offsetY = 0.0;
|
||||
|
||||
//
|
||||
// Position of the child (when not set to NaN).
|
||||
//
|
||||
private double positionX = Double.NaN;
|
||||
|
||||
private double positionY = Double.NaN;
|
||||
|
||||
public FrameworkElementAdorner(FrameworkElement adornerChildElement, FrameworkElement adornedElement)
|
||||
: base(adornedElement)
|
||||
{
|
||||
this.child = adornerChildElement;
|
||||
|
||||
base.AddLogicalChild(adornerChildElement);
|
||||
base.AddVisualChild(adornerChildElement);
|
||||
}
|
||||
|
||||
public FrameworkElementAdorner(FrameworkElement adornerChildElement, FrameworkElement adornedElement,
|
||||
AdornerPlacement horizontalAdornerPlacement, AdornerPlacement verticalAdornerPlacement,
|
||||
double offsetX, double offsetY)
|
||||
: base(adornedElement)
|
||||
{
|
||||
this.child = adornerChildElement;
|
||||
this.horizontalAdornerPlacement = horizontalAdornerPlacement;
|
||||
this.verticalAdornerPlacement = verticalAdornerPlacement;
|
||||
this.offsetX = offsetX;
|
||||
this.offsetY = offsetY;
|
||||
|
||||
adornedElement.SizeChanged += new SizeChangedEventHandler(adornedElement_SizeChanged);
|
||||
|
||||
base.AddLogicalChild(adornerChildElement);
|
||||
base.AddVisualChild(adornerChildElement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Event raised when the adorned control's size has changed.
|
||||
/// </summary>
|
||||
private void adornedElement_SizeChanged(object sender, SizeChangedEventArgs e)
|
||||
{
|
||||
InvalidateMeasure();
|
||||
}
|
||||
|
||||
//
|
||||
// Position of the child (when not set to NaN).
|
||||
//
|
||||
public double PositionX
|
||||
{
|
||||
get
|
||||
{
|
||||
return positionX;
|
||||
}
|
||||
set
|
||||
{
|
||||
positionX = value;
|
||||
}
|
||||
}
|
||||
|
||||
public double PositionY
|
||||
{
|
||||
get
|
||||
{
|
||||
return positionY;
|
||||
}
|
||||
set
|
||||
{
|
||||
positionY = value;
|
||||
}
|
||||
}
|
||||
|
||||
protected override Size MeasureOverride(Size constraint)
|
||||
{
|
||||
this.child.Measure(constraint);
|
||||
return this.child.DesiredSize;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the X coordinate of the child.
|
||||
/// </summary>
|
||||
private double DetermineX()
|
||||
{
|
||||
switch (child.HorizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Left:
|
||||
{
|
||||
if (horizontalAdornerPlacement == AdornerPlacement.Outside)
|
||||
{
|
||||
return -child.DesiredSize.Width + offsetX;
|
||||
}
|
||||
else
|
||||
{
|
||||
return offsetX;
|
||||
}
|
||||
}
|
||||
case HorizontalAlignment.Right:
|
||||
{
|
||||
if (horizontalAdornerPlacement == AdornerPlacement.Outside)
|
||||
{
|
||||
double adornedWidth = AdornedElement.ActualWidth;
|
||||
return adornedWidth + offsetX;
|
||||
}
|
||||
else
|
||||
{
|
||||
double adornerWidth = this.child.DesiredSize.Width;
|
||||
double adornedWidth = AdornedElement.ActualWidth;
|
||||
double x = adornedWidth - adornerWidth;
|
||||
return x + offsetX;
|
||||
}
|
||||
}
|
||||
case HorizontalAlignment.Center:
|
||||
{
|
||||
double adornerWidth = this.child.DesiredSize.Width;
|
||||
double adornedWidth = AdornedElement.ActualWidth;
|
||||
double x = (adornedWidth / 2) - (adornerWidth / 2);
|
||||
return x + offsetX;
|
||||
}
|
||||
case HorizontalAlignment.Stretch:
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the Y coordinate of the child.
|
||||
/// </summary>
|
||||
private double DetermineY()
|
||||
{
|
||||
switch (child.VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Top:
|
||||
{
|
||||
if (verticalAdornerPlacement == AdornerPlacement.Outside)
|
||||
{
|
||||
return -child.DesiredSize.Height + offsetY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return offsetY;
|
||||
}
|
||||
}
|
||||
case VerticalAlignment.Bottom:
|
||||
{
|
||||
if (verticalAdornerPlacement == AdornerPlacement.Outside)
|
||||
{
|
||||
double adornedHeight = AdornedElement.ActualHeight;
|
||||
return adornedHeight + offsetY;
|
||||
}
|
||||
else
|
||||
{
|
||||
double adornerHeight = this.child.DesiredSize.Height;
|
||||
double adornedHeight = AdornedElement.ActualHeight;
|
||||
double x = adornedHeight - adornerHeight;
|
||||
return x + offsetY;
|
||||
}
|
||||
}
|
||||
case VerticalAlignment.Center:
|
||||
{
|
||||
double adornerHeight = this.child.DesiredSize.Height;
|
||||
double adornedHeight = AdornedElement.ActualHeight;
|
||||
double x = (adornedHeight / 2) - (adornerHeight / 2);
|
||||
return x + offsetY;
|
||||
}
|
||||
case VerticalAlignment.Stretch:
|
||||
{
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the width of the child.
|
||||
/// </summary>
|
||||
private double DetermineWidth()
|
||||
{
|
||||
if (!Double.IsNaN(PositionX))
|
||||
{
|
||||
return this.child.DesiredSize.Width;
|
||||
}
|
||||
|
||||
switch (child.HorizontalAlignment)
|
||||
{
|
||||
case HorizontalAlignment.Left:
|
||||
{
|
||||
return this.child.DesiredSize.Width;
|
||||
}
|
||||
case HorizontalAlignment.Right:
|
||||
{
|
||||
return this.child.DesiredSize.Width;
|
||||
}
|
||||
case HorizontalAlignment.Center:
|
||||
{
|
||||
return this.child.DesiredSize.Width;
|
||||
}
|
||||
case HorizontalAlignment.Stretch:
|
||||
{
|
||||
return AdornedElement.ActualWidth;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine the height of the child.
|
||||
/// </summary>
|
||||
private double DetermineHeight()
|
||||
{
|
||||
if (!Double.IsNaN(PositionY))
|
||||
{
|
||||
return this.child.DesiredSize.Height;
|
||||
}
|
||||
|
||||
switch (child.VerticalAlignment)
|
||||
{
|
||||
case VerticalAlignment.Top:
|
||||
{
|
||||
return this.child.DesiredSize.Height;
|
||||
}
|
||||
case VerticalAlignment.Bottom:
|
||||
{
|
||||
return this.child.DesiredSize.Height;
|
||||
}
|
||||
case VerticalAlignment.Center:
|
||||
{
|
||||
return this.child.DesiredSize.Height;
|
||||
}
|
||||
case VerticalAlignment.Stretch:
|
||||
{
|
||||
return AdornedElement.ActualHeight;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
protected override Size ArrangeOverride(Size finalSize)
|
||||
{
|
||||
double x = PositionX;
|
||||
if (Double.IsNaN(x))
|
||||
{
|
||||
x = DetermineX();
|
||||
}
|
||||
double y = PositionY;
|
||||
if (Double.IsNaN(y))
|
||||
{
|
||||
y = DetermineY();
|
||||
}
|
||||
double adornerWidth = DetermineWidth();
|
||||
double adornerHeight = DetermineHeight();
|
||||
this.child.Arrange(new Rect(x, y, adornerWidth, adornerHeight));
|
||||
return finalSize;
|
||||
}
|
||||
|
||||
protected override Int32 VisualChildrenCount
|
||||
{
|
||||
get { return 1; }
|
||||
}
|
||||
|
||||
protected override Visual GetVisualChild(Int32 index)
|
||||
{
|
||||
return this.child;
|
||||
}
|
||||
|
||||
protected override IEnumerator LogicalChildren
|
||||
{
|
||||
get
|
||||
{
|
||||
ArrayList list = new ArrayList();
|
||||
list.Add(this.child);
|
||||
return list.GetEnumerator();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Disconnect the child element from the visual tree so that it may be reused later.
|
||||
/// </summary>
|
||||
public void DisconnectChild()
|
||||
{
|
||||
base.RemoveLogicalChild(child);
|
||||
base.RemoveVisualChild(child);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Override AdornedElement from base class for less type-checking.
|
||||
/// </summary>
|
||||
public new FrameworkElement AdornedElement
|
||||
{
|
||||
get
|
||||
{
|
||||
return (FrameworkElement)base.AdornedElement;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user