AtmRobotMultiLP.xaml.cs 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308
  1. using Aitex.Core.Common;
  2. using Aitex.Core.UI.MVVM;
  3. using Aitex.Sorter.UI.Controls.Common;
  4. using MECF.Framework.Common.Equipment;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.ComponentModel;
  8. using System.Linq;
  9. using System.Threading;
  10. using System.Windows;
  11. using System.Windows.Controls;
  12. using System.Windows.Input;
  13. using System.Windows.Media;
  14. using System.Windows.Media.Animation;
  15. namespace Aitex.Sorter.UI.Controls
  16. {
  17. /// <summary>
  18. /// AtmRobotMultiLP.xaml 的交互逻辑
  19. /// </summary>
  20. public partial class AtmRobotMultiLP : UserControl, INotifyPropertyChanged
  21. {
  22. protected readonly int MoveTime = 300;
  23. private const int AnimationTimeout = 3000; // seconds
  24. public int RotateAngle
  25. {
  26. get { return (int)GetValue(RotateAngleProperty); }
  27. set { SetValue(RotateAngleProperty, value); }
  28. }
  29. // Using a DependencyProperty as the backing store for RotateAngel. This enables animation, styling, binding, etc...
  30. public static readonly DependencyProperty RotateAngleProperty =
  31. DependencyProperty.Register("RotateAngel", typeof(int), typeof(AtmRobotMultiLP), new PropertyMetadata(0));
  32. public ModuleName Station
  33. {
  34. get { return (ModuleName)GetValue(StationProperty); }
  35. set { SetValue(StationProperty, value); }
  36. }
  37. // Using a DependencyProperty as the backing store for Station. This enables animation, styling, binding, etc...
  38. public static readonly DependencyProperty StationProperty =
  39. DependencyProperty.Register("Station", typeof(ModuleName), typeof(AtmRobotMultiLP), new PropertyMetadata(ModuleName.Robot));
  40. public ICommand Command
  41. {
  42. get { return (ICommand)GetValue(CommandProperty); }
  43. set { SetValue(CommandProperty, value); }
  44. }
  45. // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
  46. public static readonly DependencyProperty CommandProperty =
  47. DependencyProperty.Register("Command", typeof(ICommand), typeof(AtmRobotMultiLP), new PropertyMetadata(null));
  48. public string RobotBladeTarget
  49. {
  50. get { return (string)GetValue(RobotBladeTargetProperty); }
  51. set { SetValue(RobotBladeTargetProperty, value); }
  52. }
  53. public static readonly DependencyProperty RobotBladeTargetProperty =
  54. DependencyProperty.Register("RobotBladeTarget", typeof(string), typeof(AtmRobotMultiLP), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
  55. public Dictionary<string, StationPosition> StationPosition
  56. {
  57. get { return (Dictionary<string, StationPosition>)GetValue(StationPositionProperty); }
  58. set { SetValue(StationPositionProperty, value); }
  59. }
  60. // Using a DependencyProperty as the backing store for StationPosition. This enables animation, styling, binding, etc...
  61. public static readonly DependencyProperty StationPositionProperty =
  62. DependencyProperty.Register("StationPosition", typeof(Dictionary<string, StationPosition>), typeof(AtmRobotMultiLP), new PropertyMetadata(null, StationPositionChangedCallback));
  63. public bool ShowDock
  64. {
  65. get { return (bool)GetValue(ShowDockProperty); }
  66. set { SetValue(ShowDockProperty, value); }
  67. }
  68. // Using a DependencyProperty as the backing store for ShowDock. This enables animation, styling, binding, etc...
  69. public static readonly DependencyProperty ShowDockProperty =
  70. DependencyProperty.Register("ShowDock", typeof(bool), typeof(AtmRobotMultiLP), new PropertyMetadata(false));
  71. public WaferInfo[] RobotWafers
  72. {
  73. get { return (WaferInfo[])GetValue(RobotWafersProperty); }
  74. set { SetValue(RobotWafersProperty, value); }
  75. }
  76. // Using a DependencyProperty as the backing store for RobotWafers. This enables animation, styling, binding, etc...
  77. public static readonly DependencyProperty RobotWafersProperty =
  78. DependencyProperty.Register("RobotWafers", typeof(WaferInfo[]), typeof(AtmRobotMultiLP), new PropertyMetadata(null));
  79. private string CurrentPosition
  80. {
  81. get; set;
  82. }
  83. private List<MenuItem> menu;
  84. public List<MenuItem> Menu
  85. {
  86. get
  87. {
  88. return menu;
  89. }
  90. set
  91. {
  92. menu = value;
  93. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Menu"));
  94. }
  95. }
  96. public ICommand MoveCommand
  97. {
  98. get
  99. {
  100. return new DelegateCommand<string>(MoveTo);
  101. }
  102. }
  103. private AnimationQueue queue;
  104. public event PropertyChangedEventHandler PropertyChanged;
  105. static void StationPositionChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  106. {
  107. var self = (AtmRobotMultiLP)d;
  108. var positions = (Dictionary<string, StationPosition>)e.NewValue;
  109. self.Menu = positions.Select(x => new MenuItem() { Header = x.Key, Command = self.MoveCommand, CommandParameter = x.Key }).ToList();
  110. }
  111. public AtmRobotMultiLP()
  112. {
  113. #if DEBUG
  114. System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Critical;
  115. #endif
  116. InitializeComponent();
  117. root.DataContext = this;
  118. queue = new AnimationQueue("Robot Animation");
  119. queue.StatusUpdated += Queue_StatusUpdated;
  120. canvas1.Rotate(90);
  121. canvas2.Rotate(180);
  122. canvas3.Rotate(180);
  123. CurrentPosition = ModuleName.System.ToString();
  124. }
  125. protected override void OnRender(DrawingContext drawingContext)
  126. {
  127. base.OnRender(drawingContext);
  128. if (DesignerProperties.GetIsInDesignMode(this))
  129. {
  130. return;
  131. }
  132. if (RobotBladeTarget != null)
  133. {
  134. queue.EnqueueStatus(new AnimationParameter() { Target = RobotBladeTarget });
  135. }
  136. }
  137. private void Queue_StatusUpdated(object sender, StatusUpdateArgs e)
  138. {
  139. LogMsg(string.Format("Target: {0} - {1}", CurrentPosition, e.Parameter.Target));
  140. var nextEvent = new AutoResetEvent(false);
  141. var next = new Action(() =>
  142. {
  143. nextEvent.Set();
  144. });
  145. var wait = new Action(() =>
  146. {
  147. if (!nextEvent.WaitOne(AnimationTimeout))
  148. {
  149. LogMsg("Aniamtion time out!");
  150. }
  151. });
  152. var done = new Action(() =>
  153. {
  154. CurrentPosition = e.Parameter.Target;
  155. e.Event.Set();
  156. });
  157. var needMove = CurrentPosition != e.Parameter.Target;
  158. if (needMove)
  159. {
  160. Invoke(() => MoveRobot(e.Parameter.Target, next));
  161. wait();
  162. }
  163. done();
  164. }
  165. private void MoveRobot(string target, Action onComplete = null)
  166. {
  167. MoveToStart(CurrentPosition, () => TranslateTo(target, () => RetractArm(() => MoveToStart(target, () => MoveToEnd(target, onComplete)))));
  168. }
  169. private void RetractArm(Action onComplete = null)
  170. {
  171. canvas2.Rotate(180, true, 50, 0, 0, onComplete);
  172. canvas3.Rotate(180, true);
  173. }
  174. private void MoveToStart(string station, Action onComplete = null)
  175. {
  176. var position = StationPosition[station];
  177. canvas1.Rotate(position.StartPosition.Root, true, MoveTime, 0, 0, onComplete);
  178. canvas2.Rotate(position.StartPosition.Arm, true, MoveTime);
  179. canvas3.Rotate(position.StartPosition.Hand, true, MoveTime);
  180. CurrentPosition = station;
  181. }
  182. private void MoveToEnd(string station, Action onComplete = null)
  183. {
  184. var position = StationPosition[station];
  185. canvas1.Rotate(position.EndPosition.Root, true, MoveTime, 0, 0, onComplete);
  186. canvas2.Rotate(position.EndPosition.Arm, true, MoveTime);
  187. canvas3.Rotate(position.EndPosition.Hand, true, MoveTime);
  188. CurrentPosition = station;
  189. }
  190. private void TranslateTo(string station, Action onComplete = null)
  191. {
  192. var position = StationPosition[station];
  193. if (position.StartPosition.X.HasValue)
  194. {
  195. Translate(position.StartPosition.X.Value, onComplete);
  196. }
  197. else
  198. {
  199. onComplete?.Invoke();
  200. }
  201. }
  202. private void Translate(int x, Action onComplete = null)
  203. {
  204. var storyBoard = new Storyboard();
  205. var oldX = translate.X;
  206. var animation = new DoubleAnimation(oldX, x, TimeSpan.FromMilliseconds(MoveTime));
  207. storyBoard.Children.Add(animation);
  208. Storyboard.SetTarget(animation, root);
  209. var propertyChain = new DependencyProperty[]
  210. {
  211. Canvas.RenderTransformProperty,
  212. TransformGroup.ChildrenProperty,
  213. TranslateTransform.XProperty
  214. };
  215. string thePath = "(0).(1)[1].(2)";
  216. PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
  217. Storyboard.SetTargetProperty(animation, myPropertyPath);
  218. storyBoard.Completed += (s, e) =>
  219. {
  220. //InvalidateVisual();
  221. if (onComplete != null)
  222. {
  223. onComplete();
  224. }
  225. };
  226. storyBoard.Begin();
  227. }
  228. private void MoveTo(string target)
  229. {
  230. MoveRobot(target);
  231. }
  232. private void Invoke(Action action)
  233. {
  234. Dispatcher.Invoke(action);
  235. }
  236. private void LogMsg(string msg)
  237. {
  238. var source = "Robot";
  239. Console.WriteLine("{0} {1}", source, msg);
  240. }
  241. }
  242. public enum BladeStatusMultiLP
  243. {
  244. Extend,
  245. Retract
  246. }
  247. public class RobotPosition
  248. {
  249. public int? X;
  250. public int Root;
  251. public int Arm;
  252. public int Hand;
  253. }
  254. public class StationPosition
  255. {
  256. public RobotPosition StartPosition;
  257. public RobotPosition EndPosition;
  258. }
  259. }