using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Controls.Primitives;
using System.Windows.Media.Imaging;
namespace Tweened.Extensions
{
public static class GridExtension
{
#region Grid Properties - IsMaximizable, Transition, CurrentScreenShot
///
/// Defines if the Grid is Maximizable
///
///
///
public static bool GetIsMaximizable(DependencyObject obj)
{
return (bool)obj.GetValue(IsMaximizableProperty);
}
public static void SetIsMaximizable(DependencyObject obj, bool value)
{
obj.SetValue(IsMaximizableProperty, value);
}
// Using a DependencyProperty as the backing store for IsMaximizable. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsMaximizableProperty =
DependencyProperty.RegisterAttached("IsMaximizable", typeof(bool), typeof(Grid), new PropertyMetadata(false, null));
///
/// Contains the current bitmap ScreenShot
///
///
///
internal static ImageBrush GetCurrentScreenShot(DependencyObject obj)
{
return (ImageBrush)obj.GetValue(CurrentScreenShotProperty);
}
internal static void SetCurrentScreenShot(DependencyObject obj, ImageBrush value)
{
obj.SetValue(CurrentScreenShotProperty, value);
}
// Using a DependencyProperty as the backing store for CurrentScreenShot. This enables animation, styling, binding, etc...
internal static readonly DependencyProperty CurrentScreenShotProperty =
DependencyProperty.RegisterAttached("CurrentScreenShot", typeof(ImageBrush), typeof(Grid), new PropertyMetadata(null, null));
public static Brush GetSavedGridBackground(DependencyObject obj)
{
return (Brush)obj.GetValue(SavedGridBackgroundProperty);
}
public static void SetSavedGridBackground(DependencyObject obj, Brush value)
{
obj.SetValue(SavedGridBackgroundProperty, value);
}
// Using a DependencyProperty as the backing store for SavedGridBackground. This enables animation, styling, binding, etc...
public static readonly DependencyProperty SavedGridBackgroundProperty =
DependencyProperty.RegisterAttached("SavedGridBackground", typeof(Brush), typeof(Grid), null);
///
/// Contains current transition
///
///
///
internal static Storyboard GetTransition(DependencyObject obj)
{
return (Storyboard)obj.GetValue(TransitionProperty);
}
internal static void SetTransition(DependencyObject obj, Storyboard value)
{
obj.SetValue(TransitionProperty, value);
}
// Using a DependencyProperty as the backing store for Transition. This enables animation, styling, binding, etc...
internal static readonly DependencyProperty TransitionProperty =
DependencyProperty.RegisterAttached("Transition", typeof(Storyboard), typeof(Grid), null);
private static void storyboard_Completed(object sender, EventArgs e)
{
Storyboard s = sender as Storyboard;
s.Completed -= storyboard_Completed;
FrameworkElement f = s.GetValue(GridExtension.TweenedObjectProperty) as FrameworkElement;
Grid parentGrid = f.Parent as Grid;
parentGrid.Background = GridExtension.GetSavedGridBackground(parentGrid);
parentGrid.IsHitTestVisible = true;
foreach (UIElement u in parentGrid.Children)
{
u.Opacity = 1;
if (!Object.ReferenceEquals(u, f))
{
u.IsHitTestVisible = true;
}
else
{
//we save current object coordinates
GridCoordinates oldCoordinates = (GridCoordinates)f.GetValue(GridExtension.ObjectCoordinatesProperty);
//we set new row and column coordinates
Grid.SetRow(f, oldCoordinates.RowIndex);
Grid.SetColumn(f, oldCoordinates.ColumnIndex);
Grid.SetColumnSpan(f, oldCoordinates.ColumnSpan);
Grid.SetRowSpan(f, oldCoordinates.RowSpan);
}
}
}
///
/// Defines duration for current transition
///
///
///
public static double GetTransitionDuration(DependencyObject obj)
{
return (double)obj.GetValue(TransitionDurationProperty);
}
public static void SetTransitionDuration(DependencyObject obj, double value)
{
obj.SetValue(TransitionDurationProperty, value);
}
// Using a DependencyProperty as the backing store for TransitionDuration. This enables animation, styling, binding, etc...
public static readonly DependencyProperty TransitionDurationProperty =
DependencyProperty.RegisterAttached("TransitionDuration", typeof(double), typeof(Grid), new PropertyMetadata(200d));
///
/// Save current tweened object
///
///
///
internal static FrameworkElement GetTweenedObject(DependencyObject obj)
{
return (FrameworkElement)obj.GetValue(TweenedObjectProperty);
}
internal static void SetTweenedObject(DependencyObject obj, FrameworkElement value)
{
obj.SetValue(TweenedObjectProperty, value);
}
// Using a DependencyProperty as the backing store for TweenedObject. This enables animation, styling, binding, etc...
internal static readonly DependencyProperty TweenedObjectProperty =
DependencyProperty.RegisterAttached("TweenedObject", typeof(FrameworkElement), typeof(Storyboard), null);
#endregion
#region object attach properties
///
/// Contains Object Row et Column index
///
///
///
public static GridCoordinates GetObjectCoordinates(DependencyObject obj)
{
return (GridCoordinates)obj.GetValue(ObjectCoordinatesProperty);
}
public static void SetObjectCoordinates(DependencyObject obj, GridCoordinates value)
{
obj.SetValue(ObjectCoordinatesProperty, value);
}
// Using a DependencyProperty as the backing store for ObjectCoordinates. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ObjectCoordinatesProperty =
DependencyProperty.RegisterAttached("ObjectCoordinates", typeof(GridCoordinates), typeof(FrameworkElement), new PropertyMetadata(new GridCoordinates() { ColumnIndex = 0, RowIndex = 0 }, null));
///
/// Defines if current object isMaximized
///
///
///
public static bool GetIsMaximized(DependencyObject obj)
{
return (bool)obj.GetValue(IsMaximizedProperty);
}
public static void SetIsMaximized(DependencyObject obj, bool value)
{
obj.SetValue(IsMaximizedProperty, value);
}
// Using a DependencyProperty as the backing store for IsMaximized. This enables animation, styling, binding, etc...
public static readonly DependencyProperty IsMaximizedProperty =
DependencyProperty.RegisterAttached("IsMaximized", typeof(bool), typeof(FrameworkElement), new PropertyMetadata(false, new PropertyChangedCallback(OnMaximizedChanged)));
private static void OnMaximizedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
//1 - On récupère la grille parente
FrameworkElement f = d as FrameworkElement;
if (f == null) return;
Grid parentGrid = f.Parent as Grid;
if (parentGrid == null) return;
//on vérifie qu'elle autorise le maximize de ses enfants
if (!Convert.ToBoolean(GetIsMaximizable(parentGrid))) return;
//2 - On cache tous les enfants mis à part celui qui voit sa propriété passée à true;
bool isMaximized = Convert.ToBoolean(e.NewValue);
if (isMaximized)
{
Maximize(parentGrid, f);
}
else
{
Minimize(parentGrid, f);
}
}
///
/// Minimize object
///
/// parent grid of the object
/// object to minimize
private static void Minimize(Grid parentGrid, FrameworkElement f)
{
parentGrid.IsHitTestVisible = false;
Storyboard s = parentGrid.GetValue(GridExtension.TransitionProperty) as Storyboard;
DoubleAnimation daObj = s.Children[0] as DoubleAnimation;
DoubleAnimation daBrush = s.Children[1] as DoubleAnimation;
daBrush.To = 1;
daObj.To = 0;
daObj.BeginTime = TimeSpan.FromMilliseconds(0);
s.Begin();
s.Completed += storyboard_Completed;
}
///
/// maximize Object
///
/// parent grid of the object
/// object to maximize
private static void Maximize(Grid parentGrid, FrameworkElement f)
{
parentGrid.IsHitTestVisible = false;
//3 - we save current screenshot
WriteableBitmap wb = new WriteableBitmap(parentGrid, null);
parentGrid.SetValue(GridExtension.CurrentScreenShotProperty, new ImageBrush() { ImageSource = wb, Stretch = Stretch.None });
GridExtension.SetSavedGridBackground(parentGrid, parentGrid.Background);
parentGrid.Background = parentGrid.GetValue(GridExtension.CurrentScreenShotProperty) as ImageBrush;
Brush b = parentGrid.Background;
foreach (UIElement u in parentGrid.Children)
{
u.Opacity = 0;
if (!Object.ReferenceEquals(u, f))
{
u.IsHitTestVisible = false;
}
else
{
//we save current object coordinates
f.SetValue(GridExtension.ObjectCoordinatesProperty, new GridCoordinates()
{
RowIndex = (int)Grid.GetRow(f),
ColumnIndex = (int)Grid.GetColumn(f),
RowSpan = (int)Grid.GetRowSpan(f),
ColumnSpan = (int)Grid.GetColumnSpan(f)
});
//we set new row and column coordinates
Grid.SetRow(f, 0);
Grid.SetColumn(f, 0);
Grid.SetColumnSpan(f, parentGrid.ColumnDefinitions.Count);
Grid.SetRowSpan(f, parentGrid.RowDefinitions.Count);
}
}
double duration = (double)parentGrid.GetValue(GridExtension.TransitionDurationProperty);
Storyboard sb = new Storyboard();
DoubleAnimation daObj = new DoubleAnimation();
daObj.Duration = TimeSpan.FromMilliseconds(duration);
daObj.BeginTime = TimeSpan.FromMilliseconds(duration / 2);
daObj.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
daObj.To = 1;
Storyboard.SetTarget(daObj, f);
Storyboard.SetTargetProperty(daObj, new PropertyPath(FrameworkElement.OpacityProperty));
DoubleAnimation daBrush = new DoubleAnimation();
daBrush.Duration = TimeSpan.FromMilliseconds(duration);
daBrush.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
daBrush.To = .3;
Storyboard.SetTarget(daBrush, b);
Storyboard.SetTargetProperty(daBrush, new PropertyPath(Brush.OpacityProperty));
sb.Children.Add(daObj);
sb.Children.Add(daBrush);
parentGrid.SetValue(GridExtension.TransitionProperty, sb);
sb.SetValue(GridExtension.TweenedObjectProperty, f);
sb.Begin();
sb.Completed += (s, e) =>
{
parentGrid.IsHitTestVisible = true;
};
}
#endregion
#region Child object properties
///
/// Allow to define the object to maximize
///
///
///
public static FrameworkElement GetObjectToMaximize(DependencyObject obj)
{
return (FrameworkElement)obj.GetValue(ObjectToMaximizeProperty);
}
public static void SetObjectToMaximize(DependencyObject obj, FrameworkElement value)
{
obj.SetValue(ObjectToMaximizeProperty, value);
}
// Using a DependencyProperty as the backing store for IsMaximizedSource. This enables animation, styling, binding, etc...
public static readonly DependencyProperty ObjectToMaximizeProperty =
DependencyProperty.RegisterAttached("ObjectToMaximize", typeof(FrameworkElement), typeof(FrameworkElement), new PropertyMetadata(null, IsMaximizedSource_DependencyPropertyChangedCallback));
static void IsMaximizedSource_DependencyPropertyChangedCallback(DependencyObject dobj, DependencyPropertyChangedEventArgs ea)
{
var fe = dobj as FrameworkElement;
if (fe == null) return;
if (dobj is ButtonBase)
{
var btn = fe as ButtonBase;
btn.Click += btn_Click;
}
else
{
fe.MouseLeftButtonDown += fe_MouseLeftButtonDown;
}
fe.Unloaded += fe_Unloaded;
}
static void btn_Click(object sender, RoutedEventArgs e)
{
var dobj = sender as DependencyObject;
var objToMaximize = dobj.GetValue(GridExtension.ObjectToMaximizeProperty) as DependencyObject;
ToggleIsMaximized(objToMaximize);
}
static void fe_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var dobj = sender as DependencyObject;
var objToMaximize = dobj.GetValue(GridExtension.ObjectToMaximizeProperty) as DependencyObject;
ToggleIsMaximized(objToMaximize);
}
private static void ToggleIsMaximized(DependencyObject dobj)
{
var newIsMaxValue = (bool)dobj.GetValue(GridExtension.IsMaximizedProperty);
dobj.SetValue(GridExtension.IsMaximizedProperty, !newIsMaxValue);
}
static void fe_Unloaded(object sender, RoutedEventArgs e)
{
var fe = sender as FrameworkElement;
if (sender is ButtonBase)
{
var btn = fe as ButtonBase;
btn.Click -= btn_Click;
}
else
{
fe.MouseLeftButtonDown -= fe_MouseLeftButtonDown;
}
fe.Unloaded -= fe_Unloaded;
}
#endregion
}
public struct GridCoordinates
{
internal int RowIndex;
internal int ColumnIndex;
internal int RowSpan;
internal int ColumnSpan;
}
}