using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace HistoryDLL { public partial class CyclicScroller : UserControl { private List ExtraUnitGridList = new List(); } public class ExtraUnitGrid : Grid { //外掛 Delegate event for communicate with CyclicScroller (通知用) public delegate void ExtraUnitGridBubbleToCyclicScroller(string ProcessCode, int index); public event ExtraUnitGridBubbleToCyclicScroller ExtraUnitGridBubbleToCyclicScrollerEvent; //原始物件寬度 private int OriginalObjectWidth = 0; //放大後原始寬度必須增加的值 private int ExtendValue = 400; //縮小一次的值 public int ShrinkValueOne = 200; //展開縮小棟話時間 private int MyStoryBoardTimeL = 200; private int MyStoryBoardTimeS = 100; //Storyboard delay time private int delayTime = 100; //紀錄方向 private string Direction = ""; private double detailviewerPos = -36; private double thumbnailPos = -7; //當前物件可被控制的狀態 public enum ControlMode { //可展開 (正常狀態) CanExtend = 0x00001, //已經展開 Extend = 0x00010, //不可展開 (處在最兩邊的無用地帶) UnUse = 0x00100, //縮小一次 Clip = 0x01000, //縮小第二次 (最小寬度) MinStatus = 0x00000 }; public enum ObjectSize { OriginalSize = 0x0001, ShrinkNoneMarginSize = 0x0010, ShrinkMarginSize = 0x0100, ShrinkWholeSize = 0x1000 } private int MonitorIndex; private ControlMode BlockControlMode; private ControlMode RecodeOriMode; public Border BorderUp = new Border(); public Border BorderDown = new Border(); //是否已經被加到畫面中 public int IsUsing = 0; public TextBlock textblock = new TextBlock(); public int curDataIndex = -1; //紀錄回到原位置的Margin值 ~以確保可以正確回到該位置 public double RecodeMarginLeft = 0; private double borderupheight = 0; private double borderdownheight = 0; private double NonoUseSize = 0; private ObjectSize objSize = ObjectSize.OriginalSize; private double ThisMarginLeft = 0.0; public bool ExtendStoryboardRun = false; public bool ShrinkStoryboardRun = false; //下方方塊顏色 private SolidColorBrush borderDownColor = new SolidColorBrush(ConfigSettingClass.TimelineExtentCollect.BackgroundColor); private SolidColorBrush TextBlockExtendColor = new SolidColorBrush(ConfigSettingClass.TimelineExtentCollect.TextColor); private SolidColorBrush TextBlockShrinkColor = new SolidColorBrush(ConfigSettingClass.TimelineCollect.TextColor); public int Get_Set_MonitorIndex { get { return MonitorIndex; } set { MonitorIndex = value; if (MonitorIndex >= 2) { ThisMarginLeft = (MonitorIndex - 2) * OriginalObjectWidth + (OriginalObjectWidth - NonoUseSize); } else { ThisMarginLeft = -NonoUseSize; } } } public ControlMode Get_Set_BlockControlMode { get { return BlockControlMode; } set { BlockControlMode = value; } } public ExtraUnitGrid(int Width, int Height, int DownHeight, int NoneUse) { int borderMargin = 5; if (GlobalFunction.isSolutionUsing4K) { ExtendValue *= 2; ShrinkValueOne *= 2; borderMargin *= 2; } this.Width = this.OriginalObjectWidth = Width; this.Height = Height + DownHeight; this.NonoUseSize = NoneUse; CutTheGrid(); borderupheight = Height; borderdownheight = DownHeight; this.BorderUp.Height = Height; this.BorderUp.Height = 0; //this.BorderUp.Background = Brushes.Red; this.BorderUp.BorderBrush = Brushes.Transparent; this.BorderUp.BorderThickness = new Thickness(borderMargin); this.BorderDown.Height = DownHeight; this.BorderDown.Background = borderDownColor; //this.BorderDown.Background = Brushes.Green; this.BorderDown.BorderBrush = Brushes.Transparent; this.BorderDown.BorderThickness = new Thickness(borderMargin, borderMargin, borderMargin, GlobalFunction.isSolutionUsing4K ? 0 : borderMargin); //字體設定 textblock.FontSize = GlobalFunction.isSolutionUsing4K ? 40 * 1.5 : 40; textblock.TextTrimming = TextTrimming.CharacterEllipsis; textblock.VerticalAlignment = System.Windows.VerticalAlignment.Center; textblock.HorizontalAlignment = System.Windows.HorizontalAlignment.Center; BorderDown.Child = textblock; this.Children.Add(BorderUp); this.Children.Add(BorderDown); Grid.SetRow(BorderUp, 0); Grid.SetRow(BorderDown, 1); this.HorizontalAlignment = System.Windows.HorizontalAlignment.Left; this.VerticalAlignment = System.Windows.VerticalAlignment.Bottom; Get_Set_MonitorIndex = 0; IsUsing = 0; this.BorderDown.TouchUp += new EventHandler(BorderDown_TouchUp); } public void SetOriControlMode(ControlMode Set) { RecodeOriMode = Set; } public void BorderDown_TouchUp(object sender, System.Windows.Input.TouchEventArgs e) { if (ExtendStoryboardRun) return; if (this.BlockControlMode == ControlMode.Extend) { this.Dispatcher.BeginInvoke(ExtraUnitGridBubbleToCyclicScrollerEvent, "Change", Get_Set_MonitorIndex); } } //回復原始大小動畫完成 void Mystoryboard_Completed(object sender, EventArgs e) { this.Dispatcher.BeginInvoke(ExtraUnitGridBubbleToCyclicScrollerEvent, "Remove", Get_Set_MonitorIndex - 1); } private void CutTheGrid() { //切成上下兩塊 RowDefinition rowDefinitionUp = new RowDefinition(); RowDefinition rowDefinitionDown = new RowDefinition(); rowDefinitionUp.Height = new GridLength(6, GridUnitType.Star); rowDefinitionDown.Height = new GridLength(1, GridUnitType.Star); //rowDefinitionDown.Height = new GridLength(GlobalFunction.isSolutionUsing4K ? 184 : 92, GridUnitType.Pixel); this.RowDefinitions.Add(rowDefinitionUp); this.RowDefinitions.Add(rowDefinitionDown); } #region 展開動畫 : /// /// 1.下方區塊先展開(0.2) /// 2.上方區塊由下往上升起(0.2) /// 3.call Detailviewer opacity changed(0.1) /// public void ExtendFunction() { this.BlockControlMode = ControlMode.Extend; this.textblock.Foreground = TextBlockExtendColor; //下方區塊的變化 Storyboard Mystoryboard = new Storyboard(); this.textblock.Opacity = 1; this.BorderUp.Opacity = 1; ExtendStoryboardRun = true; Mystoryboard = SetExtendChangeAnimation(MyStoryBoardTimeL, OriginalObjectWidth + ExtendValue); Mystoryboard.Completed += new EventHandler(EventContainerExtend_Complete); Mystoryboard.Begin(); } //中間放大 private Storyboard SetExtendChangeAnimation(int time, int ToValue) { Storyboard ResultStoryboard = new Storyboard(); DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseOut, }, From = this.Width, To = ToValue }; ThicknessAnimation dbMargin = new ThicknessAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseOut, }, From = this.Margin, To = new Thickness(this.Margin.Left - Math.Abs(this.Width - ToValue) / 2, 0, 0, this.Margin.Bottom) }; this.RenderTransformOrigin = new Point(0.5, 0.5); Storyboard.SetTarget(dbOffset, (DependencyObject)this); Storyboard.SetTarget(dbMargin, (DependencyObject)this); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.WidthProperty)); Storyboard.SetTargetProperty(dbMargin, new PropertyPath(Grid.MarginProperty)); ResultStoryboard.Children.Add(dbOffset); ResultStoryboard.Children.Add(dbMargin); ResultStoryboard.FillBehavior = FillBehavior.HoldEnd; return ResultStoryboard; } private void EventContainerExtend_Complete(object sender, EventArgs e) { //上方區塊的變化 Storyboard MystoryboardUp = new Storyboard(); MystoryboardUp = ObjectAnimationToShow(MyStoryBoardTimeL, this.BorderUp.Height, borderupheight, detailviewerPos); MystoryboardUp.Completed += new EventHandler(DetailViewerControlShow); MystoryboardUp.Begin(); } //Object is fade in internal void DetailViewerControlShow(object sender, EventArgs e) { //call detailviewer to show Grid gd = new Grid(); gd = this.BorderUp.Child as Grid; if (gd != null && gd.Children.Count > 0) { if (gd.Children[0].ToString() == GlobalFunction.projectname + ".DetailViewer") { //sdlu //((DetailViewer)gd.Children[0]).StartOpacityAnimation(); } } else if (this.BorderUp.Child.ToString() == GlobalFunction.projectname + ".ThumbnailContainer") { ((ThumbnailContainer)this.BorderUp.Child).StartOpacityAnimation(); } ExtendStoryboardRun = false; } //Object is fade out internal void DetailViewerControlHide() { //call detailviewer to show Grid gd = new Grid(); gd = this.BorderUp.Child as Grid; if (gd != null) { if (gd.Children[0].ToString() == "nLightenHistoryWall.DetailViewer") { //sdlu //((DetailViewer)gd.Children[0]).StopOpacityAnimation(); } } else if (this.BorderUp.Child.ToString() == "nLightenHistoryWall.ThumbnailContainer") { ((ThumbnailContainer)this.BorderUp.Child).StopOpacityAnimation(); } } //上方物件由下往上飛入 private Storyboard ObjectAnimationToShow(int time, double fromValue, double toValue, double marginvalue) { Storyboard ResultStoryboard = new Storyboard(); DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseOut, }, From = fromValue, To = toValue }; ThicknessAnimation dbMargin = new ThicknessAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseOut, }, From = new Thickness(this.BorderDown.Margin.Left, 0, 0, -borderdownheight), To = new Thickness(this.BorderDown.Margin.Left, 0, 0, marginvalue) }; Storyboard.SetTarget(dbOffset, this.BorderUp); Storyboard.SetTarget(dbMargin, this.BorderUp); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.HeightProperty)); Storyboard.SetTargetProperty(dbMargin, new PropertyPath(Grid.MarginProperty)); ResultStoryboard.Children.Add(dbOffset); ResultStoryboard.Children.Add(dbMargin); ResultStoryboard.FillBehavior = FillBehavior.HoldEnd; return ResultStoryboard; } #endregion private void SetCurrentObjSizeShrink(string Direction) { if (objSize == ObjectSize.OriginalSize) { if (Direction == "Left") { objSize = ObjectSize.ShrinkNoneMarginSize; } else if (Direction == "Right") { objSize = ObjectSize.ShrinkMarginSize; } } else if (objSize == ObjectSize.ShrinkNoneMarginSize) { if (Direction == "Right") { objSize = ObjectSize.ShrinkWholeSize; } } else if (objSize == ObjectSize.ShrinkMarginSize) { if (Direction == "Left") { objSize = ObjectSize.ShrinkWholeSize; } } else { objSize = ObjectSize.OriginalSize; } } private void SetCurrentObjSizeExtend(string Driection) { if (objSize == ObjectSize.ShrinkWholeSize) { if (Direction == "Left") { objSize = ObjectSize.ShrinkMarginSize; } else if (Direction == "Right") { objSize = ObjectSize.ShrinkNoneMarginSize; } } else if (objSize == ObjectSize.ShrinkNoneMarginSize || objSize == ObjectSize.ShrinkMarginSize) { objSize = ObjectSize.OriginalSize; } } private void GetTargetSizeAndPos(ObjectSize objectsize, ref double size, ref double pos) { int oriSize = 460; int shrSize = 260; int shrWholeSize = 60; int marginValue = 200; if (GlobalFunction.isSolutionUsing4K) { oriSize *= 2; shrSize *= 2; shrWholeSize *= 2; marginValue *= 2; } if (objectsize == ObjectSize.OriginalSize) { size = oriSize; pos = ThisMarginLeft; } else if (objectsize == ObjectSize.ShrinkNoneMarginSize) { size = shrSize; pos = ThisMarginLeft; } else if (objectsize == ObjectSize.ShrinkMarginSize) { size = shrSize; pos = ThisMarginLeft + marginValue; } else if (objectsize == ObjectSize.ShrinkWholeSize) { size = shrWholeSize; pos = ThisMarginLeft + marginValue; } } #region 兩旁縮小動畫 /// /// 1.下方區塊先縮小(0.2) /// 2.上方區塊由下往上升起(0.1) /// 3.如果今天是縮小一次的狀態則call Detailviewer to changed opacity(0.1) /// /// 相對於被點擊物件的位置方向 public void ShrinkFunction(string Direction) { Storyboard Mystoryboard = new Storyboard(); this.textblock.Foreground = TextBlockShrinkColor; SetCurrentObjSizeShrink(Direction); if (this.BlockControlMode != ControlMode.Clip) { this.BlockControlMode = ControlMode.Clip; //縮第一次 Mystoryboard = SetShrinkChangeAnimation(MyStoryBoardTimeL, objSize, Direction); Mystoryboard.Completed += new EventHandler(EventContainerShrink_Complete); this.textblock.Opacity = 1; this.BorderUp.Opacity = 1; Mystoryboard.Begin(); } else if (this.BlockControlMode == ControlMode.Clip) { //縮第二次 this.BlockControlMode = ControlMode.MinStatus; Mystoryboard = SetShrinkChangeAnimation(MyStoryBoardTimeS, objSize, Direction); this.textblock.Opacity = 0; this.BorderUp.Opacity = 0; Mystoryboard.Begin(); } } private void EventContainerShrink_Complete(object sender, EventArgs e) { Storyboard MystoryboardUp = new Storyboard(); MystoryboardUp = ObjectAnimationToShow(MyStoryBoardTimeL, this.BorderUp.Height, borderupheight, thumbnailPos); MystoryboardUp.Completed += new EventHandler(DetailViewerControlShow); MystoryboardUp.Begin(); } private Storyboard SetShrinkChangeAnimation(int time, ObjectSize objectsize, string Direction) { Storyboard ResultStoryboard = new Storyboard(); double size = 0; double pos = 0; GetTargetSizeAndPos(objectsize, ref size, ref pos); DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseIn, Exponent = 0.3 }, From = this.Width, To = size }; ThicknessAnimation dbMargin = new ThicknessAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseIn, Exponent = 0.3 }, From = this.Margin, To = new Thickness(pos, 0, 0, this.Margin.Bottom) }; this.RenderTransformOrigin = new Point(0.5, 0.5); Storyboard.SetTarget(dbOffset, (DependencyObject)this); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.WidthProperty)); ResultStoryboard.Children.Add(dbOffset); Storyboard.SetTarget(dbMargin, (DependencyObject)this); Storyboard.SetTargetProperty(dbMargin, new PropertyPath(Grid.MarginProperty)); ResultStoryboard.Children.Add(dbMargin); ResultStoryboard.FillBehavior = FillBehavior.HoldEnd; return ResultStoryboard; } #endregion private void EventContainerShrinkOneTime_Complete(object sender, EventArgs e) { this.textblock.Opacity = 1; this.BorderUp.Opacity = 1; DetailViewerControlShow(sender, e); } #region 回原始大小動畫 public void ReturnToOriginalSize() { this.BlockControlMode = this.RecodeOriMode; //上方區塊變化 Storyboard Mystoryboard = new Storyboard(); this.IsUsing--; SetCurrentObjSizeShrink(""); Mystoryboard = ObjectAnimationToHide(MyStoryBoardTimeL, this.BorderUp.Height, 0); Mystoryboard.Completed += new EventHandler(ReturnToOriginal_Complete); Mystoryboard.Begin(); } private void ClearBorderUpChild() { Grid gd = BorderUp.Child as Grid; if (gd != null) { gd.Children.Clear(); } } private void ReturnToOriginal_Complete(object sender, EventArgs e) { Storyboard Mystoryboard = new Storyboard(); ClearBorderUpChild(); Mystoryboard = SetOriginalChangeAnimation(MyStoryBoardTimeL, OriginalObjectWidth); Mystoryboard.Completed += new EventHandler(Mystoryboard_Completed); Mystoryboard.Begin(); } #endregion #region 返回上一級大小 /// /// 1.call Detailviewer to change opacity (0.1) /// 2.上方區塊由上往下縮到消失~ /// 3.時間軸縮回(0.1) /// /// public void BackSize(string Direction) { Storyboard Mystoryboard = new Storyboard(); this.Direction = Direction; SetCurrentObjSizeExtend(Direction); DetailViewerControlHide(); if (this.BlockControlMode == ControlMode.MinStatus) { this.IsUsing--; //縮回第一次 this.BlockControlMode = ControlMode.Clip; Mystoryboard = SetBackSizeChangeAnimation(MyStoryBoardTimeL, objSize, Direction, 420); Mystoryboard.Completed += new EventHandler(EventContainerShrinkOneTime_Complete); Mystoryboard.Begin(); } else if (this.BlockControlMode == ControlMode.Clip) { this.IsUsing--; //縮回原始大小 this.BlockControlMode = this.RecodeOriMode; ClearBorderUpChild(); Mystoryboard = ObjectAnimationToHide(MyStoryBoardTimeL, this.BorderUp.Height, 0); Mystoryboard.Completed += new EventHandler(BorderUpHide_Complete); Mystoryboard.Begin(); } } private void BorderUpHide_Complete(object sender, EventArgs e) { Storyboard Mystoryboard = new Storyboard(); Mystoryboard = SetBackSizeChangeAnimation(MyStoryBoardTimeL, objSize, Direction, 100); Mystoryboard.Completed += new EventHandler(Mystoryboard_Completed); Mystoryboard.Begin(); } private Storyboard ObjectAnimationToHide(int time, double from, double to) { Storyboard ResultStoryboard = new Storyboard(); DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new CircleEase() { EasingMode = EasingMode.EaseOut, }, From = this.Width, To = to }; ThicknessAnimation dbMargin = new ThicknessAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseOut, }, From = new Thickness(this.BorderDown.Margin.Left, 0, 0, 0), To = new Thickness(this.BorderDown.Margin.Left, 0, 0, -borderdownheight) }; Storyboard.SetTarget(dbOffset, this.BorderUp); Storyboard.SetTarget(dbMargin, this.BorderUp); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.HeightProperty)); Storyboard.SetTargetProperty(dbMargin, new PropertyPath(Grid.MarginProperty)); ResultStoryboard.BeginTime = TimeSpan.FromMilliseconds(delayTime); ResultStoryboard.Children.Add(dbOffset); ResultStoryboard.Children.Add(dbMargin); ResultStoryboard.FillBehavior = FillBehavior.HoldEnd; return ResultStoryboard; } #endregion private Storyboard SetBackSizeChangeAnimation(int time, ObjectSize objectsize, string Direction, int delaytime) { Storyboard ResultStoryboard = new Storyboard(); double size = 0.0; double pos = 0.0; GetTargetSizeAndPos(objectsize, ref size, ref pos); DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseIn, Exponent = 0.3 }, From = this.Width, To = size }; ThicknessAnimation dbMargin = new ThicknessAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseIn, Exponent = 0.3 }, From = this.Margin, To = new Thickness(pos, 0, 0, this.Margin.Bottom) }; Storyboard.SetTarget(dbOffset, (DependencyObject)this); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.WidthProperty)); ResultStoryboard.Children.Add(dbOffset); Storyboard.SetTarget(dbMargin, (DependencyObject)this); Storyboard.SetTargetProperty(dbMargin, new PropertyPath(Grid.MarginProperty)); ResultStoryboard.Children.Add(dbMargin); ResultStoryboard.BeginTime = TimeSpan.FromMilliseconds(delaytime); ResultStoryboard.FillBehavior = FillBehavior.HoldEnd; return ResultStoryboard; } private Storyboard SetOriginalChangeAnimation(int time, int ToValue) { Storyboard ResultStoryboard = new Storyboard(); DoubleAnimation dbOffset = new DoubleAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseIn, Exponent = 0.3 }, From = this.Width, To = ToValue }; ThicknessAnimation dbMargin = new ThicknessAnimation() { Duration = TimeSpan.FromMilliseconds(time), EasingFunction = new ExponentialEase() { EasingMode = EasingMode.EaseIn, Exponent = 0.3 }, From = this.Margin, To = new Thickness(this.Margin.Left + Math.Abs(this.Width - ToValue) / 2, 0, 0, this.Margin.Bottom) }; Storyboard.SetTarget(dbOffset, (DependencyObject)this); Storyboard.SetTarget(dbMargin, (DependencyObject)this); Storyboard.SetTargetProperty(dbOffset, new PropertyPath(Grid.WidthProperty)); Storyboard.SetTargetProperty(dbMargin, new PropertyPath(Grid.MarginProperty)); ResultStoryboard.Children.Add(dbOffset); ResultStoryboard.Children.Add(dbMargin); ResultStoryboard.BeginTime = TimeSpan.FromMilliseconds(delayTime); ResultStoryboard.FillBehavior = FillBehavior.HoldEnd; return ResultStoryboard; } } }