BoatElevatorRobot.xaml.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502
  1. using Aitex.Core.Common;
  2. using Aitex.Core.UI.MVVM;
  3. using FurnaceUI.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.Text;
  10. using System.Threading;
  11. using System.Threading.Tasks;
  12. using System.Windows;
  13. using System.Windows.Controls;
  14. using System.Windows.Data;
  15. using System.Windows.Documents;
  16. using System.Windows.Input;
  17. using System.Windows.Media;
  18. using System.Windows.Media.Animation;
  19. using System.Windows.Media.Imaging;
  20. using System.Windows.Navigation;
  21. using System.Windows.Shapes;
  22. using CB = MECF.Framework.UI.Client.ClientBase;
  23. namespace FurnaceUI.Controls.Parts
  24. {
  25. /// <summary>
  26. /// ATMDualArmRobot.xaml 的交互逻辑
  27. /// </summary>
  28. public partial class BoatElevatorRobot : UserControl, INotifyPropertyChanged
  29. {
  30. protected readonly int MoveTime = 300;
  31. private const int AnimationTimeout = 3000; // seconds
  32. public int MinValue
  33. {
  34. get { return (int)GetValue(MinValueProperty); }
  35. set { SetValue(MinValueProperty, value); }
  36. }
  37. // Using a DependencyProperty as the backing store for MinValue. This enables animation, styling, binding, etc...
  38. public static readonly DependencyProperty MinValueProperty =
  39. DependencyProperty.Register("MinValue", typeof(int), typeof(BoatElevatorRobot), new PropertyMetadata(0));
  40. public int MaxValue
  41. {
  42. get { return (int)GetValue(MaxValueProperty); }
  43. set { SetValue(MaxValueProperty, value); }
  44. }
  45. // Using a DependencyProperty as the backing store for MaxValue. This enables animation, styling, binding, etc...
  46. public static readonly DependencyProperty MaxValueProperty =
  47. DependencyProperty.Register("MaxValue", typeof(int), typeof(BoatElevatorRobot), new PropertyMetadata(1000));
  48. public int CurrentValue
  49. {
  50. get { return (int)GetValue(CurrentValueProperty); }
  51. set { SetValue(CurrentValueProperty, value); }
  52. }
  53. // Using a DependencyProperty as the backing store for CurrentValue. This enables animation, styling, binding, etc...
  54. public static readonly DependencyProperty CurrentValueProperty =
  55. DependencyProperty.Register("CurrentValue", typeof(int), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions.AffectsRender));
  56. public int RotateAngle
  57. {
  58. get { return (int)GetValue(RotateAngleProperty); }
  59. set { SetValue(RotateAngleProperty, value); }
  60. }
  61. // Using a DependencyProperty as the backing store for RotateAngel. This enables animation, styling, binding, etc...
  62. public static readonly DependencyProperty RotateAngleProperty =
  63. DependencyProperty.Register("RotateAngel", typeof(int), typeof(BoatElevatorRobot), new PropertyMetadata(0));
  64. public ModuleName Station
  65. {
  66. get { return (ModuleName)GetValue(StationProperty); }
  67. set { SetValue(StationProperty, value); }
  68. }
  69. // Using a DependencyProperty as the backing store for Station. This enables animation, styling, binding, etc...
  70. public static readonly DependencyProperty StationProperty =
  71. DependencyProperty.Register("Station", typeof(ModuleName), typeof(BoatElevatorRobot), new PropertyMetadata(ModuleName.Robot));
  72. public ICommand Command
  73. {
  74. get { return (ICommand)GetValue(CommandProperty); }
  75. set { SetValue(CommandProperty, value); }
  76. }
  77. // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
  78. public static readonly DependencyProperty CommandProperty =
  79. DependencyProperty.Register("Command", typeof(ICommand), typeof(BoatElevatorRobot), new PropertyMetadata(null));
  80. public string RobotTarget
  81. {
  82. get { return (string)GetValue(RobotTargetProperty); }
  83. set { SetValue(RobotTargetProperty, value); }
  84. }
  85. public static readonly DependencyProperty RobotTargetProperty =
  86. DependencyProperty.Register("RobotTarget", typeof(string), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsRender));
  87. public Dictionary<string, StationPosition> StationPosition
  88. {
  89. get { return (Dictionary<string, StationPosition>)GetValue(StationPositionProperty); }
  90. set { SetValue(StationPositionProperty, value); }
  91. }
  92. // Using a DependencyProperty as the backing store for StationPosition. This enables animation, styling, binding, etc...
  93. public static readonly DependencyProperty StationPositionProperty =
  94. DependencyProperty.Register("StationPosition", typeof(Dictionary<string, StationPosition>), typeof(BoatElevatorRobot), new PropertyMetadata(null, PropertyChangedCallback));
  95. public string ArmAExtended
  96. {
  97. get { return (string)GetValue(ArmAExtendedProperty); }
  98. set { SetValue(ArmAExtendedProperty, value); }
  99. }
  100. // Using a DependencyProperty as the backing store for ArmAExtended. This enables animation, styling, binding, etc...
  101. public static readonly DependencyProperty ArmAExtendedProperty =
  102. DependencyProperty.Register("ArmAExtended", typeof(string), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata(RobotConstant.RobotRetract, FrameworkPropertyMetadataOptions.AffectsRender));
  103. public string ArmBExtended
  104. {
  105. get { return (string)GetValue(ArmBExtendedProperty); }
  106. set { SetValue(ArmBExtendedProperty, value); }
  107. }
  108. // Using a DependencyProperty as the backing store for armBExtended. This enables animation, styling, binding, etc...
  109. public static readonly DependencyProperty ArmBExtendedProperty =
  110. DependencyProperty.Register("ArmBExtended", typeof(string), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata(RobotConstant.RobotRetract, FrameworkPropertyMetadataOptions.AffectsRender));
  111. public WaferInfo[] RobotWafers
  112. {
  113. get { return (WaferInfo[])GetValue(RobotWafersProperty); }
  114. set { SetValue(RobotWafersProperty, value); }
  115. }
  116. // Using a DependencyProperty as the backing store for RobotWafers. This enables animation, styling, binding, etc...
  117. public static readonly DependencyProperty RobotWafersProperty =
  118. DependencyProperty.Register("RobotWafers", typeof(WaferInfo[]), typeof(BoatElevatorRobot), new PropertyMetadata(null, PropertyChangedCallback));
  119. public CB.WaferInfo Wafer1
  120. {
  121. get { return (CB.WaferInfo)GetValue(Wafer1Property); }
  122. set { SetValue(Wafer1Property, value); }
  123. }
  124. // Using a DependencyProperty as the backing store for Wafer1. This enables animation, styling, binding, etc...
  125. public static readonly DependencyProperty Wafer1Property =
  126. DependencyProperty.Register("Wafer1", typeof(CB.WaferInfo), typeof(BoatElevatorRobot), new PropertyMetadata(null));
  127. public CB.WaferInfo Wafer2
  128. {
  129. get { return (CB.WaferInfo)GetValue(Wafer2Property); }
  130. set { SetValue(Wafer2Property, value); }
  131. }
  132. // Using a DependencyProperty as the backing store for Wafer2. This enables animation, styling, binding, etc...
  133. public static readonly DependencyProperty Wafer2Property =
  134. DependencyProperty.Register("Wafer2", typeof(CB.WaferInfo), typeof(BoatElevatorRobot), new PropertyMetadata(null));
  135. private string CurrentPosition;
  136. private string CurrentArmA;
  137. private string CurrentArmB;
  138. public string BoatStatus
  139. {
  140. get
  141. {
  142. return (string)GetValue(BoatStatusProperty);
  143. }
  144. set
  145. {
  146. SetValue(BoatStatusProperty, value);
  147. }
  148. }
  149. // Using a DependencyProperty as the backing store for armBExtended. This enables animation, styling, binding, etc...
  150. public static readonly DependencyProperty BoatStatusProperty =
  151. DependencyProperty.Register("BoatStatus", typeof(string), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata("Init", RobotStatusChangedCallback));
  152. public string RootImagePath
  153. {
  154. get { return (string)GetValue(RootImagePathProperty); }
  155. set { SetValue(RootImagePathProperty, value); }
  156. }
  157. // Using a DependencyProperty as the backing store for RootImagePath. This enables animation, styling, binding, etc...
  158. public static readonly DependencyProperty RootImagePathProperty =
  159. DependencyProperty.Register("RootImagePath", typeof(string), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata("/FurnaceUI;component/Resources/Images/Controls3/02.png", FrameworkPropertyMetadataOptions.AffectsRender));
  160. public string Canvas1ImagePath
  161. {
  162. get { return (string)GetValue(Canvas1ImagePathProperty); }
  163. set { SetValue(Canvas1ImagePathProperty, value); }
  164. }
  165. // Using a DependencyProperty as the backing store for RootImagePath. This enables animation, styling, binding, etc...
  166. public static readonly DependencyProperty Canvas1ImagePathProperty =
  167. DependencyProperty.Register("Canvas1ImagePath", typeof(string), typeof(BoatElevatorRobot), new FrameworkPropertyMetadata("/FurnaceUI;component/Resources/Images/Controls3/lghg.png", FrameworkPropertyMetadataOptions.AffectsRender));
  168. static void RobotStatusChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  169. {
  170. var self = (BoatElevatorRobot)d;
  171. var test = d;
  172. switch ((string)e.NewValue)
  173. {
  174. case "Homing":
  175. self.Canvas1ImagePath = "/FurnaceUI;component/Resources/Images/Controls3/lghg.png";
  176. break;
  177. case "Error":
  178. self.Canvas1ImagePath = "/FurnaceUI;component/Resources/Images/Controls3/lghg.png";
  179. break;
  180. default:
  181. self.Canvas1ImagePath = "/FurnaceUI;component/Resources/Images/Controls3/lghg.png";
  182. break;
  183. }
  184. }
  185. private List<MenuItem> menu;
  186. public List<MenuItem> Menu
  187. {
  188. get
  189. {
  190. return menu;
  191. }
  192. set
  193. {
  194. menu = value;
  195. PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("Menu"));
  196. }
  197. }
  198. public ICommand MoveCommand
  199. {
  200. get
  201. {
  202. return new DelegateCommand<object>(MoveTo);
  203. }
  204. }
  205. private AnimationQueue queue;
  206. protected int homePositionX = 0;
  207. protected int processPositionX = 0;
  208. public event PropertyChangedEventHandler PropertyChanged;
  209. static void PropertyChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
  210. {
  211. //var self = (BoatElevatorRobot)d;
  212. //switch (e.Property.Name)
  213. //{
  214. // case "StationPosition":
  215. // var positions = (Dictionary<string, StationPosition>)e.NewValue;
  216. // //var menu1 = new MenuItem() { Header = "Arm" };
  217. // //var subMenu1 = positions.Select(x => new MenuItem() { Header = x.Key, Command = self.MoveCommand, CommandParameter = new Tuple<string, string, string>(x.Key, RobotConstant.RobotExtend, RobotConstant.RobotRetract) }).ToList();
  218. // //foreach (var menu in subMenu1)
  219. // //{
  220. // // menu1.Items.Add(menu);
  221. // //}
  222. // //self.menu = subMenu1;// new List<MenuItem>().Add(subMenu1);
  223. // break;
  224. // case "RobotWafers":
  225. // //if (e.NewValue == null)
  226. // //{
  227. // // self.Wafer1 = null;
  228. // // self.Wafer2 = null;
  229. // //}
  230. // //else
  231. // //{
  232. // // if (self.RobotWafers.Length > 1)
  233. // // {
  234. // // self.Wafer1 = self.RobotWafers[0];
  235. // // self.Wafer2 = self.RobotWafers[1];
  236. // // }
  237. // //}
  238. // break;
  239. // default:
  240. // break;
  241. //}
  242. var self = (BoatElevatorRobot)d;
  243. switch (e.Property.Name)
  244. {
  245. case "StationPosition":
  246. var positions = (Dictionary<string, StationPosition>)e.NewValue;
  247. //var param = new AnimationParameter() { Target = positions.Keys.ToList()[0], ArmA = RobotConstant.RobotExtend, ArmB = RobotConstant.RobotRetract };
  248. ////if (self.CurrentPosition != param.Target || self.CurrentArmA != param.ArmA || self.CurrentArmB != param.ArmB)
  249. ////{
  250. //// self.MoveRobot((AnimationParameter)param);
  251. ////}
  252. //self.CurrentPosition = param.Target;
  253. //self.CurrentArmA = param.ArmA;
  254. //self.CurrentArmB = param.ArmB;
  255. //var menu1 = new MenuItem() { Header = "Arm" };
  256. //var subMenu1 = positions.Select(x => new MenuItem() { Header = x.Key, Command = self.MoveCommand, CommandParameter = new Tuple<string, string, string>(x.Key, RobotConstant.RobotExtend, RobotConstant.RobotRetract) }).ToList();
  257. //foreach (var menu in subMenu1)
  258. //{
  259. // menu1.Items.Add(menu);
  260. //}
  261. //self.menu = subMenu1;// new List<MenuItem>().Add(subMenu1);
  262. self.homePositionX = (int)positions["HomePosition"]?.StartPosition.X;
  263. self.processPositionX = (int)positions["ProcessPosition"]?.StartPosition.X;
  264. break;
  265. }
  266. }
  267. public BoatElevatorRobot()
  268. {
  269. #if DEBUG
  270. System.Diagnostics.PresentationTraceSources.DataBindingSource.Switch.Level = System.Diagnostics.SourceLevels.Critical;
  271. #endif
  272. InitializeComponent();
  273. root.DataContext = this;
  274. queue = new AnimationQueue("Robot Animation");
  275. //queue.StatusUpdated += Queue_StatusUpdated;
  276. //canvas1.Rotate(200);
  277. //canvas2.Rotate(260);
  278. //canvasRoot.Rotate(90);
  279. CurrentPosition = ModuleName.System.ToString();
  280. CurrentArmA = CurrentArmB = RobotConstant.RobotRetract;
  281. }
  282. protected override void OnRender(DrawingContext drawingContext)
  283. {
  284. base.OnRender(drawingContext);
  285. if (DesignerProperties.GetIsInDesignMode(this))
  286. {
  287. return;
  288. }
  289. //if (RobotTarget != null || ArmAExtended != null || ArmBExtended != null)
  290. //{
  291. // LogMsg(string.Format("Received ------ Target: {0} ArmA: {1} ArmB: {2} ", RobotTarget, ArmAExtended, ArmBExtended));
  292. Invoke(() => MoveRobot(new AnimationParameter() { Target = RobotTarget, ArmA = ArmAExtended, ArmB = ArmBExtended }));
  293. //}
  294. }
  295. private void Queue_StatusUpdated(object sender, StatusUpdateArgs e)
  296. {
  297. LogMsg(string.Format("Target: {0} - {1}", CurrentPosition, e.Parameter.Target));
  298. var nextEvent = new AutoResetEvent(false);
  299. var next = new Action(() =>
  300. {
  301. nextEvent.Set();
  302. });
  303. var wait = new Action(() =>
  304. {
  305. if (!nextEvent.WaitOne(AnimationTimeout))
  306. {
  307. LogMsg("Aniamtion time out!");
  308. }
  309. });
  310. var done = new Action(() =>
  311. {
  312. CurrentPosition = e.Parameter.Target;
  313. CurrentArmA = e.Parameter.ArmA;
  314. CurrentArmB = e.Parameter.ArmB;
  315. e.Event.Set();
  316. });
  317. var needMove = CurrentPosition != e.Parameter.Target || CurrentArmA != e.Parameter.ArmA || CurrentArmB != e.Parameter.ArmB;
  318. if (needMove)
  319. {
  320. Invoke(() => MoveRobot(e.Parameter, next));
  321. wait();
  322. }
  323. done();
  324. }
  325. private void MoveRobot(AnimationParameter parameter, Action onComplete = null)
  326. {
  327. MoveToStart(parameter.Target, () => TranslateTo(parameter.Target, () => MoveToEnd(parameter, onComplete)));
  328. }
  329. private void MoveToStart(string station, Action onComplete = null)
  330. {
  331. //if (StationPosition == null || station == "Unknown" || station == null)
  332. // return;
  333. //var position = StationPosition[station];
  334. //canvas1.Rotate(position.StartPosition.Root, true, MoveTime);
  335. //CurrentPosition = station;
  336. onComplete?.Invoke();
  337. }
  338. private void MoveToEnd(AnimationParameter parameter, Action onComplete = null)
  339. {
  340. //var position = StationPosition[parameter.Target];
  341. //var extended = false;
  342. //if (parameter.ArmA == RobotConstant.RobotExtend)
  343. //{
  344. // extended = true;
  345. // canvas1.Rotate(position.EndPosition.Root, true, MoveTime, 0, 0, onComplete);
  346. // canvas2.Rotate(position.EndPosition.Arm, true, MoveTime);
  347. //}
  348. //CurrentPosition = parameter.Target;
  349. //if (!extended)
  350. //{
  351. onComplete?.Invoke();
  352. //}
  353. }
  354. private void TranslateTo(string station, Action onComplete = null)
  355. {
  356. //var position = StationPosition[station];
  357. //if (position.StartPosition.X.HasValue)
  358. //{
  359. // Translate(position.StartPosition.X.Value, onComplete);
  360. //}
  361. //else
  362. //{
  363. Translate(CurrentValue, onComplete);
  364. onComplete?.Invoke();
  365. //}
  366. }
  367. private int oldCurrentValue = 0;
  368. int oldX = 0;
  369. private void Translate(int x, Action onComplete = null)
  370. {
  371. //var storyBoard = new Storyboard();
  372. //var oldX = translate.X;
  373. //AnimationHelper.TranslateY(canvasRoot, (int)oldX, x, MoveTime, onComplete);
  374. //oldX = x;
  375. //var animation = new DoubleAnimation(oldX, x, TimeSpan.FromMilliseconds(MoveTime));
  376. //storyBoard.Children.Add(animation);
  377. //Storyboard.SetTarget(animation, root);
  378. //var propertyChain = new DependencyProperty[]
  379. // {
  380. // Canvas.RenderTransformProperty,
  381. // TransformGroup.ChildrenProperty,
  382. // TranslateTransform.XProperty
  383. // };
  384. //string thePath = "(0).(1)[1].(2)";
  385. //PropertyPath myPropertyPath = new PropertyPath(thePath, propertyChain);
  386. //Storyboard.SetTargetProperty(animation, myPropertyPath);
  387. //storyBoard.Completed += (s, e) =>
  388. //{
  389. // //InvalidateVisual();
  390. // if (onComplete != null)
  391. // {
  392. // onComplete();
  393. // }
  394. //};
  395. //storyBoard.Begin();
  396. if (oldCurrentValue != x)
  397. {
  398. var xValue = (int)((((float)x) / (MinValue - MaxValue)) * (homePositionX - processPositionX));
  399. AnimationHelper.TranslateY(canvasRoot, oldX, xValue, MoveTime, onComplete);
  400. oldX = xValue;
  401. oldCurrentValue = x;
  402. }
  403. }
  404. private void MoveTo(object obj)
  405. {
  406. var para = (Tuple<string, string, string>)obj;
  407. MoveRobot(new AnimationParameter() { Target = para.Item1, ArmA = para.Item2, ArmB = para.Item3 });
  408. }
  409. private void Invoke(Action action)
  410. {
  411. Dispatcher.Invoke(action);
  412. }
  413. private void LogMsg(string msg)
  414. {
  415. var source = "ATMRobot";
  416. Console.WriteLine("{0} {1}", source, msg);
  417. }
  418. }
  419. }