RecipeEditorControlViewModel.cs 84 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Collections.ObjectModel;
  4. using System.ComponentModel;
  5. using System.Diagnostics;
  6. using System.IO;
  7. using System.Linq;
  8. using System.Reflection;
  9. using System.Text.RegularExpressions;
  10. using System.Threading.Tasks;
  11. using System.Windows;
  12. using System.Windows.Controls;
  13. using System.Windows.Data;
  14. using System.Windows.Input;
  15. using System.Windows.Media;
  16. using System.Xml;
  17. using Aitex.UI.RecipeEditor.Core;
  18. using Aitex.UI.RecipeEditor.View;
  19. using ExcelLibrary.SpreadSheet;
  20. using Microsoft.Win32;
  21. using Xceed.Wpf.DataGrid;
  22. namespace Aitex.UI.RecipeEditor
  23. {
  24. public class RecipeEditorControlViewModel : INotifyPropertyChanged
  25. {
  26. private ObservableCollection<RecipeModel> m_RecipeModelObservableCollection = new ObservableCollection<RecipeModel>();
  27. public ObservableCollection<RecipeModel> RecipeModelObservableCollection
  28. {
  29. get { return m_RecipeModelObservableCollection; }
  30. set { m_RecipeModelObservableCollection = value; InvokePropertyChanged("RecipeModelObservableCollection"); }
  31. }
  32. private Visibility m_DataGridVisibility=Visibility.Collapsed;
  33. public Visibility DataGridVisibility
  34. {
  35. get { return m_DataGridVisibility; }
  36. set { m_DataGridVisibility = value; InvokePropertyChanged("DataGridVisibility"); }
  37. }
  38. public ICommand AddStepCommand { get; set; }
  39. public ICommand DeleteStepCommand { get; set; }
  40. public List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>> UndoList { get; set; }
  41. public List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>> RedoList { get; set; }
  42. public bool IsUndoEnabled { get { return UndoList != null && UndoList.Count > 0; } }
  43. public bool IsRedoEnabled { get { return RedoList != null && RedoList.Count > 0; } }
  44. public ObservableCollection<RecipeRow> RecipeRows { get; set; }
  45. private ObservableCollection<RecipeRow> _previousRecipeRows { get; set; }
  46. private string _valueBeforeEditing { get; set; }
  47. private string _currentRecipeVariationName = string.Empty;
  48. private SmartCellData _currentEditingCellData { get; set; }
  49. public List<Tuple<int/*row no*/, int/*col no*/, string/*var name*/, string/*reason*/>> Errors { get; set; }
  50. public List<Tuple<string, string>> CreateRecipeList { get; set; }
  51. public List<Tuple<string, string>> OpenRecipeList { get; set; }
  52. public DataGrid DataGridControl { get; set; }
  53. public int CurrentRunningStepNo { get; set; }
  54. public Visibility SingleAppElementVisibility { get; set; }
  55. public Visibility RecipeInfoTextVisibility { get; set; }
  56. public ICommand ShowDetailedErrInfoCommand { get; set; }
  57. public ICommand EditRecipeInfoCommand { get; set; }
  58. //public ICommand CellContentChangedCommand { get; set; }
  59. public ICommand RightClickCommand { get; set; }
  60. public ICommand OpenLocalRecipeCommand { get; set; }
  61. public ICommand ExpandGroupCommand { get; set; }
  62. public ICommand CollapseGroupCommand { get; set; }
  63. public ICommand SaveRecipeCommand { get; set; }
  64. public ICommand RecipeHelpDocCommand { get; set; }
  65. public ICommand RecipeExport2ExcelCommand { get; set; }
  66. public ICommand ToggleHideSameCommand { get; set; }
  67. public ICommand UndoCommand { get; set; }
  68. public ICommand RedoCommand { get; set; }
  69. public ICommand SmartCellEditorLoadedCommand { get; set; }
  70. public ICommand SmartCellEditorUnloadedCommand { get; set; }
  71. public RecipeHead RecipeHead { get; set; }
  72. public bool IsBusy { get; set; }
  73. public bool IsHideSameContent { get; set; }
  74. public string RecipeInfo { get; set; }
  75. public HashSet<string> MaskedTechNames { get; set; }
  76. public HashSet<string> MaskedCatalogNames { get; set; }
  77. public event EventHandler OnSaveRecipeFile;
  78. public event EventHandler OnLocalRecipeOpened;
  79. public event EventHandler OnLoadRecipeContent;
  80. public bool IsRecipeModified { get; set; }
  81. public string UserName { set; get; }
  82. //private List<Tuple<string, string, string>> SourceDilteInjectRestrictions { get; set; }
  83. private Dictionary<string, string> _preDefinedRecipeVars { get; set; }
  84. private List<Tuple<string/*varName*/, string/*check condition*/, string/*message*/>> _validationRules { get; set; }
  85. private List<string> _checkVariables { get; set; }
  86. private Dictionary<string, int> RowVarNameDic { get; set; }
  87. private Dictionary<int, List<SmartCellData>> _copiedColumnDatas = new Dictionary<int, List<SmartCellData>>();
  88. private Dictionary<string/*CatalogName*/, Dictionary<string/*GroupName*/, List<RecipeVariableDefine/*StepList*/>>> _recipeReadingFormat;
  89. private Dictionary<string/*ModuleName*/, List<string>/*each item's control name*/> _recipeSavingFormat;
  90. private string _currentRecipeFormatContent;
  91. public bool IsBarcodeEnabled
  92. {
  93. get; set;
  94. }
  95. public Visibility IsBarcodeVisibility
  96. {
  97. get
  98. {
  99. return IsBarcodeEnabled ? Visibility.Visible : Visibility.Hidden;
  100. }
  101. }
  102. private string _defaultEndPointValue { get; set; }
  103. /// <summary>
  104. /// class construction
  105. /// </summary>
  106. public RecipeEditorControlViewModel()
  107. {
  108. UndoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>();
  109. RedoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>();
  110. //if(SingleAppElementVisibility
  111. CreateRecipeList = new List<Tuple<string, string>>();
  112. OpenRecipeList = new List<Tuple<string, string>>();
  113. foreach (var item in GetDefinedRecipeVariations())
  114. {
  115. CreateRecipeList.Add(new Tuple<string, string>("配置:" + item, item));
  116. OpenRecipeList.Add(new Tuple<string, string>("转换为配置:" + item, item));
  117. }
  118. RecipeInfoTextVisibility = Visibility.Collapsed;
  119. SingleAppElementVisibility = Visibility.Collapsed;
  120. RightClickCommand = new DelegatedCommand((o) => true, (o) => RightClickAction());
  121. SaveRecipeCommand = new DelegatedCommand((o) => true, (o) => SaveRecipeFile());
  122. OpenLocalRecipeCommand = new DelegatedCommand((o) => true, (o) => OpenLocalRecipe());
  123. ShowDetailedErrInfoCommand = new DelegatedCommand((o) => true, (o) => ShowDetailedErrInformation());
  124. EditRecipeInfoCommand = new DelegatedCommand((o) => true, (o) => EditRecipeInformation());
  125. RecipeHelpDocCommand = new DelegatedCommand((o) => true, (o) => ShowHelpDocView());
  126. ToggleHideSameCommand = new DelegatedCommand((o) => true, (o) => ToggleHideSameContent());
  127. AddStepCommand = new DelegatedCommand((o) => true, (o) => OnAddStep());
  128. DeleteStepCommand = new DelegatedCommand((o) => true, (o) => OnDeleteStep());
  129. }
  130. private void OnAddStep()
  131. {
  132. RecipeModelObservableCollection.Add(new RecipeModel() { Name = "Zack",StepEndMode="Time" ,ValveControlMode="VAT"});
  133. }
  134. private void OnDeleteStep()
  135. {
  136. RecipeModelObservableCollection.RemoveAt(RecipeModelObservableCollection.Count-1);
  137. }
  138. /// <summary>
  139. /// hide or show same content before and after one step
  140. /// </summary>
  141. private void ToggleHideSameContent()
  142. {
  143. IsHideSameContent = !IsHideSameContent;
  144. RefreshCellsDisplay(false);
  145. }
  146. /// <summary>
  147. /// get recipe variations
  148. /// </summary>
  149. /// <returns></returns>
  150. public List<string> GetDefinedRecipeVariations()
  151. {
  152. var list1 = new List<string>();
  153. var dir = new System.IO.FileInfo(Process.GetCurrentProcess().MainModule.FileName).Directory;
  154. string cfgPath = dir + "\\Config\\";
  155. var di = new System.IO.DirectoryInfo(cfgPath);
  156. if (di.Exists)
  157. {
  158. foreach (var item in di.GetFiles("*.xml"))
  159. {
  160. list1.Add(item.Name.Substring(0, item.Name.Length - item.Extension.Length));
  161. }
  162. }
  163. return list1;
  164. }
  165. /// <summary>
  166. /// Show recipe information
  167. /// </summary>
  168. private void ShowHelpDocView()
  169. {
  170. var view = RecipeHelpView.Instance;
  171. view.Owner = Application.Current.MainWindow;
  172. view.DataContext = this;
  173. if (view.Visibility == Visibility.Visible)
  174. view.Hide();
  175. else
  176. view.Show();
  177. }
  178. /// <summary>
  179. /// Edit recipe information
  180. /// </summary>
  181. private void EditRecipeInformation()
  182. {
  183. RecipeInfoEditor editor = new RecipeInfoEditor() { RecipeHead = this.RecipeHead, Owner = Application.Current.MainWindow };
  184. editor.ShowDialog();
  185. InvokePropertyChanged("RecipeHead");
  186. }
  187. public void EnableBarcode(bool enable)
  188. {
  189. IsBarcodeEnabled = enable;
  190. InvokePropertyChanged("IsBarcodeVisibility");
  191. }
  192. public void SetCurrentUser(string user)
  193. {
  194. UserName = user;
  195. InvokePropertyChanged("UserName");
  196. }
  197. public void SetEndPointDefaultValue(string defaultValue)
  198. {
  199. _defaultEndPointValue = defaultValue;
  200. }
  201. /// <summary>
  202. /// Show recipe information
  203. /// </summary>
  204. private void ShowDetailedErrInformation()
  205. {
  206. var view = ErrorInformationDetailsView.Instance;
  207. view.Owner = Application.Current.MainWindow;
  208. view.DataContext = this;
  209. if (view.Visibility == Visibility.Visible)
  210. view.Hide();
  211. else
  212. view.ShowDialog();
  213. }
  214. /// <summary>
  215. /// Update selected cells data
  216. /// </summary>
  217. /// <returns>overrided cells number</returns>
  218. private int OverrideSelectedCellsData()
  219. {
  220. int overridedCellsNum = 0;
  221. //if (_currentEditingCellData != null)
  222. //{
  223. // var finalCellData = _currentEditingCellData;
  224. // bool containsEditingCell = false;
  225. // foreach (var item in DataGridControl.SelectedCellRanges)
  226. // {
  227. // int startColIndex = Math.Min(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  228. // int endColIndex = Math.Max(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  229. // int startRowIndex = Math.Min(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  230. // int endRowIndex = Math.Max(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  231. // if (startColIndex > 0 && startColIndex <= RecipeRows[0].RecipeItems.Count &&
  232. // endColIndex > 0 && endColIndex <= RecipeRows[0].RecipeItems.Count &&
  233. // startRowIndex >= 0 && startRowIndex < RecipeRows.Count &&
  234. // endRowIndex >= 0 && endRowIndex < RecipeRows.Count)
  235. // {
  236. // for (int m = startRowIndex; m <= endRowIndex; m++)
  237. // {
  238. // for (int n = startColIndex; n <= endColIndex; n++)
  239. // {
  240. // int rowIndex = m;
  241. // int colIndex = n - 1;
  242. // if (RecipeRows[rowIndex].RecipeItems[colIndex] == _currentEditingCellData)
  243. // {
  244. // containsEditingCell = true;
  245. // break;
  246. // }
  247. // }
  248. // }
  249. // }
  250. // }
  251. // if (containsEditingCell)
  252. // {
  253. // foreach (var item in DataGridControl.SelectedCellRanges)
  254. // {
  255. // int startColIndex = Math.Min(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  256. // int endColIndex = Math.Max(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  257. // int startRowIndex = Math.Min(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  258. // int endRowIndex = Math.Max(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  259. // if (startColIndex > 0 && startColIndex <= RecipeRows[0].RecipeItems.Count &&
  260. // endColIndex > 0 && endColIndex <= RecipeRows[0].RecipeItems.Count &&
  261. // startRowIndex >= 0 && startRowIndex < RecipeRows.Count &&
  262. // endRowIndex >= 0 && endRowIndex < RecipeRows.Count)
  263. // {
  264. // for (int m = startRowIndex; m <= endRowIndex; m++)
  265. // {
  266. // for (int n = startColIndex; n <= endColIndex; n++)
  267. // {
  268. // int rowIndex = m;
  269. // int colIndex = n - 1;
  270. // if (RecipeRows[rowIndex].RecipeItems[colIndex].RecipeVariableDefine.CellType == finalCellData.RecipeVariableDefine.CellType)
  271. // {
  272. // overridedCellsNum++;
  273. // RecipeRows[rowIndex].RecipeItems[colIndex].Value = finalCellData.Value;
  274. // RecipeRows[rowIndex].RecipeItems[colIndex].InvokePropertyChanged();
  275. // }
  276. // }
  277. // }
  278. // }
  279. // }
  280. // }
  281. //}
  282. return overridedCellsNum;
  283. }
  284. /// <summary>
  285. /// Open local recipe operation
  286. /// </summary>
  287. /// <param name="recipeDefineFilePath"></param>
  288. public void OpenLocalRecipe(string recipeVariationName = "")
  289. {
  290. var dlg = new OpenFileDialog();
  291. dlg.DefaultExt = ".rcp";
  292. dlg.Filter = "Recipe File (.rcp)|*.rcp|All (*.*)|*.*";
  293. if (dlg.ShowDialog() == true)
  294. {
  295. try
  296. {
  297. XmlDocument rcpDoc = new XmlDocument();
  298. rcpDoc.Load(dlg.FileName);
  299. string recipeVariation = recipeVariationName;
  300. if (string.IsNullOrEmpty(recipeVariation))
  301. {
  302. var root = rcpDoc.SelectSingleNode("/TableRecipeData") as XmlElement;
  303. recipeVariation = root.Attributes["RecipeVersion"].Value;
  304. }
  305. var startupPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
  306. string dir = System.IO.Path.GetDirectoryName(startupPath);
  307. List<Aitex.Controls.RecipeCompare.Item> map = CustomXmlSerializer.Deserialize<List<Aitex.Controls.RecipeCompare.Item>>(new System.IO.FileInfo(System.IO.Path.Combine(dir, "map.xml")));
  308. Func<Aitex.Controls.RecipeCompare.Item, bool> predicate = item => item.Name.Equals(recipeVariation);
  309. System.IO.FileInfo fi = new System.IO.FileInfo(string.Format("{0}\\config\\{1}.xml", dir, map.Any(predicate) ? map.Single(predicate).No : recipeVariation));
  310. if (fi.Exists)
  311. {
  312. XmlDocument doc = new XmlDocument();
  313. doc.Load(fi.FullName);
  314. string formatXml = doc.SelectSingleNode("/Aitex/TableRecipeFormat").OuterXml;
  315. string recipeXml = rcpDoc.SelectSingleNode("/TableRecipeData").OuterXml;
  316. LoadRecipe(formatXml, recipeXml);
  317. if (OnLocalRecipeOpened != null)
  318. OnLocalRecipeOpened.Invoke(new Tuple<string, string>(recipeVariation, dlg.FileName), null);
  319. }
  320. else
  321. {
  322. MessageBox.Show(string.Format("工艺程序版本{0}的描述文件不存在,无法正确识别该版本的工艺程序文件。", recipeVariation), "工艺程序打开失败",
  323. MessageBoxButton.OK, MessageBoxImage.Error);
  324. }
  325. }
  326. catch (Exception ex)
  327. {
  328. System.Diagnostics.Debug.WriteLine(ex.Message);
  329. MessageBox.Show(string.Format("open recipe {0} failed,please confirm the recipe file is exist and valid。\r\n{1}", dlg.FileName, ex.Message), "Open recipe failed",
  330. MessageBoxButton.OK, MessageBoxImage.Error);
  331. }
  332. }
  333. }
  334. /// <summary>
  335. /// Save recipe file
  336. /// </summary>
  337. private void SaveRecipeFile()
  338. {
  339. try
  340. {
  341. if (Errors != null && Errors.Count > 0)
  342. {
  343. var ret = MessageBox.Show(string.Format("Recipe have {0} error,continue save?", Errors.Count), "Save", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
  344. if (ret != MessageBoxResult.Yes)
  345. return;
  346. }
  347. if (OnSaveRecipeFile != null)
  348. {
  349. IsRecipeModified = false;
  350. OnSaveRecipeFile.Invoke(GetRecipeContentString(), null);
  351. }
  352. }
  353. catch (Exception ex)
  354. {
  355. System.Diagnostics.Debug.WriteLine(ex.Message);
  356. MessageBox.Show("save recipe failed!\r\n\r\n" + ex.Message, "Save", MessageBoxButton.OK, MessageBoxImage.Warning);
  357. }
  358. }
  359. /// <summary>
  360. /// get string typed recipe content
  361. /// </summary>
  362. /// <returns></returns>
  363. public string GetRecipeContentString()
  364. {
  365. if (string.IsNullOrEmpty(UserName))
  366. {
  367. var dlg1 = new Aitex.UI.RecipeEditor.UserNameInput() { Owner = Application.Current.MainWindow };
  368. var ret = dlg1.ShowDialog();
  369. if (ret.HasValue && ret.Value)
  370. {
  371. UserName = dlg1.UserName;
  372. }
  373. }
  374. RecipeHead.LastRevisionTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
  375. RecipeHead.LastModifiedBy = UserName;
  376. InvokePropertyChanged("RecipeHead");
  377. if (RecipeRows == null || RecipeRows.Count == 0 || RecipeRows[0].RecipeItems == null || RecipeRows[0].RecipeItems.Count == 0)
  378. return string.Empty;
  379. //Dictionary<string/*CatalogName*/, Dictionary<string/*GroupName*/, List<RecipeVariableDefine/*StepList*/>>> _recipeReadingFormat;
  380. XmlDocument doc = new XmlDocument();
  381. var rootNode = doc.CreateElement("TableRecipeData");
  382. rootNode.SetAttribute("RecipeVersion", RecipeHead.RecipeVariation);
  383. rootNode.SetAttribute("CreatedBy", RecipeHead.CreatedBy);
  384. rootNode.SetAttribute("CreationTime", RecipeHead.CreationTime);
  385. rootNode.SetAttribute("LastRevisedBy", RecipeHead.LastModifiedBy);
  386. rootNode.SetAttribute("LastRevisionTime", RecipeHead.LastRevisionTime);
  387. if (!string.IsNullOrEmpty(RecipeHead.PressureMode))
  388. {
  389. rootNode.SetAttribute("PressureMode", RecipeHead.PressureMode);
  390. }
  391. if (!string.IsNullOrEmpty(RecipeHead.BasePressure))
  392. {
  393. rootNode.SetAttribute("BasePressure", RecipeHead.BasePressure);
  394. }
  395. if (!string.IsNullOrEmpty(RecipeHead.SubstrateTemp))
  396. {
  397. rootNode.SetAttribute("SubstrateTemp", RecipeHead.SubstrateTemp);
  398. }
  399. if (!string.IsNullOrEmpty(RecipeHead.PumpingPinState))
  400. {
  401. rootNode.SetAttribute("PumpingPinState", RecipeHead.PumpingPinState);
  402. }
  403. if(!string.IsNullOrEmpty(RecipeHead.VentingPinState))
  404. {
  405. rootNode.SetAttribute("VentingPinState", RecipeHead.VentingPinState);
  406. }
  407. if(!string.IsNullOrEmpty(RecipeHead.PinDownPressure))
  408. {
  409. rootNode.SetAttribute("PinDownPressure", RecipeHead.PinDownPressure);
  410. }
  411. if (!string.IsNullOrEmpty(RecipeHead.PumpDownLimit))
  412. {
  413. rootNode.SetAttribute("PumpDownLimit", RecipeHead.PumpDownLimit);
  414. }
  415. if (!string.IsNullOrEmpty(RecipeHead.PurgeActive))
  416. {
  417. rootNode.SetAttribute("PurgeActive", RecipeHead.PurgeActive);
  418. }
  419. if (!string.IsNullOrEmpty(RecipeHead.NotToPurgeOrVent))
  420. {
  421. rootNode.SetAttribute("NotToPurgeOrVent", RecipeHead.NotToPurgeOrVent);
  422. }
  423. rootNode.SetAttribute("Barcode", RecipeHead.Barcode);
  424. rootNode.SetAttribute("Description", RecipeHead.Description);
  425. doc.AppendChild(rootNode);
  426. for (int stepIndex/* 0-> */ = 0; stepIndex < RecipeRows[0].RecipeItems.Count; stepIndex++)
  427. {
  428. var stepNode = doc.CreateElement("Step");
  429. rootNode.AppendChild(stepNode);
  430. foreach (var module in _recipeSavingFormat)
  431. {
  432. var moduleName = module.Key;
  433. XmlElement subNode = stepNode;
  434. if (!string.IsNullOrEmpty(moduleName))
  435. {
  436. string[] pathArr = moduleName.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
  437. for (int i = 0; i < pathArr.Length; i++)
  438. {
  439. var snd = subNode.SelectSingleNode(pathArr[i]) as XmlElement;
  440. if (snd == null)
  441. {
  442. var nd = doc.CreateElement(pathArr[i]);
  443. subNode.AppendChild(nd);
  444. subNode = nd;
  445. }
  446. else
  447. {
  448. subNode = snd;
  449. }
  450. }
  451. }
  452. foreach (var controlName in module.Value)
  453. {
  454. if (controlName == "StepNo")
  455. {
  456. subNode.SetAttribute(controlName, string.Format("第{0}步", stepIndex + 1));
  457. }
  458. else
  459. {
  460. var recipeRow = RecipeRows.First((o) => o.TechnicalName == controlName);
  461. if (recipeRow == null) continue;
  462. /*to compatiable with old recipe editor, always fill 'black space' to loop step*/
  463. if (controlName == "Loop" && string.IsNullOrEmpty(recipeRow.RecipeItems[stepIndex].Value))
  464. subNode.SetAttribute(controlName, " ");
  465. else
  466. {
  467. subNode.SetAttribute(controlName, recipeRow.RecipeItems[stepIndex].Value);
  468. //bool isJump = recipeRow.RecipeItems[stepIndex].IsJump;
  469. //if (isJump)
  470. //{
  471. // string deviceType = recipeRow.RecipeItems[stepIndex].RecipeVariableDefine.DeviceType;
  472. // if (deviceType == "MFC" || deviceType == "PC")
  473. // subNode.SetAttribute(controlName + ".IsJump", isJump.ToString());
  474. //}
  475. }
  476. }
  477. }
  478. }
  479. }
  480. return doc.OuterXml;
  481. }
  482. private void RightClickAction()
  483. {
  484. //DataGridControl.ContextMenu = null;
  485. ////get selected column information
  486. //List<int> selectedColumns = new List<int>();
  487. //foreach (var item in DataGridControl.SelectedCellRanges)
  488. //{
  489. // bool dir = item.ColumnRange.StartIndex <= item.ColumnRange.EndIndex;
  490. // if (dir)
  491. // {
  492. // for (int i = item.ColumnRange.StartIndex; i <= item.ColumnRange.EndIndex; i++)
  493. // {
  494. // if (i > 0)
  495. // if (!selectedColumns.Contains(i)) selectedColumns.Add(i);
  496. // }
  497. // }
  498. // else
  499. // {
  500. // for (int i = item.ColumnRange.StartIndex; i >= item.ColumnRange.EndIndex; i--)
  501. // {
  502. // if (i > 0)
  503. // if (!selectedColumns.Contains(i)) selectedColumns.Add(i);
  504. // }
  505. // }
  506. //}
  507. //selectedColumns.Sort();
  508. ////debug only
  509. ///*
  510. //string s = "";
  511. //foreach (var item in selectedColumns)
  512. //{
  513. // s += "," + item;
  514. //}
  515. //MessageBox.Show(s);
  516. // * */
  517. ////generate context menu
  518. //ContextMenu cms = new ContextMenu();
  519. //if (selectedColumns.Count > 0)
  520. //{
  521. // string colStrings = "";
  522. // foreach (var item in selectedColumns)
  523. // {
  524. // if (string.IsNullOrEmpty(colStrings))
  525. // colStrings = item.ToString();
  526. // else
  527. // colStrings += "," + item.ToString();
  528. // }
  529. // MenuItem mi;
  530. // cms.Items.Add(new MenuItem() { Header = string.Format(" 当前选中第{0}步", colStrings), FontFamily = new FontFamily("Arial,SimSun"), IsEnabled = false, Background = Brushes.Gray, Foreground = Brushes.White });
  531. // //copy
  532. // mi = new MenuItem() { Header = " 复制", FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns.ToList() };
  533. // mi.Click += (s, e) =>
  534. // {
  535. // try
  536. // {
  537. // var list = (s as MenuItem).Tag as List<int>;
  538. // _copiedColumnDatas.Clear();
  539. // foreach (var colId in list)
  540. // {
  541. // _copiedColumnDatas.Add(colId/*index from 1*/, new List<SmartCellData>());
  542. // for (int i = 0; i < RecipeRows.Count; i++)
  543. // {
  544. // var oldCellData = RecipeRows[i].RecipeItems[colId - 1];
  545. // var newCellData = new SmartCellData() { Value = oldCellData.Value, RecipeVariableDefine = oldCellData.RecipeVariableDefine };
  546. // _copiedColumnDatas[colId].Add(newCellData);
  547. // }
  548. // }
  549. // }
  550. // catch (Exception ex)
  551. // {
  552. // System.Diagnostics.Debug.WriteLine(ex.Message);
  553. // }
  554. // };
  555. // cms.Items.Add(mi);
  556. // if (selectedColumns.Count < RecipeRows[0].RecipeItems.Count)
  557. // {
  558. // mi = new MenuItem() { Header = " 剪切", FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns.ToList() };
  559. // mi.Click += (s, e) =>
  560. // {
  561. // try
  562. // {
  563. // AddUndoHistory("剪切", CloneRecipeRowData(RecipeRows));
  564. // var list = (s as MenuItem).Tag as List<int>;
  565. // _copiedColumnDatas.Clear();
  566. // foreach (var colId in list)
  567. // {
  568. // _copiedColumnDatas.Add(colId/*index from 1*/, new List<SmartCellData>());
  569. // for (int i = 0; i < RecipeRows.Count; i++)
  570. // {
  571. // var oldCellData = RecipeRows[i].RecipeItems[colId - 1];
  572. // var newCellData = new SmartCellData() { Value = oldCellData.Value, RecipeVariableDefine = oldCellData.RecipeVariableDefine };
  573. // _copiedColumnDatas[colId].Add(newCellData);
  574. // }
  575. // }
  576. // foreach (var item in RecipeRows)
  577. // {
  578. // var collection = new ObservableCollection<SmartCellData>();
  579. // for (int index = 0; index < item.RecipeItems.Count; index++)
  580. // {
  581. // if (list.Contains(index + 1))
  582. // continue;
  583. // collection.Add(item.RecipeItems[index]);
  584. // }
  585. // item.RecipeItems = collection;
  586. // }
  587. // RefreshDataGrid();
  588. // RefreshCellsDisplay(false);
  589. // }
  590. // catch (Exception ex)
  591. // {
  592. // System.Diagnostics.Debug.WriteLine(ex.Message);
  593. // }
  594. // };
  595. // cms.Items.Add(mi);
  596. // mi = new MenuItem() { Header = " 删除", FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns.ToList() };
  597. // mi.Click += (s, e) =>
  598. // {
  599. // try
  600. // {
  601. // AddUndoHistory("删除", CloneRecipeRowData(RecipeRows));
  602. // var list = (s as MenuItem).Tag as List<int>;
  603. // foreach (var item in RecipeRows)
  604. // {
  605. // var collection = new ObservableCollection<SmartCellData>();
  606. // for (int index = 0; index < item.RecipeItems.Count; index++)
  607. // {
  608. // if (list.Contains(index + 1))
  609. // continue;
  610. // collection.Add(item.RecipeItems[index]);
  611. // }
  612. // item.RecipeItems = collection;
  613. // }
  614. // RefreshDataGrid();
  615. // RefreshCellsDisplay(false);
  616. // }
  617. // catch (Exception ex)
  618. // {
  619. // System.Diagnostics.Debug.WriteLine(ex.Message);
  620. // }
  621. // };
  622. // cms.Items.Add(mi);
  623. // }
  624. // if (selectedColumns.Count == 1 && _copiedColumnDatas.Count > 0)
  625. // {
  626. // mi = new MenuItem() { Header = string.Format(" 插入第{0}步后", selectedColumns[0]/*, _copiedColumnDatas.Count*/), FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns[0] };
  627. // mi.Click += (s, e) =>
  628. // {
  629. // try
  630. // {
  631. // AddUndoHistory("插入", CloneRecipeRowData(RecipeRows));
  632. // int insertColId = (int)(s as MenuItem).Tag;
  633. // for (int rowIndex = 0; rowIndex < RecipeRows.Count; rowIndex++)
  634. // {
  635. // var collection = new ObservableCollection<SmartCellData>();
  636. // for (int index = 0; index < insertColId; index++)
  637. // {
  638. // collection.Add(RecipeRows[rowIndex].RecipeItems[index]);
  639. // }
  640. // foreach (var col in _copiedColumnDatas)
  641. // {
  642. // collection.Add(new SmartCellData() { Value = col.Value[rowIndex].Value, RecipeVariableDefine = col.Value[rowIndex].RecipeVariableDefine });
  643. // }
  644. // for (int index = insertColId; index < RecipeRows[rowIndex].RecipeItems.Count; index++)
  645. // {
  646. // collection.Add(RecipeRows[rowIndex].RecipeItems[index]);
  647. // }
  648. // RecipeRows[rowIndex].RecipeItems = collection;
  649. // }
  650. // RefreshDataGrid();
  651. // RefreshCellsDisplay(false);
  652. // }
  653. // catch (Exception ex)
  654. // {
  655. // System.Diagnostics.Debug.WriteLine(ex.Message);
  656. // }
  657. // };
  658. // cms.Items.Add(mi);
  659. // }
  660. //}
  661. ////show context menu
  662. //DataGridControl.ContextMenu = cms;
  663. //cms.Visibility = Visibility.Visible;
  664. }
  665. /// <summary>
  666. /// Parse recipe content with recipe format
  667. /// </summary>
  668. /// <param name="recipeFormat"></param>
  669. /// <param name="recipeContent"></param>
  670. /// <param name="selectedStepNo"></param>
  671. public void LoadRecipe(string recipeFormat, string recipeContent, int selectedStepNo = -1)
  672. {
  673. DataGridVisibility = Visibility.Visible;
  674. RecipeModelObservableCollection = new ObservableCollection<RecipeModel>() { new RecipeModel() { Name = "Alex" } };
  675. }
  676. /// <summary>
  677. /// 检查变量ramp rate
  678. /// </summary>
  679. /// <param name="stepNo"></param>
  680. /// <param name="rampEnable"></param>
  681. /// <param name="varName"></param>
  682. /// <param name="rampTime"></param>
  683. /// <param name="maxRampUpRate"></param>
  684. /// <param name="maxRampDownRate"></param>
  685. /// <returns>False:check ok, True: check failed</returns>
  686. public bool CheckRampRate(int stepNo, string rampEnable, string varName, string rampTime, double maxRampUpRate, double maxRampDownRate)
  687. {
  688. try
  689. {
  690. if (stepNo <= 0) return false;
  691. int rowIndex = RowVarNameDic[varName];
  692. double currentValue = double.Parse(RecipeRows[rowIndex].RecipeItems[stepNo].Value);
  693. //if (varName == "AZone.Setpoint" || varName == "BZone.Setpoint" || varName == "CZone.Setpoint" || varName == "DZone.Setpoint")
  694. //{
  695. // int heatControlModeIndex = RowVarNameDic["Heater.Mode"];
  696. // string curStepHeatCtrlMode = RecipeRows[heatControlModeIndex].RecipeItems[stepNo].Value;
  697. // string lastStepHeatCtrlMode = RecipeRows[heatControlModeIndex].RecipeItems[stepNo - 1].Value;
  698. // if (curStepHeatCtrlMode != lastStepHeatCtrlMode)
  699. // {
  700. // if (!(lastStepHeatCtrlMode.Equals("CurrentControl") && curStepHeatCtrlMode.Equals("PyroTempControl")))
  701. // return false;
  702. // int endbyIndex = RowVarNameDic["EndBy"];
  703. // int endValueIndex = RowVarNameDic["EndValue"];
  704. // string endby = RecipeRows[endbyIndex].RecipeItems[stepNo - 1].Value;
  705. // EndByCondition endbyEnum;
  706. // if (!Enum.TryParse(endby, out endbyEnum)) return false;
  707. // if (endbyEnum != EndByCondition.PmTempGt && endbyEnum != EndByCondition.PmTempLt) return false;
  708. // string end = RecipeRows[endValueIndex].RecipeItems[stepNo - 1].Value;
  709. // double endValue;
  710. // if (!double.TryParse(end, out endValue)) return false;
  711. // return CheckRampRate(rampEnable, rampTime, maxRampUpRate, maxRampDownRate, endValue, currentValue);
  712. // }
  713. //}
  714. double prevValue = double.Parse(RecipeRows[rowIndex].RecipeItems[stepNo - 1].Value);
  715. return CheckRampRate(rampEnable, rampTime, maxRampUpRate, maxRampDownRate, prevValue, currentValue);
  716. }
  717. catch (Exception ex)
  718. {
  719. System.Diagnostics.Debug.WriteLine(ex.Message);
  720. return true;
  721. }
  722. }
  723. bool CheckRampRate(string rampEnable, string rampTime, double maxRampUpRate, double maxRampDownRate, double prevValue, double currentValue)
  724. {
  725. bool isRampEnable = bool.Parse(rampEnable);
  726. //string[] timeStr = rampTime.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  727. //string tt = string.Join(":", timeStr);
  728. TimeSpan timeSpan;
  729. TimeSpan.TryParse(rampTime, out timeSpan);
  730. double totalTimeSec = timeSpan.TotalSeconds;
  731. double diff = currentValue - prevValue;
  732. if (!isRampEnable || totalTimeSec <= 0)
  733. {
  734. if (diff != 0) return true;
  735. return false;
  736. }
  737. else
  738. {
  739. double rampRate = diff / totalTimeSec;
  740. return (rampRate > 0 && rampRate >= maxRampUpRate) || (rampRate < 0 && rampRate <= -maxRampDownRate);
  741. }
  742. }
  743. /// <summary>
  744. /// Refresh datagrid cell data display
  745. /// </summary>
  746. /// <param name="moving2RunningStepPosition">True: moving to current running step position</param>
  747. public void RefreshCellsDisplay(bool moving2RunningStepPosition = true)
  748. {
  749. try
  750. {
  751. if (RecipeRows == null || RecipeRows.Count < 2)
  752. return;
  753. Errors = new List<Tuple<int, int, string, string>>();
  754. Dictionary<int, string> dicEndby = new Dictionary<int, string>();
  755. Dictionary<int, string> dicPressureMode = new Dictionary<int, string>();
  756. Dictionary<int, string> dicRfMode = new Dictionary<int, string>();
  757. Dictionary<int, string> dicRfMatchProcessMode = new Dictionary<int, string>();
  758. Dictionary<int, string> dicSetMatchPositionC1 = new Dictionary<int, string>();
  759. Dictionary<int, string> dicSetMatchPositionC2 = new Dictionary<int, string>();
  760. for (int i = 0; i < RecipeRows.Count; i++)
  761. {
  762. for (int j = 0; j < RecipeRows[i].RecipeItems.Count; j++)
  763. {
  764. var cell = RecipeRows[i].RecipeItems[j];
  765. cell.RowIndex = i;
  766. cell.ColIndex = j;
  767. cell.ErrInfo = string.Empty;
  768. bool logicEnable = true;
  769. if (cell.RecipeVariableDefine.TechnicalName == "EndBy")
  770. dicEndby[j] = cell.Value;
  771. if (cell.RecipeVariableDefine.TechnicalName == "ThrottleValve.SetMode")
  772. {
  773. dicPressureMode[j] = cell.Value;
  774. }
  775. if (cell.RecipeVariableDefine.TechnicalName == "PressureControl.SetTVMode")
  776. {
  777. dicPressureMode[j] = cell.Value;
  778. }
  779. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetMode")
  780. dicRfMode[j] = cell.Value;
  781. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchProcessMode")
  782. dicRfMatchProcessMode[j] = cell.Value;
  783. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC1")
  784. dicSetMatchPositionC1[j] = cell.Value;
  785. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC2")
  786. dicSetMatchPositionC2[j] = cell.Value;
  787. if (cell.RecipeVariableDefine.TechnicalName == "Time")
  788. {
  789. logicEnable = dicEndby.ContainsKey(j) && (dicEndby[j] == "EndByStepTime" ||
  790. dicEndby[j] == "EndByHeatUp" ||
  791. dicEndby[j] == "EndByEndPoint");
  792. }
  793. if (cell.RecipeVariableDefine.TechnicalName == "ThrottleValve.SetPosition")
  794. {
  795. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPositionCtrl";
  796. }
  797. if (cell.RecipeVariableDefine.TechnicalName == "ThrottleValve.SetPressure")
  798. {
  799. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPressureCtrl";
  800. }
  801. if (cell.RecipeVariableDefine.TechnicalName == "PressureControl.SetTVPosition")
  802. {
  803. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPositionCtrl";
  804. }
  805. if (cell.RecipeVariableDefine.TechnicalName == "PressureControl.SetTVPressure")
  806. {
  807. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPressureCtrl";
  808. }
  809. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetPulsingFrequency")
  810. {
  811. logicEnable = dicRfMode.ContainsKey(j) && dicRfMode[j] == "PulsingMode";
  812. }
  813. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetPulsingDuty")
  814. {
  815. logicEnable = dicRfMode.ContainsKey(j) && dicRfMode[j] == "PulsingMode";
  816. }
  817. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetPowerOnTime")
  818. {
  819. logicEnable = dicEndby.ContainsKey(j) && dicEndby[j] == "EndByRfTime";
  820. }
  821. if (cell.RecipeVariableDefine.TechnicalName == "EPD.SetConfig")
  822. {
  823. logicEnable = dicEndby.ContainsKey(j) && dicEndby[j] == "EndByEndPoint";
  824. if (string.IsNullOrEmpty(cell.Value) || cell.Value.StartsWith("n/a"))
  825. cell.Value = _defaultEndPointValue;
  826. }
  827. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchProcessMode")
  828. {
  829. logicEnable = dicRfMatchProcessMode.ContainsKey(j);// && dicRfMatchProcessMode[j] == "TritonPresetMode";
  830. }
  831. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC1")
  832. {
  833. logicEnable = dicSetMatchPositionC1.ContainsKey(j);// && dicRfMatchProcessMode[j] == "TritonPresetMode";
  834. }
  835. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC2")
  836. {
  837. logicEnable = dicSetMatchPositionC2.ContainsKey(j);// && dicRfMatchProcessMode[j] == "TritonPresetMode";
  838. }
  839. cell.IsMasked = !logicEnable;
  840. //update diff variable numbers
  841. if (cell.RecipeVariableDefine.TechnicalName == "Ramp")
  842. {
  843. //更新当前步骤中Ramp的变量数据
  844. if (j == 0)
  845. {
  846. cell.Tag = 0;
  847. }
  848. else
  849. {
  850. int rampNum = 0;
  851. for (int s1 = 0; s1 < RecipeRows.Count; s1++)
  852. {
  853. if (RecipeRows[s1].CatalogName == "StepInfo")// RecipeRows[s1].RecipeItems[j].RecipeVariableDefine.CellType == CellType.ReadOnly)
  854. continue;
  855. string preValue = RecipeRows[s1].RecipeItems[j - 1].Value;
  856. string curValue = RecipeRows[s1].RecipeItems[j].Value;
  857. if (RecipeRows[s1].RecipeItems[j].RecipeVariableDefine.CellType == CellType.NumInput)
  858. {
  859. double pd, cd;
  860. if (double.TryParse(preValue, out pd) && double.TryParse(curValue, out cd))
  861. if (pd != cd) rampNum++;
  862. }
  863. else if (String.Compare(preValue, curValue, false) != 0)
  864. {
  865. rampNum++;
  866. }
  867. }
  868. cell.Tag = rampNum;
  869. }
  870. cell.InvokePropertyChanged();
  871. }
  872. #region mask (hide or show cell content)
  873. if ((MaskedTechNames != null && MaskedTechNames.Contains(cell.RecipeVariableDefine.TechnicalName)) ||
  874. (MaskedCatalogNames != null && MaskedCatalogNames.Contains(cell.RecipeVariableDefine.CatalogName)) || !logicEnable)
  875. cell.IsMasked = true;
  876. else
  877. cell.IsMasked = false;
  878. #endregion mask (hide or show cell content)
  879. #region check cell data range
  880. switch (cell.RecipeVariableDefine.CellType)
  881. {
  882. case CellType.CheckBox:
  883. {
  884. if (string.Compare(cell.Value, "true", true) == 0 || string.Compare(cell.Value, "false", true) == 0)
  885. {
  886. cell.ErrInfo = "";
  887. cell.Background = Brushes.Transparent;
  888. }
  889. else
  890. {
  891. string reason = string.Format("Value '{0}' not valid", cell.Value);
  892. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  893. cell.ErrInfo = reason;
  894. cell.Background = Brushes.Pink;
  895. }
  896. }
  897. break;
  898. case CellType.EditableSelection:
  899. {
  900. cell.ErrInfo = "";
  901. cell.Background = Brushes.Transparent;
  902. }
  903. break;
  904. case CellType.NumInput:
  905. {
  906. double min = cell.RecipeVariableDefine.MinValue;
  907. double max = cell.RecipeVariableDefine.MaxValue;
  908. double v;
  909. if (!double.TryParse(cell.Value, out v))
  910. {
  911. string reason = string.Format("Value '{0}' not valid", cell.Value);
  912. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  913. cell.ErrInfo = reason;
  914. cell.Background = Brushes.Pink;
  915. }
  916. else if (v > max || v < 0 || (v < min && v > max * 0.1 / 100))
  917. {
  918. string reason = string.Format("Value'{0}',Out of Range {1}~{2}", cell.Value, min, max);
  919. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  920. cell.ErrInfo = reason;
  921. cell.Background = Brushes.Pink;
  922. }
  923. else
  924. {
  925. cell.ErrInfo = "";
  926. cell.Background = Brushes.Transparent;
  927. }
  928. }
  929. break;
  930. case CellType.ReadOnlySelection:
  931. {
  932. if (cell.RecipeVariableDefine.DropdownItemList != null && cell.RecipeVariableDefine.DropdownItemList.Find((o) => o.Item1 == cell.Value) != null)
  933. {
  934. cell.ErrInfo = "";
  935. cell.Background = Brushes.Transparent;
  936. }
  937. else
  938. {
  939. string reason = string.Format("Value'{0}' is not valid", cell.Value);
  940. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  941. cell.ErrInfo = reason;
  942. cell.Background = Brushes.Pink;
  943. }
  944. }
  945. break;
  946. case CellType.ReadOnly:
  947. case CellType.TextInput:
  948. cell.ErrInfo = "";
  949. cell.Background = Brushes.Transparent;
  950. break;
  951. case CellType.TimeInput:
  952. {
  953. string[] arr = cell.Value.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  954. int h, mi, s;
  955. if (arr.Length == 3 && int.TryParse(arr[0], out h) && int.TryParse(arr[1], out mi) && int.TryParse(arr[2], out s) && h >= 0 && mi >= 0 && mi <= 59 && s >= 0 && s <= 59)
  956. {
  957. cell.ErrInfo = "";
  958. cell.Background = Brushes.Transparent;
  959. }
  960. else
  961. {
  962. string reason = string.Format("value'{0}' is not valid", cell.Value);
  963. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  964. cell.ErrInfo = reason;
  965. cell.Background = Brushes.Pink;
  966. }
  967. }
  968. break;
  969. }
  970. #endregion check cell data range
  971. #region mark data trend / hide same content
  972. if (j == 0) //step one
  973. {
  974. cell.Foreground = Brushes.Black;
  975. cell.FontWeight = FontWeights.Normal;
  976. cell.IsHidden = false;
  977. cell.InvokePropertyChanged();
  978. cell.IsMasked = !logicEnable;
  979. continue;
  980. }
  981. var preCell = RecipeRows[i].RecipeItems[j - 1];
  982. if (cell.RecipeVariableDefine.CellType == CellType.NumInput)
  983. {
  984. double preValue = 0;
  985. double.TryParse(preCell.Value.ToString(), out preValue);
  986. double curValue = 0;
  987. double.TryParse(cell.Value.ToString(), out curValue);
  988. if (curValue > preValue)
  989. {
  990. cell.Foreground = Brushes.Red;
  991. cell.FontWeight = FontWeights.Bold;
  992. }
  993. else if (curValue < preValue)
  994. {
  995. cell.Foreground = Brushes.Blue;
  996. cell.FontWeight = FontWeights.Bold;
  997. }
  998. else
  999. {
  1000. cell.Foreground = Brushes.Black;
  1001. cell.FontWeight = FontWeights.Normal;
  1002. }
  1003. }
  1004. else
  1005. {
  1006. //not number type
  1007. cell.Foreground = Brushes.Black;
  1008. cell.FontWeight = FontWeights.Normal;
  1009. }
  1010. if (IsHideSameContent && cell.Value == preCell.Value)
  1011. cell.IsHidden = true;
  1012. else
  1013. cell.IsHidden = false;
  1014. //!logicEnable;
  1015. cell.IsMasked = !logicEnable;
  1016. //if (!logicEnable)
  1017. //{
  1018. // cell.Background = Brushes.DarkGray;
  1019. // cell.IsMasked = true;
  1020. //}
  1021. #endregion mark data trend / hide same content
  1022. cell.InvokePropertyChanged();
  1023. }
  1024. }
  1025. #region check loop
  1026. int loopRowId = -1;
  1027. for (int i = 0; i < RecipeRows.Count; i++)
  1028. {
  1029. if (RecipeRows[i].TechnicalName == "Loop")
  1030. {
  1031. loopRowId = i;
  1032. break;
  1033. }
  1034. }
  1035. for (int j = 0; j < RecipeRows[loopRowId].RecipeItems.Count; j++)
  1036. {
  1037. var cell = RecipeRows[loopRowId].RecipeItems[j];
  1038. bool isLoopStart = Regex.IsMatch(cell.Value, @"^Loop\x20\d+$");
  1039. bool isLoopEnd = Regex.IsMatch(cell.Value, @"^Loop End$");
  1040. bool isNullOrEmpty = string.IsNullOrWhiteSpace(cell.Value);
  1041. if (!isLoopEnd && !isLoopStart && !isNullOrEmpty)
  1042. {
  1043. string reason = string.Format("Value '{0}' not valid", cell.Value);
  1044. cell.ErrInfo = reason;
  1045. cell.Background = Brushes.Pink;
  1046. Errors.Add(new Tuple<int, int, string, string>(loopRowId, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1047. }
  1048. if (isLoopEnd)
  1049. {
  1050. string reason = "Loop Start 缺失";
  1051. cell.ErrInfo = reason;
  1052. cell.Background = Brushes.Pink;
  1053. Errors.Add(new Tuple<int, int, string, string>(loopRowId, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1054. }
  1055. else if (isLoopStart)
  1056. {
  1057. for (int k = j + 1; k < RecipeRows[loopRowId].RecipeItems.Count; k++)
  1058. {
  1059. cell = RecipeRows[loopRowId].RecipeItems[k];
  1060. bool isCurStepLoopStart = Regex.IsMatch(cell.Value, @"^Loop\x20\d+$");
  1061. bool isCurStepLoopEnd = Regex.IsMatch(cell.Value, @"^Loop End$");
  1062. isNullOrEmpty = string.IsNullOrWhiteSpace(cell.Value);
  1063. if (!isCurStepLoopEnd && !isCurStepLoopStart && !isNullOrEmpty)
  1064. {
  1065. string reason = string.Format("Value '{0}' not valid", cell.Value);
  1066. cell.ErrInfo = reason;
  1067. cell.Background = Brushes.Pink;
  1068. Errors.Add(new Tuple<int, int, string, string>(loopRowId, k, cell.RecipeVariableDefine.FriendlyName, reason));
  1069. }
  1070. else if (isCurStepLoopStart)
  1071. {
  1072. string reason = "前面循环没有结束,不能设置新的Loop Start标志";
  1073. cell.ErrInfo = reason;
  1074. cell.Background = Brushes.Pink;
  1075. Errors.Add(new Tuple<int, int, string, string>(loopRowId, k, cell.RecipeVariableDefine.FriendlyName, reason));
  1076. }
  1077. else if (isCurStepLoopEnd)
  1078. {
  1079. //mark loop steps with blue background
  1080. for (int m1 = j; m1 <= k; m1++)
  1081. {
  1082. var curCell = RecipeRows[loopRowId].RecipeItems[m1];
  1083. if (curCell.Background == Brushes.Transparent)
  1084. curCell.Background = Brushes.LightGreen;
  1085. curCell.InvokePropertyChanged();
  1086. }
  1087. j = k;
  1088. break;
  1089. }
  1090. if (k == RecipeRows[loopRowId].RecipeItems.Count - 1)
  1091. {
  1092. j = k;
  1093. string reason = "Loop End 缺失";
  1094. cell.ErrInfo = reason;
  1095. cell.Background = Brushes.Pink;
  1096. Errors.Add(new Tuple<int, int, string, string>(loopRowId, k, cell.RecipeVariableDefine.FriendlyName, reason));
  1097. }
  1098. }
  1099. }
  1100. }
  1101. #endregion check loop
  1102. #region recipe parameter validation
  1103. //using (var lua = new LuaInterface.Lua())
  1104. //{
  1105. // //is special recipe?
  1106. // //bool IsSpecialRecipe = true;
  1107. // //{
  1108. // // int heaterModeRowIndex = RowVarNameDic["Heater.Mode"];
  1109. // // int aZoneSetpointIndex = RowVarNameDic["AZone.Setpoint"];
  1110. // // int bZoneSetpointIndex = RowVarNameDic["BZone.Setpoint"];
  1111. // // int cZoneSetpointIndex = RowVarNameDic["CZone.Setpoint"];
  1112. // // int dZoneSetpointIndex = RowVarNameDic.ContainsKey("DZone.Setpoint") ? RowVarNameDic["DZone.Setpoint"] : aZoneSetpointIndex;
  1113. // // for (int stepIndex = 0; stepIndex < RecipeRows[0].RecipeItems.Count; stepIndex++)
  1114. // // {
  1115. // // if (RecipeRows[heaterModeRowIndex].RecipeItems[stepIndex].Value != "CurrentControl" ||
  1116. // // RecipeRows[aZoneSetpointIndex].RecipeItems[stepIndex].Value != "0" ||
  1117. // // RecipeRows[bZoneSetpointIndex].RecipeItems[stepIndex].Value != "0" ||
  1118. // // RecipeRows[cZoneSetpointIndex].RecipeItems[stepIndex].Value != "0" ||
  1119. // // RecipeRows[dZoneSetpointIndex].RecipeItems[stepIndex].Value != "0")
  1120. // // {
  1121. // // IsSpecialRecipe = false;
  1122. // // break;
  1123. // // }
  1124. // // }
  1125. // //}
  1126. // ////set get ramp rate function
  1127. // //lua.RegisterFunction("CheckRampRate", this, GetType().GetMethod("CheckRampRate"));
  1128. // //lua.DoString(string.Format("IsProductionRecipe={0};",(!IsSpecialRecipe).ToString().ToLower()));
  1129. // for (int stepIndex = 0; stepIndex < RecipeRows[0].RecipeItems.Count; stepIndex++)
  1130. // {
  1131. // //set stepNo
  1132. // lua.DoString(string.Format("StepNo={0};", stepIndex));
  1133. // //reading var from current recipe step
  1134. // foreach (var checkVar in _checkVariables)
  1135. // {
  1136. // if (!RowVarNameDic.ContainsKey(checkVar))
  1137. // {
  1138. // System.Diagnostics.Debug.WriteLine("检查不到变量定义," + checkVar);
  1139. // continue;
  1140. // }
  1141. // try
  1142. // {
  1143. // int varId = RowVarNameDic[checkVar];
  1144. // if (RecipeRows[varId].RecipeItems[stepIndex].RecipeVariableDefine.CellType == CellType.NumInput)
  1145. // lua.DoString(string.Format("{0}={1};", RecipeRows[varId].RecipeItems[stepIndex].RecipeVariableDefine.TechnicalName.Replace(".", "_"), RecipeRows[varId].RecipeItems[stepIndex].Value));
  1146. // else
  1147. // lua.DoString(string.Format("{0}=\"{1}\";", RecipeRows[varId].RecipeItems[stepIndex].RecipeVariableDefine.TechnicalName.Replace(".", "_"), RecipeRows[varId].RecipeItems[stepIndex].Value));
  1148. // }
  1149. // catch (Exception ex)
  1150. // {
  1151. // System.Diagnostics.Debug.WriteLine("校验异常," + ex);
  1152. // }
  1153. // }
  1154. // //reading from recipe format file
  1155. // foreach (string key in _preDefinedRecipeVars.Keys)
  1156. // {
  1157. // string varValueString = _preDefinedRecipeVars[key];
  1158. // double varValue;
  1159. // if (double.TryParse(varValueString, out varValue))
  1160. // lua.DoString(string.Format("{0}={1};", key, varValue));
  1161. // else
  1162. // lua.DoString(string.Format("{0}=\"{1}\";", key, varValueString));
  1163. // }
  1164. // //do valation
  1165. // foreach (var rule in _validationRules)
  1166. // {
  1167. // lua.DoString(string.Format("if {0} then hasErr=1 else hasErr=0 end", rule.Item2));
  1168. // bool hasError = ((int)lua.GetNumber("hasErr")) == 1;
  1169. // if (hasError)
  1170. // {
  1171. // lua.DoString(string.Format("message=string.format({0});", rule.Item3));
  1172. // string reason = lua.GetString("message");
  1173. // var rowId = RowVarNameDic[rule.Item1];
  1174. // var cell = RecipeRows[rowId].RecipeItems[stepIndex];
  1175. // cell.ErrInfo = reason;
  1176. // cell.Background = Brushes.Pink;
  1177. // Errors.Add(new Tuple<int, int, string, string>(rowId, stepIndex, cell.RecipeVariableDefine.FriendlyName, reason));
  1178. // cell.InvokePropertyChanged();
  1179. // }
  1180. // }
  1181. // }
  1182. //}
  1183. #endregion recipe parameter validation
  1184. #region update material cell data
  1185. int materialRowId = -1;
  1186. for (int colId = 0; colId < RecipeRows[0].RecipeItems.Count; colId++)
  1187. {
  1188. string materialName = "";
  1189. for (int rowId = 0; rowId < RecipeRows.Count; rowId++)
  1190. {
  1191. string curMo = "";
  1192. if (materialRowId == -1 && RecipeRows[rowId].RecipeItems[colId].RecipeVariableDefine.TechnicalName == "Material")
  1193. {
  1194. materialRowId = rowId;
  1195. }
  1196. var cell = RecipeRows[rowId].RecipeItems[colId];
  1197. if (cell.RecipeVariableDefine.CellType == CellType.ReadOnlySelection && String.Compare(cell.Value, "flow", true) == 0)
  1198. {
  1199. string moName = cell.RecipeVariableDefine.TechnicalName.Split('.')[0].ToLower();
  1200. string displayName = cell.RecipeVariableDefine.FriendlyName.Replace("_", ".").Split('.')[0].ToLower();
  1201. if (moName.Contains("cp2mg_1") || displayName.Contains("cp2mg_1")) curMo = "Mg1";
  1202. else if (moName.Contains("cp2mg_2") || displayName.Contains("cp2mg_2")) curMo = "Mg2";
  1203. else if (moName.Contains("cp2mg_3") || displayName.Contains("cp2mg_3")) curMo = "Mg3";
  1204. else if (moName.Contains("cp2mg_4") || displayName.Contains("cp2mg_4")) curMo = "Mg4";
  1205. else if (moName.Contains("cp2mg") || displayName.Contains("cp2mg")) curMo = "Mg";
  1206. else if (moName.Contains("tmin") || displayName.Contains("tmin")) curMo = "In";
  1207. else if (moName.Contains("tmin_1") || displayName.Contains("tmin_1")) curMo = "In1";
  1208. else if (moName.Contains("tmin_2") || displayName.Contains("tmin_2")) curMo = "In2";
  1209. else if (moName.Contains("tmin_3") || displayName.Contains("tmin_3")) curMo = "In3";
  1210. else if (moName.Contains("tmin_4") || displayName.Contains("tmin_4")) curMo = "In4";
  1211. else if (moName.Contains("tmga") || displayName.Contains("tmga")) curMo = "TMG";
  1212. else if (moName.Contains("tmga_1") || displayName.Contains("tmga_1")) curMo = "TMG1";
  1213. else if (moName.Contains("tmga_2") || displayName.Contains("tmga_2")) curMo = "TMG2";
  1214. else if (moName.Contains("tmga_3") || displayName.Contains("tmga_3")) curMo = "TMG3";
  1215. else if (moName.Contains("tmga_4") || displayName.Contains("tmga_4")) curMo = "TMG4";
  1216. else if (moName.Contains("tega") || displayName.Contains("tega")) curMo = "TEG";
  1217. else if (moName.Contains("tega_1") || displayName.Contains("tega_1")) curMo = "TEG1";
  1218. else if (moName.Contains("tega_2") || displayName.Contains("tega_2")) curMo = "TEG2";
  1219. else if (moName.Contains("tega_3") || displayName.Contains("tega_3")) curMo = "TEG3";
  1220. else if (moName.Contains("tega_4") || displayName.Contains("tega_4")) curMo = "TEG4";
  1221. else if (moName.Contains("tmal") || displayName.Contains("tmal")) curMo = "TAl";
  1222. else if (moName.Contains("tmal_1") || displayName.Contains("tmal_1")) curMo = "TAl1";
  1223. else if (moName.Contains("tmal_2") || displayName.Contains("tmal_2")) curMo = "TAl2";
  1224. else if (moName.Contains("tmal_3") || displayName.Contains("tmal_3")) curMo = "TAl3";
  1225. else if (moName.Contains("tmal_4") || displayName.Contains("tmal_4")) curMo = "TAl4";
  1226. else if (moName.Contains("nh3source") || displayName.Contains("nh3source")) curMo = "NH3";
  1227. else if (moName.Contains("si")) curMo = "Si";
  1228. if (!string.IsNullOrEmpty(curMo))
  1229. {
  1230. if (string.IsNullOrEmpty(materialName))
  1231. materialName = curMo;
  1232. else
  1233. materialName += "|" + curMo;
  1234. }
  1235. }
  1236. }
  1237. if (materialRowId >= 0)
  1238. {
  1239. RecipeRows[materialRowId].RecipeItems[colId].Value = materialName;
  1240. RecipeRows[materialRowId].RecipeItems[colId].InvokePropertyChanged();
  1241. }
  1242. }
  1243. #endregion update material cell data
  1244. #region update column header
  1245. //if (DataGridControl.Columns.Count - 1 == RecipeRows[0].RecipeItems.Count)
  1246. //{
  1247. // var redColHeader = (DataTemplate)DataGridControl.FindResource("columnRedTitleTemplate");
  1248. // var blackColHeader = (DataTemplate)DataGridControl.FindResource("columnBlackTitleTemplate");
  1249. // for (int j = 0; j < RecipeRows[0].RecipeItems.Count; j++)
  1250. // {
  1251. // DataGridControl.Columns[j + 1].Title = string.Format("{0}|{2}\r\n{1}", j + 1, RecipeRows[0].RecipeItems[j].Value, RecipeRows[2].RecipeItems[j].Value);
  1252. // if (Errors.Find((o) => o.Item2 == j) != null)
  1253. // DataGridControl.Columns[j + 1].TitleTemplate = redColHeader;
  1254. // else
  1255. // DataGridControl.Columns[j + 1].TitleTemplate = blackColHeader;
  1256. // }
  1257. //}
  1258. #endregion update column header
  1259. #region if running state, highlight current running step, move horizontal bar to current running step
  1260. if (CurrentRunningStepNo > 0 && DataGridControl.Columns.Count > 2)
  1261. {
  1262. for (int rowId = 0; rowId < RecipeRows.Count; rowId++)
  1263. {
  1264. for (int colId = 0; colId < RecipeRows[0].RecipeItems.Count; colId++)
  1265. {
  1266. var cell = RecipeRows[rowId].RecipeItems[colId];
  1267. if (colId + 1 == CurrentRunningStepNo)
  1268. {
  1269. cell.IsRunning = true;
  1270. }
  1271. else
  1272. {
  1273. cell.IsRunning = false;
  1274. }
  1275. cell.InvokePropertyChanged("IsRunning");
  1276. }
  1277. }
  1278. //if (moving2RunningStepPosition)
  1279. //{
  1280. // Task.Factory.StartNew(() =>
  1281. // {
  1282. // System.Threading.Thread.Sleep(200);
  1283. // DataGridControl.Dispatcher.Invoke(new Action(() =>
  1284. // {
  1285. // double singleWidth = DataGridControl.Columns[1].Width;
  1286. // double horizontalOffset = (CurrentRunningStepNo - 2) * singleWidth;
  1287. // if (DataGridControl.ScrollViewer != null)
  1288. // {
  1289. // if (horizontalOffset > DataGridControl.ScrollViewer.ScrollableWidth)
  1290. // horizontalOffset = DataGridControl.ScrollViewer.ScrollableWidth;
  1291. // if (horizontalOffset < 0)
  1292. // horizontalOffset = 0;
  1293. // DataGridControl.ScrollViewer.ScrollToHorizontalOffset(horizontalOffset);
  1294. // }
  1295. // }));
  1296. // });
  1297. //}
  1298. }
  1299. #endregion if running state, highlight current running step, move horizontal bar to current running step
  1300. //calc recipe time
  1301. CalcRecipeTime();
  1302. //invoke property
  1303. InvokePropertyChanged("Errors");
  1304. }
  1305. catch (Exception ex)
  1306. {
  1307. MessageBox.Show("工艺程序校验出错!\r\n\r\n" + ex.Message, "出错", MessageBoxButton.OK, MessageBoxImage.Error);
  1308. System.Diagnostics.Debug.WriteLine(ex.Message);
  1309. }
  1310. }
  1311. /// <summary>
  1312. /// reload datagrid content
  1313. /// </summary>
  1314. private void RefreshDataGrid()
  1315. {
  1316. //try
  1317. //{
  1318. //generate columns in Grid
  1319. DataGridControl.CurrentColumn = null;
  1320. if (DataGridControl.Columns.Count > 0)
  1321. DataGridControl.Columns.Clear();
  1322. var template = (DataTemplate)DataGridControl.FindResource("CustomTemplate");
  1323. var rowTemplate = (DataTemplate)DataGridControl.FindResource("RowHeadTemplate");
  1324. //DataGridControl.Columns.Add(new Xceed.Wpf.DataGrid.Column()
  1325. //{
  1326. // Width = 140,
  1327. // Title = " ",
  1328. // FieldName = ".",
  1329. // CellContentTemplate = rowTemplate
  1330. //});
  1331. // var cellEditor = DataGridControl.DefaultCellEditors[typeof(SmartCellData)];// DefaultCellEditorSelector.SelectCellEditor(typeof(SmartCellData));
  1332. // for (int index = 0; index < RecipeRows[0].RecipeItems.Count; index++)
  1333. // {
  1334. // //var col = new Xceed.Wpf.DataGrid.Column();
  1335. // DataGridControl.Columns.Add(new Xceed.Wpf.DataGrid.Column()
  1336. // {
  1337. // Title = string.Format("【{0}】\r\n{1}", index + 1, RecipeRows[0].RecipeItems[index].Value),
  1338. // FieldName = string.Format("RecipeItems[{0}]", index),
  1339. // CellContentTemplate = template,
  1340. // AllowSort = false,
  1341. // Width = 120,
  1342. // MaxWidth = 120,
  1343. // CellEditor = cellEditor
  1344. // });
  1345. // }
  1346. // InvokePropertyChanged("RecipeRows");
  1347. // InvokePropertyChanged("RecipeHead");
  1348. //}
  1349. //catch (Exception ex)
  1350. //{
  1351. // System.Diagnostics.Debug.WriteLine(ex.Message);
  1352. //}
  1353. }
  1354. /// <summary>
  1355. /// calc recipe total time
  1356. /// </summary>
  1357. private void CalcRecipeTime()
  1358. {
  1359. int timeStepRowId = -1;
  1360. int loopStepRowId = -1;
  1361. for (int i = 0; i < RecipeRows.Count; i++)
  1362. {
  1363. if (RecipeRows[i].TechnicalName == "Time")
  1364. timeStepRowId = i;
  1365. if (RecipeRows[i].TechnicalName == "Loop")
  1366. loopStepRowId = i;
  1367. if (loopStepRowId != -1 && timeStepRowId != -1)
  1368. break;
  1369. }
  1370. TimeSpan tspan = new TimeSpan();
  1371. for (int stepNo = 0; stepNo < RecipeRows[timeStepRowId].RecipeItems.Count; stepNo++)
  1372. {
  1373. string loopStr = RecipeRows[loopStepRowId].RecipeItems[stepNo].Value;
  1374. bool isLoopStart = Regex.IsMatch(loopStr, @"^Loop\x20\d+$");
  1375. if (isLoopStart)
  1376. {
  1377. int loopNum = int.Parse(loopStr.ToLower().Replace("loop", "").Replace(" ", ""));
  1378. TimeSpan ts = new TimeSpan();
  1379. for (int innerStepNo = stepNo; innerStepNo < RecipeRows[timeStepRowId].RecipeItems.Count; innerStepNo++)
  1380. {
  1381. loopStr = RecipeRows[loopStepRowId].RecipeItems[innerStepNo].Value;
  1382. stepNo = innerStepNo;
  1383. string timeDuration = RecipeRows[timeStepRowId].RecipeItems[innerStepNo].Value;
  1384. string[] timeArr = timeDuration.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  1385. if (timeArr.Length == 3)
  1386. {
  1387. int h, mi, s;
  1388. if (int.TryParse(timeArr[0], out h) && int.TryParse(timeArr[1], out mi) && int.TryParse(timeArr[2], out s))
  1389. {
  1390. var tt = new TimeSpan(h, mi, s);
  1391. ts += tt;
  1392. }
  1393. }
  1394. bool isLoopEnd = Regex.IsMatch(loopStr, @"^Loop End$");
  1395. if (isLoopEnd)
  1396. {
  1397. tspan += new TimeSpan(ts.Ticks * loopNum);
  1398. break;
  1399. }
  1400. }
  1401. }
  1402. else
  1403. {
  1404. string timeDuration = RecipeRows[timeStepRowId].RecipeItems[stepNo].Value;
  1405. string[] timeArr = timeDuration.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  1406. if (timeArr.Length == 3)
  1407. {
  1408. int h, mi, s;
  1409. if (int.TryParse(timeArr[0], out h) && int.TryParse(timeArr[1], out mi) && int.TryParse(timeArr[2], out s))
  1410. {
  1411. var ts = new TimeSpan(h, mi, s);
  1412. tspan += ts;
  1413. }
  1414. }
  1415. }
  1416. }
  1417. RecipeInfo = string.Format("共{0}步,总时间{1}:{2}:{3}", RecipeRows[0].RecipeItems.Count, (int)tspan.TotalHours, tspan.Minutes.ToString("00"), tspan.Seconds.ToString("00"));
  1418. InvokePropertyChanged("RecipeInfo");
  1419. }
  1420. #region INotifyPropertyChanged
  1421. public event PropertyChangedEventHandler PropertyChanged;
  1422. public void InvokePropertyChanged(string propertyName)
  1423. {
  1424. if (PropertyChanged != null)
  1425. {
  1426. PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
  1427. }
  1428. }
  1429. #endregion INotifyPropertyChanged
  1430. }
  1431. public class RecipeRow
  1432. {
  1433. private ObservableCollection<SmartCellData> _recipeItems = new ObservableCollection<SmartCellData>();
  1434. public RecipeRow(params SmartCellData[] vars)
  1435. {
  1436. foreach (var var in vars)
  1437. _recipeItems.Add(var);
  1438. }
  1439. public string CatalogName { get; set; }
  1440. public string FriendlyName { get; set; }
  1441. public string TechnicalName { get; set; }
  1442. public ObservableCollection<SmartCellData> RecipeItems
  1443. {
  1444. get { return _recipeItems; }
  1445. set { _recipeItems = value; }
  1446. }
  1447. }
  1448. /// <summary>
  1449. /// Recipe head
  1450. /// </summary>
  1451. public class RecipeHead
  1452. {
  1453. public string RecipeVariation { get; set; }
  1454. public string CreationTime { get; set; }
  1455. public string LastRevisionTime { get; set; }
  1456. public string CreatedBy { get; set; }
  1457. public string LastModifiedBy { get; set; }
  1458. public string PressureMode { get; set; }
  1459. public string Description { get; set; }
  1460. public string BasePressure
  1461. {
  1462. get; set;
  1463. }
  1464. public string PumpDownLimit
  1465. {
  1466. get; set;
  1467. }
  1468. public string PurgeActive
  1469. {
  1470. get; set;
  1471. }
  1472. public string NotToPurgeOrVent
  1473. {
  1474. get; set;
  1475. }
  1476. public string Barcode
  1477. {
  1478. get; set;
  1479. }
  1480. public string SubstrateTemp
  1481. {
  1482. get; set;
  1483. }
  1484. public string PumpingPinState
  1485. {
  1486. get; set;
  1487. }
  1488. public string VentingPinState
  1489. {
  1490. get; set;
  1491. }
  1492. public string PinDownPressure
  1493. {
  1494. get; set;
  1495. }
  1496. }
  1497. public class EndPointConfigItem : INotifyPropertyChanged
  1498. {
  1499. public event PropertyChangedEventHandler PropertyChanged;
  1500. public void InvokePropertyChanged(string propertyName)
  1501. {
  1502. if (PropertyChanged != null)
  1503. {
  1504. PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
  1505. }
  1506. }
  1507. public string ExposureTime { get; set; }
  1508. public string WaveLengthA { get; set; }
  1509. public string BinningA { get; set; }
  1510. public string WaveLengthB { get; set; }
  1511. public string BinningB { get; set; }
  1512. public string WaveLengthC { get; set; }
  1513. public string BinningC { get; set; }
  1514. public string WaveLengthD { get; set; }
  1515. public string BinningD { get; set; }
  1516. public string Fd { get; set; }
  1517. public string PrefilterTime { get; set; }
  1518. public string PostfilterTime { get; set; }
  1519. public string AlgorithmType { get; set; }
  1520. public string Criteria { get; set; }
  1521. public string DelayTime { get; set; }
  1522. public string ValidationTime { get; set; }
  1523. public string ValidationValue { get; set; }
  1524. public string TimeWindow { get; set; }
  1525. public string MinimalTime { get; set; }
  1526. public string PostponeTime { get; set; }
  1527. public bool Control { get; set; }
  1528. public bool Normalization { get; set; }
  1529. public bool EnablePostponePercent { get; set; }
  1530. public bool EnableCriterialPercent { get; set; }
  1531. public bool EnableEventTrigger { get; set; }
  1532. public bool IsFaultIfNoTrigger { get; set; }
  1533. public string ToValue()
  1534. {
  1535. return
  1536. $@"ExposureTime={ExposureTime};WaveLengthA={WaveLengthA};BinningA={BinningA};WaveLengthB={WaveLengthB};" +
  1537. $@"BinningB={BinningB};WaveLengthC={WaveLengthC};BinningC={BinningC};WaveLengthD={WaveLengthD};BinningD={BinningD};Fd={Fd};" +
  1538. $@"PrefilterTime={PrefilterTime};PostfilterTime={PostfilterTime};AlgorithmType={AlgorithmType};Criteria={Criteria};DelayTime={DelayTime};ValidationTime={ValidationTime};" +
  1539. $@"ValidationValue={ValidationValue};TimeWindow={TimeWindow};MinimalTime={MinimalTime};PostponeTime={PostponeTime};Control={Control};Normalization={Normalization};" +
  1540. $@"EnablePostponePercent={EnablePostponePercent};EnableCriterialPercent={EnableCriterialPercent};EnableEventTrigger={EnableEventTrigger};IsFaultIfNoTrigger={IsFaultIfNoTrigger};"
  1541. ;
  1542. }
  1543. public void SetValue(string config)
  1544. {
  1545. if (string.IsNullOrEmpty(config))
  1546. return;
  1547. string[] items = config.Split(';');
  1548. foreach (var item in items)
  1549. {
  1550. if (string.IsNullOrEmpty(item))
  1551. continue;
  1552. string[] pairs = item.Split('=');
  1553. if (pairs.Length != 2)
  1554. continue;
  1555. Parallel.ForEach(this.GetType().GetProperties(),
  1556. property =>
  1557. {
  1558. PropertyInfo pi = (PropertyInfo) property;
  1559. if (pi.Name == pairs[0])
  1560. {
  1561. try
  1562. {
  1563. var convertedValue = Convert.ChangeType(pairs[1], pi.PropertyType);
  1564. var originValue = Convert.ChangeType(pi.GetValue(this, null), pi.PropertyType);
  1565. if (originValue != convertedValue)
  1566. {
  1567. pi.SetValue(this, convertedValue, null);
  1568. }
  1569. }
  1570. catch (Exception)
  1571. {
  1572. }
  1573. }
  1574. });
  1575. }
  1576. }
  1577. }
  1578. }