RecipeEditorControlViewModel.cs 111 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376
  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. public List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>> UndoList { get; set; }
  27. public List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>> RedoList { get; set; }
  28. public bool IsUndoEnabled { get { return UndoList != null && UndoList.Count > 0; } }
  29. public bool IsRedoEnabled { get { return RedoList != null && RedoList.Count > 0; } }
  30. public ObservableCollection<RecipeRow> RecipeRows { get; set; }
  31. private ObservableCollection<RecipeRow> _previousRecipeRows { get; set; }
  32. private string _valueBeforeEditing { get; set; }
  33. private string _currentRecipeVariationName = string.Empty;
  34. private SmartCellData _currentEditingCellData { get; set; }
  35. public List<Tuple<int/*row no*/, int/*col no*/, string/*var name*/, string/*reason*/>> Errors { get; set; }
  36. public List<Tuple<string, string>> CreateRecipeList { get; set; }
  37. public List<Tuple<string, string>> OpenRecipeList { get; set; }
  38. public DataGridControl DataGridControl { get; set; }
  39. public int CurrentRunningStepNo { get; set; }
  40. public Visibility SingleAppElementVisibility { get; set; }
  41. public Visibility RecipeInfoTextVisibility { get; set; }
  42. public ICommand ShowDetailedErrInfoCommand { get; set; }
  43. public ICommand EditRecipeInfoCommand { get; set; }
  44. //public ICommand CellContentChangedCommand { get; set; }
  45. public ICommand RightClickCommand { get; set; }
  46. public ICommand OpenLocalRecipeCommand { get; set; }
  47. public ICommand ExpandGroupCommand { get; set; }
  48. public ICommand CollapseGroupCommand { get; set; }
  49. public ICommand SaveRecipeCommand { get; set; }
  50. public ICommand RecipeHelpDocCommand { get; set; }
  51. public ICommand RecipeExport2ExcelCommand { get; set; }
  52. public ICommand ToggleHideSameCommand { get; set; }
  53. public ICommand UndoCommand { get; set; }
  54. public ICommand RedoCommand { get; set; }
  55. public ICommand SmartCellEditorLoadedCommand { get; set; }
  56. public ICommand SmartCellEditorUnloadedCommand { get; set; }
  57. public RecipeHead RecipeHead { get; set; }
  58. public bool IsBusy { get; set; }
  59. public bool IsHideSameContent { get; set; }
  60. public string RecipeInfo { get; set; }
  61. public HashSet<string> MaskedTechNames { get; set; }
  62. public HashSet<string> MaskedCatalogNames { get; set; }
  63. public event EventHandler OnSaveRecipeFile;
  64. public event EventHandler OnLocalRecipeOpened;
  65. public event EventHandler OnLoadRecipeContent;
  66. public bool IsRecipeModified { get; set; }
  67. public string UserName { set; get; }
  68. //private List<Tuple<string, string, string>> SourceDilteInjectRestrictions { get; set; }
  69. private Dictionary<string, string> _preDefinedRecipeVars { get; set; }
  70. private List<Tuple<string/*varName*/, string/*check condition*/, string/*message*/>> _validationRules { get; set; }
  71. private List<string> _checkVariables { get; set; }
  72. private Dictionary<string, int> RowVarNameDic { get; set; }
  73. private Dictionary<int, List<SmartCellData>> _copiedColumnDatas = new Dictionary<int, List<SmartCellData>>();
  74. private Dictionary<string/*CatalogName*/, Dictionary<string/*GroupName*/, List<RecipeVariableDefine/*StepList*/>>> _recipeReadingFormat;
  75. private Dictionary<string/*ModuleName*/, List<string>/*each item's control name*/> _recipeSavingFormat;
  76. private string _currentRecipeFormatContent;
  77. public bool IsBarcodeEnabled
  78. {
  79. get; set;
  80. }
  81. public Visibility IsBarcodeVisibility
  82. {
  83. get
  84. {
  85. return IsBarcodeEnabled ? Visibility.Visible : Visibility.Hidden;
  86. }
  87. }
  88. private string _defaultEndPointValue { get; set; }
  89. /// <summary>
  90. /// class construction
  91. /// </summary>
  92. public RecipeEditorControlViewModel()
  93. {
  94. UndoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>();
  95. RedoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>();
  96. //if(SingleAppElementVisibility
  97. CreateRecipeList = new List<Tuple<string, string>>();
  98. OpenRecipeList = new List<Tuple<string, string>>();
  99. foreach (var item in GetDefinedRecipeVariations())
  100. {
  101. CreateRecipeList.Add(new Tuple<string, string>("配置:" + item, item));
  102. OpenRecipeList.Add(new Tuple<string, string>("转换为配置:" + item, item));
  103. }
  104. RecipeInfoTextVisibility = Visibility.Collapsed;
  105. SingleAppElementVisibility = Visibility.Collapsed;
  106. RightClickCommand = new DelegatedCommand((o) => true, (o) => RightClickAction());
  107. ExpandGroupCommand = new DelegatedCommand((o) => true, (o) => ExpandGroups());
  108. CollapseGroupCommand = new DelegatedCommand((o) => true, (o) => CollapseGroups());
  109. SaveRecipeCommand = new DelegatedCommand((o) => true, (o) => SaveRecipeFile());
  110. OpenLocalRecipeCommand = new DelegatedCommand((o) => true, (o) => OpenLocalRecipe());
  111. ShowDetailedErrInfoCommand = new DelegatedCommand((o) => true, (o) => ShowDetailedErrInformation());
  112. EditRecipeInfoCommand = new DelegatedCommand((o) => true, (o) => EditRecipeInformation());
  113. RecipeHelpDocCommand = new DelegatedCommand((o) => true, (o) => ShowHelpDocView());
  114. RecipeExport2ExcelCommand = new DelegatedCommand((o) => true, (o) => Export2Excel());
  115. ToggleHideSameCommand = new DelegatedCommand((o) => true, (o) => ToggleHideSameContent());
  116. UndoCommand = new DelegatedCommand((o) => true, (o) => UndoOperation(o));
  117. RedoCommand = new DelegatedCommand((o) => true, (o) => RedoOperation(o));
  118. SmartCellEditorLoadedCommand = new DelegatedCommand((o) => true, (o) => SmartCellEditorLoaded(o));
  119. SmartCellEditorUnloadedCommand = new DelegatedCommand((o) => true, (o) => SmartCellEditorUnloaded(o));
  120. }
  121. /// <summary>
  122. /// When smart cell editor loaded
  123. /// </summary>
  124. /// <param name="obj"></param>
  125. private void SmartCellEditorLoaded(object obj)
  126. {
  127. _currentEditingCellData = obj as SmartCellData;
  128. if (_currentEditingCellData == null) return;
  129. _valueBeforeEditing = _currentEditingCellData.Value;
  130. _previousRecipeRows = CloneRecipeRowData(RecipeRows);
  131. }
  132. /// <summary>
  133. /// make a clone of current recipe row data
  134. /// </summary>
  135. /// <returns></returns>
  136. private ObservableCollection<RecipeRow> CloneRecipeRowData(ObservableCollection<RecipeRow> oldData)
  137. {
  138. ObservableCollection<RecipeRow> newRecipeRows = new ObservableCollection<RecipeRow>();
  139. foreach (var item in oldData)
  140. {
  141. var newRecipeRow = new RecipeRow() { CatalogName = item.CatalogName, FriendlyName = item.FriendlyName, TechnicalName = item.TechnicalName, RecipeItems = new ObservableCollection<SmartCellData>() };
  142. newRecipeRows.Add(newRecipeRow);
  143. foreach (var item2 in item.RecipeItems)
  144. {
  145. var newRecipeItem = new SmartCellData() { Background = item2.Background, ErrInfo = item2.ErrInfo, FontWeight = item2.FontWeight, Foreground = item2.Foreground, IsHidden = item2.IsHidden, IsMasked = item2.IsMasked, IsRunning = item2.IsRunning, RecipeVariableDefine = item2.RecipeVariableDefine, Value = item2.Value };
  146. newRecipeRow.RecipeItems.Add(newRecipeItem);
  147. }
  148. }
  149. return newRecipeRows;
  150. }
  151. /// <summary>
  152. /// When smart cell editor unloaded
  153. /// </summary>
  154. /// <param name="obj"></param>
  155. private void SmartCellEditorUnloaded(object obj)
  156. {
  157. if (_currentEditingCellData != null && _currentEditingCellData.Value != _valueBeforeEditing)
  158. {
  159. IsRecipeModified = true;
  160. var ret = OverrideSelectedCellsData();
  161. if (ret < 2)
  162. AddUndoHistory(string.Format("第{0}步({1})",
  163. _currentEditingCellData.ColIndex + 1,
  164. _currentEditingCellData.RecipeVariableDefine.CatalogName + _currentEditingCellData.RecipeVariableDefine.FriendlyName), _previousRecipeRows);
  165. else
  166. AddUndoHistory(string.Format("第{0}步({1})等{2}个单元格数据",
  167. _currentEditingCellData.ColIndex + 1,
  168. _currentEditingCellData.RecipeVariableDefine.CatalogName + _currentEditingCellData.RecipeVariableDefine.FriendlyName, ret), _previousRecipeRows);
  169. }
  170. RefreshCellsDisplay(false);
  171. }
  172. /// <summary>
  173. /// Adding undo history
  174. /// </summary>
  175. /// <param name="description"></param>
  176. /// <param name="recipeRows"></param>
  177. private void AddUndoHistory(string description, ObservableCollection<RecipeRow> recipeRows)
  178. {
  179. System.Diagnostics.Debug.WriteLine(description);
  180. if (recipeRows == null)
  181. return;
  182. string shortDesc = "";
  183. if (description.Length > 50)
  184. {
  185. shortDesc = description.Substring(0, 50);
  186. shortDesc += "...";
  187. }
  188. else
  189. {
  190. shortDesc = description;
  191. }
  192. UndoList.Insert(0, new Tuple<string, string, ObservableCollection<RecipeRow>, Guid>(shortDesc, description, recipeRows, Guid.NewGuid()));
  193. UndoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>(UndoList.ToList());
  194. RedoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>();
  195. InvokePropertyChanged("UndoList");
  196. InvokePropertyChanged("RedoList");
  197. InvokePropertyChanged("IsUndoEnabled");
  198. InvokePropertyChanged("IsRedoEnabled");
  199. }
  200. /// <summary>
  201. /// Redo something here
  202. /// </summary>
  203. private void RedoOperation(object obj)
  204. {
  205. try
  206. {
  207. if (RedoList == null || RedoList.Count == 0)
  208. return;
  209. Guid redoId = Guid.Empty;
  210. if (obj == null)
  211. redoId = RedoList[0].Item4;
  212. else
  213. redoId = (Guid)obj;
  214. var itemIndex = RedoList.FindIndex((o) => o.Item4 == redoId);
  215. if (itemIndex < 0)
  216. return;
  217. UndoList.Reverse();
  218. for (int i = 0; i <= itemIndex; i++)
  219. {
  220. if (i == 0)
  221. UndoList.Add(new Tuple<string, string, ObservableCollection<RecipeRow>, Guid>(RedoList[i].Item1, RedoList[i].Item2, CloneRecipeRowData(RecipeRows), RedoList[i].Item4));
  222. else
  223. UndoList.Add(new Tuple<string, string, ObservableCollection<RecipeRow>, Guid>(RedoList[i].Item1, RedoList[i].Item2, RedoList[i - 1].Item3, RedoList[i].Item4));
  224. }
  225. UndoList.Reverse();
  226. UndoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>(UndoList.ToList());
  227. RecipeRows = RedoList[itemIndex].Item3;
  228. RedoList.RemoveRange(0, itemIndex + 1);
  229. RedoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>(RedoList.ToList());
  230. RefreshDataGrid();
  231. RefreshCellsDisplay(false);
  232. InvokePropertyChanged("UndoList");
  233. InvokePropertyChanged("RedoList");
  234. InvokePropertyChanged("IsUndoEnabled");
  235. InvokePropertyChanged("IsRedoEnabled");
  236. }
  237. catch (Exception ex)
  238. {
  239. System.Diagnostics.Debug.WriteLine(ex.Message);
  240. MessageBox.Show("恢复动作失败!\r\n\r\n" + ex.Message, "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  241. }
  242. }
  243. /// <summary>
  244. /// Undo something here
  245. /// </summary>
  246. private void UndoOperation(object obj)
  247. {
  248. try
  249. {
  250. if (UndoList == null || UndoList.Count == 0)
  251. return;
  252. Guid undoId = Guid.Empty;
  253. if (obj == null)
  254. undoId = UndoList[0].Item4;
  255. else
  256. undoId = (Guid)obj;
  257. var itemIndex = UndoList.FindIndex((o) => o.Item4 == undoId);
  258. if (itemIndex < 0)
  259. return;
  260. RedoList.Reverse();
  261. for (int i = 0; i <= itemIndex; i++)
  262. {
  263. if (i == 0)
  264. RedoList.Add(new Tuple<string, string, ObservableCollection<RecipeRow>, Guid>(UndoList[i].Item1, UndoList[i].Item2, CloneRecipeRowData(RecipeRows), UndoList[i].Item4));
  265. else
  266. RedoList.Add(new Tuple<string, string, ObservableCollection<RecipeRow>, Guid>(UndoList[i].Item1, UndoList[i].Item2, UndoList[i - 1].Item3, UndoList[i].Item4));
  267. }
  268. RedoList.Reverse();
  269. RedoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>(RedoList.ToList());
  270. RecipeRows = UndoList[itemIndex].Item3;
  271. UndoList.RemoveRange(0, itemIndex + 1);
  272. UndoList = new List<Tuple<string, string, ObservableCollection<RecipeRow>, Guid>>(UndoList.ToList());
  273. RefreshDataGrid();
  274. RefreshCellsDisplay(false);
  275. InvokePropertyChanged("UndoList");
  276. InvokePropertyChanged("RedoList");
  277. InvokePropertyChanged("IsUndoEnabled");
  278. InvokePropertyChanged("IsRedoEnabled");
  279. }
  280. catch (Exception ex)
  281. {
  282. System.Diagnostics.Debug.WriteLine(ex.Message);
  283. MessageBox.Show("撤销动作失败!\r\n\r\n" + ex.Message, "警告", MessageBoxButton.OK, MessageBoxImage.Warning);
  284. }
  285. }
  286. /// <summary>
  287. /// hide or show same content before and after one step
  288. /// </summary>
  289. private void ToggleHideSameContent()
  290. {
  291. IsHideSameContent = !IsHideSameContent;
  292. RefreshCellsDisplay(false);
  293. }
  294. /// <summary>
  295. /// get recipe variations
  296. /// </summary>
  297. /// <returns></returns>
  298. public List<string> GetDefinedRecipeVariations()
  299. {
  300. var list1 = new List<string>();
  301. var dir = new System.IO.FileInfo(Process.GetCurrentProcess().MainModule.FileName).Directory;
  302. string cfgPath = dir + "\\Config\\";
  303. var di = new System.IO.DirectoryInfo(cfgPath);
  304. if (di.Exists)
  305. {
  306. foreach (var item in di.GetFiles("*.xml"))
  307. {
  308. list1.Add(item.Name.Substring(0, item.Name.Length - item.Extension.Length));
  309. }
  310. }
  311. return list1;
  312. }
  313. /// <summary>
  314. /// Export to excel
  315. /// </summary>
  316. private void Export2Excel()
  317. {
  318. try
  319. {
  320. if (RecipeRows == null) return;
  321. var dlg = new SaveFileDialog();
  322. dlg.DefaultExt = ".xls";
  323. dlg.Filter = "Excel文件 (.xls)|*.xls|所有文件 (*.*)|*.*";
  324. if (dlg.ShowDialog() == true)
  325. {
  326. if (File.Exists(dlg.FileName))
  327. File.Delete(dlg.FileName);
  328. Workbook workbook = new Workbook();
  329. Worksheet worksheet = new Worksheet("First Sheet");
  330. XmlDocument doc = new XmlDocument();
  331. doc.LoadXml(_currentRecipeFormatContent);
  332. var catalogNodes = doc.SelectNodes("TableRecipeFormat/Catalog");
  333. int groupRowIndex = 0;
  334. int stepRowIndex = 0;
  335. int catalogRowIndex = 0;
  336. foreach (XmlElement cNode in catalogNodes)
  337. {
  338. XmlNodeList sNodes = cNode.SelectNodes("Group/Step");
  339. string catalogHeader = cNode.Attributes["DisplayName"].Value;
  340. worksheet.Cells[catalogRowIndex, 0] = new ExcelLibrary.SpreadSheet.Cell(catalogHeader);
  341. catalogRowIndex += sNodes.Count;
  342. XmlNodeList gNodes = cNode.SelectNodes("Group");
  343. foreach (XmlElement gNode in gNodes)
  344. {
  345. XmlNodeList stepNodes = gNode.SelectNodes("Step");
  346. string groupHeader = gNode.Attributes["DisplayName"].Value;
  347. worksheet.Cells[groupRowIndex, 1] = new ExcelLibrary.SpreadSheet.Cell(groupHeader);
  348. groupRowIndex += stepNodes.Count;
  349. foreach (XmlElement nd in stepNodes)
  350. {
  351. string stepHeader = nd.Attributes["DisplayName"].Value;
  352. worksheet.Cells[stepRowIndex, 2] = new ExcelLibrary.SpreadSheet.Cell(stepHeader);
  353. stepRowIndex++;
  354. }
  355. }
  356. }
  357. string recipeContent = GetRecipeContentString();
  358. XmlDocument rcp = new XmlDocument();
  359. rcp.LoadXml(recipeContent);
  360. XmlNodeList stepNodeList = rcp.SelectNodes("/TableRecipeData/Step");
  361. for (int stepNo = 0; stepNo < stepNodeList.Count; stepNo++)
  362. {
  363. var dataDic = new Dictionary<string, string>();
  364. foreach (XmlAttribute att in (stepNodeList[stepNo] as XmlElement).Attributes)
  365. {
  366. dataDic.Add(att.Name, att.Value);
  367. }
  368. //fill sub node's attributes
  369. foreach (XmlElement subStep in stepNodeList[stepNo].ChildNodes)
  370. {
  371. foreach (XmlAttribute att in subStep.Attributes)
  372. {
  373. dataDic.Add(att.Name, att.Value);
  374. }
  375. foreach (XmlElement subsubStep in subStep.ChildNodes)
  376. {
  377. foreach (XmlAttribute att2 in subsubStep.Attributes)
  378. {
  379. dataDic.Add(att2.Name, att2.Value);
  380. }
  381. }
  382. }
  383. long length = dataDic.LongCount();
  384. int step = 0;
  385. foreach (string key in dataDic.Keys)
  386. {
  387. worksheet.Cells.ColumnWidth[(ushort)step] = 4000;
  388. var cellContent = dataDic[key];
  389. double v;
  390. if (double.TryParse(cellContent, out v))
  391. {
  392. worksheet.Cells[step, stepNo + 3] = new ExcelLibrary.SpreadSheet.Cell(v);
  393. }
  394. else
  395. {
  396. worksheet.Cells[step, stepNo + 3] = new ExcelLibrary.SpreadSheet.Cell(cellContent);
  397. }
  398. step++;
  399. }
  400. }
  401. workbook.Worksheets.Add(worksheet);
  402. workbook.Save(dlg.FileName);
  403. MessageBox.Show(string.Format("成功导出到Excel文件!\r\n\r\n{0}", dlg.FileName), "导出", MessageBoxButton.OK, MessageBoxImage.Information);
  404. }
  405. }
  406. catch (Exception ex)
  407. {
  408. System.Diagnostics.Debug.WriteLine(ex.Message);
  409. MessageBox.Show("导出Excel文件发生异常!\r\n\r\n" + ex.Message, "导出", MessageBoxButton.OK, MessageBoxImage.Error);
  410. }
  411. }
  412. /// <summary>
  413. /// Show recipe information
  414. /// </summary>
  415. private void ShowHelpDocView()
  416. {
  417. var view = RecipeHelpView.Instance;
  418. view.Owner = Application.Current.MainWindow;
  419. view.DataContext = this;
  420. if (view.Visibility == Visibility.Visible)
  421. view.Hide();
  422. else
  423. view.Show();
  424. }
  425. /// <summary>
  426. /// Edit recipe information
  427. /// </summary>
  428. private void EditRecipeInformation()
  429. {
  430. RecipeInfoEditor editor = new RecipeInfoEditor() { RecipeHead = this.RecipeHead, Owner = Application.Current.MainWindow };
  431. editor.ShowDialog();
  432. InvokePropertyChanged("RecipeHead");
  433. }
  434. public void EnableBarcode(bool enable)
  435. {
  436. IsBarcodeEnabled = enable;
  437. InvokePropertyChanged("IsBarcodeVisibility");
  438. }
  439. public void SetCurrentUser(string user)
  440. {
  441. UserName = user;
  442. InvokePropertyChanged("UserName");
  443. }
  444. public void SetEndPointDefaultValue(string defaultValue)
  445. {
  446. _defaultEndPointValue = defaultValue;
  447. }
  448. /// <summary>
  449. /// Show recipe information
  450. /// </summary>
  451. private void ShowDetailedErrInformation()
  452. {
  453. var view = ErrorInformationDetailsView.Instance;
  454. view.Owner = Application.Current.MainWindow;
  455. view.DataContext = this;
  456. if (view.Visibility == Visibility.Visible)
  457. view.Hide();
  458. else
  459. view.ShowDialog();
  460. }
  461. /// <summary>
  462. /// Update selected cells data
  463. /// </summary>
  464. /// <returns>overrided cells number</returns>
  465. private int OverrideSelectedCellsData()
  466. {
  467. int overridedCellsNum = 0;
  468. if (_currentEditingCellData != null)
  469. {
  470. var finalCellData = _currentEditingCellData;
  471. bool containsEditingCell = false;
  472. foreach (var item in DataGridControl.SelectedCellRanges)
  473. {
  474. int startColIndex = Math.Min(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  475. int endColIndex = Math.Max(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  476. int startRowIndex = Math.Min(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  477. int endRowIndex = Math.Max(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  478. if (startColIndex > 0 && startColIndex <= RecipeRows[0].RecipeItems.Count &&
  479. endColIndex > 0 && endColIndex <= RecipeRows[0].RecipeItems.Count &&
  480. startRowIndex >= 0 && startRowIndex < RecipeRows.Count &&
  481. endRowIndex >= 0 && endRowIndex < RecipeRows.Count)
  482. {
  483. for (int m = startRowIndex; m <= endRowIndex; m++)
  484. {
  485. for (int n = startColIndex; n <= endColIndex; n++)
  486. {
  487. int rowIndex = m;
  488. int colIndex = n - 1;
  489. if (RecipeRows[rowIndex].RecipeItems[colIndex] == _currentEditingCellData)
  490. {
  491. containsEditingCell = true;
  492. break;
  493. }
  494. }
  495. }
  496. }
  497. }
  498. if (containsEditingCell)
  499. {
  500. foreach (var item in DataGridControl.SelectedCellRanges)
  501. {
  502. int startColIndex = Math.Min(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  503. int endColIndex = Math.Max(item.ColumnRange.StartIndex, item.ColumnRange.EndIndex);
  504. int startRowIndex = Math.Min(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  505. int endRowIndex = Math.Max(item.ItemRange.StartIndex, item.ItemRange.EndIndex);
  506. if (startColIndex > 0 && startColIndex <= RecipeRows[0].RecipeItems.Count &&
  507. endColIndex > 0 && endColIndex <= RecipeRows[0].RecipeItems.Count &&
  508. startRowIndex >= 0 && startRowIndex < RecipeRows.Count &&
  509. endRowIndex >= 0 && endRowIndex < RecipeRows.Count)
  510. {
  511. for (int m = startRowIndex; m <= endRowIndex; m++)
  512. {
  513. for (int n = startColIndex; n <= endColIndex; n++)
  514. {
  515. int rowIndex = m;
  516. int colIndex = n - 1;
  517. if (RecipeRows[rowIndex].RecipeItems[colIndex].RecipeVariableDefine.CellType == finalCellData.RecipeVariableDefine.CellType)
  518. {
  519. overridedCellsNum++;
  520. RecipeRows[rowIndex].RecipeItems[colIndex].Value = finalCellData.Value;
  521. RecipeRows[rowIndex].RecipeItems[colIndex].InvokePropertyChanged();
  522. }
  523. }
  524. }
  525. }
  526. }
  527. }
  528. }
  529. return overridedCellsNum;
  530. }
  531. /// <summary>
  532. /// Open local recipe operation
  533. /// </summary>
  534. /// <param name="recipeDefineFilePath"></param>
  535. public void OpenLocalRecipe(string recipeVariationName = "")
  536. {
  537. var dlg = new OpenFileDialog();
  538. dlg.DefaultExt = ".rcp";
  539. dlg.Filter = "Recipe File (.rcp)|*.rcp|All (*.*)|*.*";
  540. if (dlg.ShowDialog() == true)
  541. {
  542. try
  543. {
  544. XmlDocument rcpDoc = new XmlDocument();
  545. rcpDoc.Load(dlg.FileName);
  546. string recipeVariation = recipeVariationName;
  547. if (string.IsNullOrEmpty(recipeVariation))
  548. {
  549. var root = rcpDoc.SelectSingleNode("/TableRecipeData") as XmlElement;
  550. recipeVariation = root.Attributes["RecipeVersion"].Value;
  551. }
  552. var startupPath = System.Diagnostics.Process.GetCurrentProcess().MainModule.FileName;
  553. string dir = System.IO.Path.GetDirectoryName(startupPath);
  554. List<Aitex.Controls.RecipeCompare.Item> map = CustomXmlSerializer.Deserialize<List<Aitex.Controls.RecipeCompare.Item>>(new System.IO.FileInfo(System.IO.Path.Combine(dir, "map.xml")));
  555. Func<Aitex.Controls.RecipeCompare.Item, bool> predicate = item => item.Name.Equals(recipeVariation);
  556. System.IO.FileInfo fi = new System.IO.FileInfo(string.Format("{0}\\config\\{1}.xml", dir, map.Any(predicate) ? map.Single(predicate).No : recipeVariation));
  557. if (fi.Exists)
  558. {
  559. XmlDocument doc = new XmlDocument();
  560. doc.Load(fi.FullName);
  561. string formatXml = doc.SelectSingleNode("/Aitex/TableRecipeFormat").OuterXml;
  562. string recipeXml = rcpDoc.SelectSingleNode("/TableRecipeData").OuterXml;
  563. LoadRecipe(formatXml, recipeXml);
  564. if (OnLocalRecipeOpened != null)
  565. OnLocalRecipeOpened.Invoke(new Tuple<string, string>(recipeVariation, dlg.FileName), null);
  566. }
  567. else
  568. {
  569. MessageBox.Show(string.Format("工艺程序版本{0}的描述文件不存在,无法正确识别该版本的工艺程序文件。", recipeVariation), "工艺程序打开失败",
  570. MessageBoxButton.OK, MessageBoxImage.Error);
  571. }
  572. }
  573. catch (Exception ex)
  574. {
  575. System.Diagnostics.Debug.WriteLine(ex.Message);
  576. 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",
  577. MessageBoxButton.OK, MessageBoxImage.Error);
  578. }
  579. }
  580. }
  581. /// <summary>
  582. /// Save recipe file
  583. /// </summary>
  584. private void SaveRecipeFile()
  585. {
  586. try
  587. {
  588. if (Errors != null && Errors.Count > 0)
  589. {
  590. var ret = MessageBox.Show(string.Format("Recipe have {0} error,continue save?", Errors.Count), "Save", MessageBoxButton.YesNo, MessageBoxImage.Warning, MessageBoxResult.No);
  591. if (ret != MessageBoxResult.Yes)
  592. return;
  593. }
  594. if (OnSaveRecipeFile != null)
  595. {
  596. IsRecipeModified = false;
  597. OnSaveRecipeFile.Invoke(GetRecipeContentString(), null);
  598. }
  599. }
  600. catch (Exception ex)
  601. {
  602. System.Diagnostics.Debug.WriteLine(ex.Message);
  603. MessageBox.Show("save recipe failed!\r\n\r\n" + ex.Message, "Save", MessageBoxButton.OK, MessageBoxImage.Warning);
  604. }
  605. }
  606. /// <summary>
  607. /// get string typed recipe content
  608. /// </summary>
  609. /// <returns></returns>
  610. public string GetRecipeContentString()
  611. {
  612. if (string.IsNullOrEmpty(UserName))
  613. {
  614. var dlg1 = new Aitex.UI.RecipeEditor.UserNameInput() { Owner = Application.Current.MainWindow };
  615. var ret = dlg1.ShowDialog();
  616. if (ret.HasValue && ret.Value)
  617. {
  618. UserName = dlg1.UserName;
  619. }
  620. }
  621. RecipeHead.LastRevisionTime = DateTime.Now.ToString("yyyy-MM-ddTHH:mm:ss");
  622. RecipeHead.LastModifiedBy = UserName;
  623. InvokePropertyChanged("RecipeHead");
  624. if (RecipeRows == null || RecipeRows.Count == 0 || RecipeRows[0].RecipeItems == null || RecipeRows[0].RecipeItems.Count == 0)
  625. return string.Empty;
  626. //Dictionary<string/*CatalogName*/, Dictionary<string/*GroupName*/, List<RecipeVariableDefine/*StepList*/>>> _recipeReadingFormat;
  627. XmlDocument doc = new XmlDocument();
  628. var rootNode = doc.CreateElement("TableRecipeData");
  629. rootNode.SetAttribute("RecipeVersion", RecipeHead.RecipeVariation);
  630. rootNode.SetAttribute("CreatedBy", RecipeHead.CreatedBy);
  631. rootNode.SetAttribute("CreationTime", RecipeHead.CreationTime);
  632. rootNode.SetAttribute("LastRevisedBy", RecipeHead.LastModifiedBy);
  633. rootNode.SetAttribute("LastRevisionTime", RecipeHead.LastRevisionTime);
  634. if (!string.IsNullOrEmpty(RecipeHead.PressureMode))
  635. {
  636. rootNode.SetAttribute("PressureMode", RecipeHead.PressureMode);
  637. }
  638. if (!string.IsNullOrEmpty(RecipeHead.BasePressure))
  639. {
  640. rootNode.SetAttribute("BasePressure", RecipeHead.BasePressure);
  641. }
  642. if (!string.IsNullOrEmpty(RecipeHead.Chamber1Temp))
  643. {
  644. rootNode.SetAttribute("Chamber1Temperature", RecipeHead.Chamber1Temp);
  645. }
  646. if (!string.IsNullOrEmpty(RecipeHead.Chamber2Temp))
  647. {
  648. rootNode.SetAttribute("Chamber2Temperature", RecipeHead.Chamber2Temp);
  649. }
  650. if (!string.IsNullOrEmpty(RecipeHead.PinDownPressure))
  651. {
  652. rootNode.SetAttribute("PinDownPressure", RecipeHead.PinDownPressure);
  653. }
  654. if (!string.IsNullOrEmpty(RecipeHead.VentingPinState))
  655. {
  656. rootNode.SetAttribute("VentingPinState", RecipeHead.VentingPinState);
  657. }
  658. if (!string.IsNullOrEmpty(RecipeHead.PumpingPinState))
  659. {
  660. rootNode.SetAttribute("PumpingPinState", RecipeHead.PumpingPinState);
  661. }
  662. if (!string.IsNullOrEmpty(RecipeHead.PumpDownLimit))
  663. {
  664. rootNode.SetAttribute("PumpDownLimit", RecipeHead.PumpDownLimit);
  665. }
  666. if (!string.IsNullOrEmpty(RecipeHead.PurgeActive))
  667. {
  668. rootNode.SetAttribute("PurgeActive", RecipeHead.PurgeActive);
  669. }
  670. if (!string.IsNullOrEmpty(RecipeHead.NotToPurgeOrVent))
  671. {
  672. rootNode.SetAttribute("NotToPurgeOrVent", RecipeHead.NotToPurgeOrVent);
  673. }
  674. rootNode.SetAttribute("Barcode", RecipeHead.Barcode);
  675. rootNode.SetAttribute("Description", RecipeHead.Description);
  676. doc.AppendChild(rootNode);
  677. for (int stepIndex/* 0-> */ = 0; stepIndex < RecipeRows[0].RecipeItems.Count; stepIndex++)
  678. {
  679. var stepNode = doc.CreateElement("Step");
  680. rootNode.AppendChild(stepNode);
  681. foreach (var module in _recipeSavingFormat)
  682. {
  683. var moduleName = module.Key;
  684. XmlElement subNode = stepNode;
  685. if (!string.IsNullOrEmpty(moduleName))
  686. {
  687. string[] pathArr = moduleName.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);
  688. for (int i = 0; i < pathArr.Length; i++)
  689. {
  690. var snd = subNode.SelectSingleNode(pathArr[i]) as XmlElement;
  691. if (snd == null)
  692. {
  693. var nd = doc.CreateElement(pathArr[i]);
  694. subNode.AppendChild(nd);
  695. subNode = nd;
  696. }
  697. else
  698. {
  699. subNode = snd;
  700. }
  701. }
  702. }
  703. foreach (var controlName in module.Value)
  704. {
  705. if (controlName == "StepNo")
  706. {
  707. subNode.SetAttribute(controlName, string.Format("第{0}步", stepIndex + 1));
  708. }
  709. else
  710. {
  711. var recipeRow = RecipeRows.First((o) => o.TechnicalName == controlName);
  712. if (recipeRow == null) continue;
  713. /*to compatiable with old recipe editor, always fill 'black space' to loop step*/
  714. if (controlName == "Loop" && string.IsNullOrEmpty(recipeRow.RecipeItems[stepIndex].Value))
  715. subNode.SetAttribute(controlName, " ");
  716. else
  717. {
  718. subNode.SetAttribute(controlName, recipeRow.RecipeItems[stepIndex].Value);
  719. //bool isJump = recipeRow.RecipeItems[stepIndex].IsJump;
  720. //if (isJump)
  721. //{
  722. // string deviceType = recipeRow.RecipeItems[stepIndex].RecipeVariableDefine.DeviceType;
  723. // if (deviceType == "MFC" || deviceType == "PC")
  724. // subNode.SetAttribute(controlName + ".IsJump", isJump.ToString());
  725. //}
  726. }
  727. }
  728. }
  729. }
  730. }
  731. return doc.OuterXml;
  732. }
  733. /// <summary>
  734. /// expand groups
  735. /// </summary>
  736. private void ExpandGroups()
  737. {
  738. try
  739. {
  740. foreach (CollectionViewGroup item in DataGridControl.Items.Groups)
  741. {
  742. DataGridControl.ExpandGroup(item);
  743. }
  744. }
  745. catch (Exception ex)
  746. {
  747. System.Diagnostics.Debug.WriteLine(ex.Message);
  748. }
  749. }
  750. /// <summary>
  751. /// collapse groups
  752. /// </summary>
  753. private void CollapseGroups()
  754. {
  755. try
  756. {
  757. foreach (CollectionViewGroup item in DataGridControl.Items.Groups)
  758. {
  759. DataGridControl.CollapseGroup(item);
  760. }
  761. }
  762. catch (Exception ex)
  763. {
  764. System.Diagnostics.Debug.WriteLine(ex.Message);
  765. }
  766. }
  767. /// <summary>
  768. /// right click context menu
  769. /// </summary>
  770. private void RightClickAction()
  771. {
  772. DataGridControl.ContextMenu = null;
  773. //get selected column information
  774. List<int> selectedColumns = new List<int>();
  775. foreach (var item in DataGridControl.SelectedCellRanges)
  776. {
  777. bool dir = item.ColumnRange.StartIndex <= item.ColumnRange.EndIndex;
  778. if (dir)
  779. {
  780. for (int i = item.ColumnRange.StartIndex; i <= item.ColumnRange.EndIndex; i++)
  781. {
  782. if (i > 0)
  783. if (!selectedColumns.Contains(i)) selectedColumns.Add(i);
  784. }
  785. }
  786. else
  787. {
  788. for (int i = item.ColumnRange.StartIndex; i >= item.ColumnRange.EndIndex; i--)
  789. {
  790. if (i > 0)
  791. if (!selectedColumns.Contains(i)) selectedColumns.Add(i);
  792. }
  793. }
  794. }
  795. selectedColumns.Sort();
  796. //debug only
  797. /*
  798. string s = "";
  799. foreach (var item in selectedColumns)
  800. {
  801. s += "," + item;
  802. }
  803. MessageBox.Show(s);
  804. * */
  805. //generate context menu
  806. ContextMenu cms = new ContextMenu();
  807. if (selectedColumns.Count > 0)
  808. {
  809. string colStrings = "";
  810. foreach (var item in selectedColumns)
  811. {
  812. if (string.IsNullOrEmpty(colStrings))
  813. colStrings = item.ToString();
  814. else
  815. colStrings += "," + item.ToString();
  816. }
  817. MenuItem mi;
  818. cms.Items.Add(new MenuItem() { Header = string.Format(" 当前选中第{0}步", colStrings), FontFamily = new FontFamily("Arial,SimSun"), IsEnabled = false, Background = Brushes.Gray, Foreground = Brushes.White });
  819. //copy
  820. mi = new MenuItem() { Header = " 复制", FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns.ToList() };
  821. mi.Click += (s, e) =>
  822. {
  823. try
  824. {
  825. var list = (s as MenuItem).Tag as List<int>;
  826. _copiedColumnDatas.Clear();
  827. foreach (var colId in list)
  828. {
  829. _copiedColumnDatas.Add(colId/*index from 1*/, new List<SmartCellData>());
  830. for (int i = 0; i < RecipeRows.Count; i++)
  831. {
  832. var oldCellData = RecipeRows[i].RecipeItems[colId - 1];
  833. var newCellData = new SmartCellData() { Value = oldCellData.Value, RecipeVariableDefine = oldCellData.RecipeVariableDefine };
  834. _copiedColumnDatas[colId].Add(newCellData);
  835. }
  836. }
  837. }
  838. catch (Exception ex)
  839. {
  840. System.Diagnostics.Debug.WriteLine(ex.Message);
  841. }
  842. };
  843. cms.Items.Add(mi);
  844. if (selectedColumns.Count < RecipeRows[0].RecipeItems.Count)
  845. {
  846. mi = new MenuItem() { Header = " 剪切", FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns.ToList() };
  847. mi.Click += (s, e) =>
  848. {
  849. try
  850. {
  851. AddUndoHistory("剪切", CloneRecipeRowData(RecipeRows));
  852. var list = (s as MenuItem).Tag as List<int>;
  853. _copiedColumnDatas.Clear();
  854. foreach (var colId in list)
  855. {
  856. _copiedColumnDatas.Add(colId/*index from 1*/, new List<SmartCellData>());
  857. for (int i = 0; i < RecipeRows.Count; i++)
  858. {
  859. var oldCellData = RecipeRows[i].RecipeItems[colId - 1];
  860. var newCellData = new SmartCellData() { Value = oldCellData.Value, RecipeVariableDefine = oldCellData.RecipeVariableDefine };
  861. _copiedColumnDatas[colId].Add(newCellData);
  862. }
  863. }
  864. foreach (var item in RecipeRows)
  865. {
  866. var collection = new ObservableCollection<SmartCellData>();
  867. for (int index = 0; index < item.RecipeItems.Count; index++)
  868. {
  869. if (list.Contains(index + 1))
  870. continue;
  871. collection.Add(item.RecipeItems[index]);
  872. }
  873. item.RecipeItems = collection;
  874. }
  875. RefreshDataGrid();
  876. RefreshCellsDisplay(false);
  877. }
  878. catch (Exception ex)
  879. {
  880. System.Diagnostics.Debug.WriteLine(ex.Message);
  881. }
  882. };
  883. cms.Items.Add(mi);
  884. mi = new MenuItem() { Header = " 删除", FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns.ToList() };
  885. mi.Click += (s, e) =>
  886. {
  887. try
  888. {
  889. AddUndoHistory("删除", CloneRecipeRowData(RecipeRows));
  890. var list = (s as MenuItem).Tag as List<int>;
  891. foreach (var item in RecipeRows)
  892. {
  893. var collection = new ObservableCollection<SmartCellData>();
  894. for (int index = 0; index < item.RecipeItems.Count; index++)
  895. {
  896. if (list.Contains(index + 1))
  897. continue;
  898. collection.Add(item.RecipeItems[index]);
  899. }
  900. item.RecipeItems = collection;
  901. }
  902. RefreshDataGrid();
  903. RefreshCellsDisplay(false);
  904. }
  905. catch (Exception ex)
  906. {
  907. System.Diagnostics.Debug.WriteLine(ex.Message);
  908. }
  909. };
  910. cms.Items.Add(mi);
  911. }
  912. if (selectedColumns.Count == 1 && _copiedColumnDatas.Count > 0)
  913. {
  914. mi = new MenuItem() { Header = string.Format(" 插入第{0}步后", selectedColumns[0]/*, _copiedColumnDatas.Count*/), FontFamily = new FontFamily("Arial,SimSun"), Tag = selectedColumns[0] };
  915. mi.Click += (s, e) =>
  916. {
  917. try
  918. {
  919. AddUndoHistory("插入", CloneRecipeRowData(RecipeRows));
  920. int insertColId = (int)(s as MenuItem).Tag;
  921. for (int rowIndex = 0; rowIndex < RecipeRows.Count; rowIndex++)
  922. {
  923. var collection = new ObservableCollection<SmartCellData>();
  924. for (int index = 0; index < insertColId; index++)
  925. {
  926. collection.Add(RecipeRows[rowIndex].RecipeItems[index]);
  927. }
  928. foreach (var col in _copiedColumnDatas)
  929. {
  930. collection.Add(new SmartCellData() { Value = col.Value[rowIndex].Value, RecipeVariableDefine = col.Value[rowIndex].RecipeVariableDefine });
  931. }
  932. for (int index = insertColId; index < RecipeRows[rowIndex].RecipeItems.Count; index++)
  933. {
  934. collection.Add(RecipeRows[rowIndex].RecipeItems[index]);
  935. }
  936. RecipeRows[rowIndex].RecipeItems = collection;
  937. }
  938. RefreshDataGrid();
  939. RefreshCellsDisplay(false);
  940. }
  941. catch (Exception ex)
  942. {
  943. System.Diagnostics.Debug.WriteLine(ex.Message);
  944. }
  945. };
  946. cms.Items.Add(mi);
  947. }
  948. }
  949. //show context menu
  950. DataGridControl.ContextMenu = cms;
  951. cms.Visibility = Visibility.Visible;
  952. }
  953. /// <summary>
  954. /// Parse recipe content with recipe format
  955. /// </summary>
  956. /// <param name="recipeFormat"></param>
  957. /// <param name="recipeContent"></param>
  958. /// <param name="selectedStepNo"></param>
  959. public void LoadRecipe(string recipeFormat, string recipeContent, int selectedStepNo = -1)
  960. {
  961. CurrentRunningStepNo = selectedStepNo;
  962. IsHideSameContent = false;
  963. IsRecipeModified = false;
  964. RecipeHead = new RecipeEditor.RecipeHead();
  965. DataGridControl.ContextMenu = null;
  966. RecipeInfo = "";
  967. IsBusy = true;
  968. InvokePropertyChanged("IsBusy");
  969. UndoList.Clear();
  970. RedoList.Clear();
  971. InvokePropertyChanged("UndoList");
  972. InvokePropertyChanged("RedoList");
  973. InvokePropertyChanged("IsUndoEnabled");
  974. InvokePropertyChanged("IsRedoEnabled");
  975. try
  976. {
  977. RecipeRows = new ObservableCollection<RecipeRow>();
  978. _recipeReadingFormat = new Dictionary<string, Dictionary<string, List<RecipeVariableDefine>>>();
  979. _recipeSavingFormat = new Dictionary<string, List<string>>();
  980. //parse recipe format
  981. XmlDocument formatXml = new XmlDocument();
  982. formatXml.LoadXml(recipeFormat);
  983. _currentRecipeFormatContent = formatXml.OuterXml;
  984. //reading recipe variation
  985. string recipeVariationName = formatXml.SelectSingleNode("TableRecipeFormat").Attributes["RecipeVersion"].Value;
  986. if (String.Compare(recipeVariationName, _currentRecipeVariationName) != 0)
  987. {
  988. //if variation name is different from previous loaded recipe -> clear all previous copied recipe columns
  989. _copiedColumnDatas.Clear();
  990. }
  991. _currentRecipeVariationName = recipeVariationName;
  992. //reading recipe validation releated parameters
  993. _preDefinedRecipeVars = new Dictionary<string, string>();
  994. foreach (XmlElement nd in formatXml.SelectNodes("/TableRecipeFormat/Validation/Predefine/Item"))
  995. {
  996. _preDefinedRecipeVars.Add(nd.Attributes["VarName"].Value, nd.Attributes["Value"].Value);
  997. }
  998. //reading check variables
  999. _checkVariables = new List<string>();
  1000. foreach (XmlElement nd in formatXml.SelectNodes("/TableRecipeFormat/Validation/CheckVariable/Var"))
  1001. {
  1002. string varName = nd.Attributes["Name"].Value;
  1003. _checkVariables.Add(varName);
  1004. }
  1005. //reading validation rules
  1006. _validationRules = new List<Tuple<string, string, string>>();
  1007. foreach (XmlElement nd in formatXml.SelectNodes("/TableRecipeFormat/Validation/Restriction/Rule"))
  1008. {
  1009. string varName = nd.Attributes["VarName"].Value;
  1010. string checkCondition = nd.Attributes["CheckCondition"].Value.Replace("&lt;", "<").Replace("&gt;", ">");
  1011. string message = nd.Attributes["Message"].Value.Replace("'", "\"");
  1012. _validationRules.Add(new Tuple<string, string, string>(varName, checkCondition, message));
  1013. }
  1014. //parsing recipe format xml file
  1015. foreach (XmlElement catalogNode in formatXml.SelectNodes("/TableRecipeFormat/Catalog"))
  1016. {
  1017. string catalogName = catalogNode.Attributes["DisplayName"].Value;
  1018. _recipeReadingFormat.Add(catalogName, new Dictionary<string, List<RecipeVariableDefine>>());
  1019. foreach (XmlElement groupNode in catalogNode.SelectNodes("Group"))
  1020. {
  1021. string groupName = groupNode.Attributes["DisplayName"].Value;
  1022. _recipeReadingFormat[catalogName].Add(groupName, new List<RecipeVariableDefine>());
  1023. foreach (XmlElement stepNode in groupNode.SelectNodes("Step"))
  1024. {
  1025. string stepModuleName = stepNode.Attributes["ModuleName"].Value;
  1026. string stepDeviceType = stepNode.Attributes["DeviceType"].Value;
  1027. string stepDisplayName = stepNode.Attributes["DisplayName"].Value;
  1028. string stepControlName = stepNode.Attributes["ControlName"].Value;
  1029. string stepInputType = stepNode.Attributes["InputType"].Value;
  1030. string stepDescription = stepNode.HasAttribute("Desc") ? stepNode.Attributes["Desc"].Value : "";
  1031. double stepMin = double.Parse(stepNode.HasAttribute("Min") ? stepNode.Attributes["Min"].Value : "0");
  1032. double stepMax = double.Parse(stepNode.HasAttribute("Max") ? stepNode.Attributes["Max"].Value : "0");
  1033. var selectionList = new List<Tuple<string, string>>();
  1034. foreach (XmlElement selectionNode in stepNode.SelectNodes("Item"))
  1035. {
  1036. selectionList.Add(new Tuple<string, string>(selectionNode.Attributes["ControlName"].Value, selectionNode.Attributes["DisplayName"].Value));
  1037. }
  1038. if (!_recipeSavingFormat.ContainsKey(stepModuleName)) _recipeSavingFormat.Add(stepModuleName, new List<string>());
  1039. _recipeSavingFormat[stepModuleName].Add(stepControlName);
  1040. if (stepControlName == "StepNo")
  1041. continue;
  1042. _recipeReadingFormat[catalogName][groupName].Add(new RecipeVariableDefine()
  1043. {
  1044. CellType = (CellType)Enum.Parse(typeof(CellType), stepInputType),
  1045. Description = stepDescription,
  1046. DeviceType = stepDeviceType,
  1047. DropdownItemList = selectionList,
  1048. MaxValue = stepMax,
  1049. //MinValue = stepDeviceType.Equals("MFC",StringComparison.InvariantCultureIgnoreCase)? stepMax*2.0/100: stepMin,
  1050. MinValue = stepMin,
  1051. GroupName = groupName,
  1052. CatalogName = catalogName,
  1053. TechnicalName = stepControlName,
  1054. FriendlyName = stepDisplayName
  1055. });
  1056. }
  1057. }
  1058. }
  1059. //parse recipe content
  1060. XmlDocument contentXml = new XmlDocument();
  1061. contentXml.LoadXml(recipeContent);
  1062. contentXml.DocumentElement.SetAttribute("RecipeVersion", _currentRecipeVariationName);
  1063. //read recipe head
  1064. //em. RecipeVersion="Ace" CreatedBy="tech" CreationTime="2013-02-02T12:36:02" LastRevisedBy="Peter" LastRevisionTime="2013-10-22T13:30:29" Description="5e46af80-49f9-4b4f-b04b-bc911fb292f8"
  1065. RecipeHead.CreatedBy = contentXml.DocumentElement.HasAttribute("CreatedBy") ? contentXml.DocumentElement.Attributes["CreatedBy"].Value : "(无)";
  1066. RecipeHead.CreationTime = contentXml.DocumentElement.HasAttribute("CreationTime") ? contentXml.DocumentElement.Attributes["CreationTime"].Value : "(无)";
  1067. RecipeHead.LastModifiedBy = contentXml.DocumentElement.HasAttribute("LastRevisedBy") ? contentXml.DocumentElement.Attributes["LastRevisedBy"].Value : "(无)";
  1068. RecipeHead.LastRevisionTime = contentXml.DocumentElement.HasAttribute("LastRevisionTime") ? contentXml.DocumentElement.Attributes["LastRevisionTime"].Value : "(无)";
  1069. if (contentXml.DocumentElement.HasAttribute("PressureMode"))
  1070. {
  1071. RecipeHead.PressureMode = contentXml.DocumentElement.Attributes["PressureMode"].Value;
  1072. }
  1073. if (contentXml.DocumentElement.HasAttribute("BasePressure"))
  1074. {
  1075. RecipeHead.BasePressure = contentXml.DocumentElement.Attributes["BasePressure"].Value;
  1076. }
  1077. if (contentXml.DocumentElement.HasAttribute("PumpDownLimit"))
  1078. {
  1079. RecipeHead.PumpDownLimit = contentXml.DocumentElement.Attributes["PumpDownLimit"].Value;
  1080. }
  1081. if (contentXml.DocumentElement.HasAttribute("Chamber1Temperature"))
  1082. {
  1083. RecipeHead.Chamber1Temp = contentXml.DocumentElement.Attributes["Chamber1Temperature"].Value;
  1084. }
  1085. if (contentXml.DocumentElement.HasAttribute("Chamber2Temperature"))
  1086. {
  1087. RecipeHead.Chamber2Temp = contentXml.DocumentElement.Attributes["Chamber2Temperature"].Value;
  1088. }
  1089. if (contentXml.DocumentElement.HasAttribute("PinDownPressure"))
  1090. {
  1091. RecipeHead.PinDownPressure = contentXml.DocumentElement.Attributes["PinDownPressure"].Value;
  1092. }
  1093. if (contentXml.DocumentElement.HasAttribute("VentingPinState"))
  1094. {
  1095. RecipeHead.VentingPinState = contentXml.DocumentElement.Attributes["VentingPinState"].Value;
  1096. }
  1097. if (contentXml.DocumentElement.HasAttribute("PumpingPinState"))
  1098. {
  1099. RecipeHead.PumpingPinState = contentXml.DocumentElement.Attributes["PumpingPinState"].Value;
  1100. }
  1101. if (contentXml.DocumentElement.HasAttribute("PurgeActive"))
  1102. {
  1103. RecipeHead.PurgeActive = contentXml.DocumentElement.Attributes["PurgeActive"].Value;
  1104. }
  1105. if (contentXml.DocumentElement.HasAttribute("NotToPurgeOrVent"))
  1106. {
  1107. RecipeHead.NotToPurgeOrVent = contentXml.DocumentElement.Attributes["NotToPurgeOrVent"].Value;
  1108. }
  1109. if (contentXml.DocumentElement.HasAttribute("Barcode"))
  1110. {
  1111. RecipeHead.Barcode = contentXml.DocumentElement.Attributes["Barcode"].Value;
  1112. }
  1113. RecipeHead.RecipeVariation = contentXml.DocumentElement.HasAttribute("RecipeVersion") ? contentXml.DocumentElement.Attributes["RecipeVersion"].Value : "(NULL)";
  1114. RecipeHead.Description = contentXml.DocumentElement.HasAttribute("Description") ? contentXml.DocumentElement.Attributes["Description"].Value : "(NULL)";
  1115. var allRecipeItems = new List<Dictionary<string, string>>();
  1116. foreach (XmlElement stepNode in contentXml.SelectNodes("/TableRecipeData/Step"))
  1117. {
  1118. var stepDic = new Dictionary<string, string>();
  1119. allRecipeItems.Add(stepDic);
  1120. foreach (XmlAttribute att in stepNode.Attributes)
  1121. {
  1122. stepDic.Add(att.Name, att.Value);
  1123. }
  1124. foreach (XmlElement innerStep in stepNode.ChildNodes)
  1125. {
  1126. foreach (XmlAttribute att in innerStep.Attributes)
  1127. {
  1128. stepDic.Add(att.Name, att.Value);
  1129. }
  1130. foreach (XmlElement innerInnerStep in innerStep.ChildNodes)
  1131. {
  1132. foreach (XmlAttribute att in innerInnerStep.Attributes)
  1133. {
  1134. stepDic.Add(att.Name, att.Value);
  1135. }
  1136. }
  1137. }
  1138. }
  1139. //generate view model
  1140. RowVarNameDic = new Dictionary<string, int>();
  1141. int rowIndex = 0;
  1142. foreach (var catalog in _recipeReadingFormat.Keys)
  1143. {
  1144. foreach (var group in _recipeReadingFormat[catalog].Keys)
  1145. {
  1146. foreach (var var1 in _recipeReadingFormat[catalog][group])
  1147. {
  1148. var singleRow = new RecipeRow() { CatalogName = catalog, FriendlyName = /*group + */var1.FriendlyName, TechnicalName = var1.TechnicalName };
  1149. for (int stepNo = 0; stepNo < allRecipeItems.Count; stepNo++)
  1150. {
  1151. var stepCell = new SmartCellData() { RecipeVariableDefine = var1 };
  1152. if (allRecipeItems[stepNo].ContainsKey(var1.TechnicalName))
  1153. {
  1154. stepCell.Value = allRecipeItems[stepNo][var1.TechnicalName];
  1155. //stepCell.ShowsJumpControl = false;
  1156. //if (var1.CellType == CellType.NumInput)
  1157. //{
  1158. // if (var1.DeviceType == "MFC" || var1.DeviceType == "PC")
  1159. // {
  1160. // string jumpString = var1.TechnicalName + ".IsJump";
  1161. // stepCell.IsJump = allRecipeItems[stepNo].ContainsKey(jumpString) ? bool.Parse(allRecipeItems[stepNo][jumpString]) : false;
  1162. // stepCell.ShowsJumpControl = true;
  1163. // }
  1164. //}
  1165. }
  1166. else
  1167. stepCell.Value = "0";
  1168. singleRow.RecipeItems.Add(stepCell);
  1169. }
  1170. RecipeRows.Add(singleRow);
  1171. RowVarNameDic.Add(var1.TechnicalName, rowIndex++);
  1172. }
  1173. }
  1174. }
  1175. //refresh datagrid
  1176. RefreshDataGrid();
  1177. //refresh recipe information
  1178. RefreshCellsDisplay();
  1179. if (OnLoadRecipeContent != null)
  1180. OnLoadRecipeContent.Invoke(recipeContent, null);
  1181. }
  1182. catch (Exception ex)
  1183. {
  1184. System.Diagnostics.Debug.WriteLine(ex.Message);
  1185. //LOG.Write("", ex);
  1186. }
  1187. IsBusy = false;
  1188. InvokePropertyChanged("IsBusy");
  1189. }
  1190. /// <summary>
  1191. /// 检查变量ramp rate
  1192. /// </summary>
  1193. /// <param name="stepNo"></param>
  1194. /// <param name="rampEnable"></param>
  1195. /// <param name="varName"></param>
  1196. /// <param name="rampTime"></param>
  1197. /// <param name="maxRampUpRate"></param>
  1198. /// <param name="maxRampDownRate"></param>
  1199. /// <returns>False:check ok, True: check failed</returns>
  1200. public bool CheckRampRate(int stepNo, string rampEnable, string varName, string rampTime, double maxRampUpRate, double maxRampDownRate)
  1201. {
  1202. try
  1203. {
  1204. if (stepNo <= 0) return false;
  1205. int rowIndex = RowVarNameDic[varName];
  1206. double currentValue = double.Parse(RecipeRows[rowIndex].RecipeItems[stepNo].Value);
  1207. //if (varName == "AZone.Setpoint" || varName == "BZone.Setpoint" || varName == "CZone.Setpoint" || varName == "DZone.Setpoint")
  1208. //{
  1209. // int heatControlModeIndex = RowVarNameDic["Heater.Mode"];
  1210. // string curStepHeatCtrlMode = RecipeRows[heatControlModeIndex].RecipeItems[stepNo].Value;
  1211. // string lastStepHeatCtrlMode = RecipeRows[heatControlModeIndex].RecipeItems[stepNo - 1].Value;
  1212. // if (curStepHeatCtrlMode != lastStepHeatCtrlMode)
  1213. // {
  1214. // if (!(lastStepHeatCtrlMode.Equals("CurrentControl") && curStepHeatCtrlMode.Equals("PyroTempControl")))
  1215. // return false;
  1216. // int endbyIndex = RowVarNameDic["EndBy"];
  1217. // int endValueIndex = RowVarNameDic["EndValue"];
  1218. // string endby = RecipeRows[endbyIndex].RecipeItems[stepNo - 1].Value;
  1219. // EndByCondition endbyEnum;
  1220. // if (!Enum.TryParse(endby, out endbyEnum)) return false;
  1221. // if (endbyEnum != EndByCondition.PmTempGt && endbyEnum != EndByCondition.PmTempLt) return false;
  1222. // string end = RecipeRows[endValueIndex].RecipeItems[stepNo - 1].Value;
  1223. // double endValue;
  1224. // if (!double.TryParse(end, out endValue)) return false;
  1225. // return CheckRampRate(rampEnable, rampTime, maxRampUpRate, maxRampDownRate, endValue, currentValue);
  1226. // }
  1227. //}
  1228. double prevValue = double.Parse(RecipeRows[rowIndex].RecipeItems[stepNo - 1].Value);
  1229. return CheckRampRate(rampEnable, rampTime, maxRampUpRate, maxRampDownRate, prevValue, currentValue);
  1230. }
  1231. catch (Exception ex)
  1232. {
  1233. System.Diagnostics.Debug.WriteLine(ex.Message);
  1234. return true;
  1235. }
  1236. }
  1237. bool CheckRampRate(string rampEnable, string rampTime, double maxRampUpRate, double maxRampDownRate, double prevValue, double currentValue)
  1238. {
  1239. bool isRampEnable = bool.Parse(rampEnable);
  1240. //string[] timeStr = rampTime.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  1241. //string tt = string.Join(":", timeStr);
  1242. TimeSpan timeSpan;
  1243. TimeSpan.TryParse(rampTime, out timeSpan);
  1244. double totalTimeSec = timeSpan.TotalSeconds;
  1245. double diff = currentValue - prevValue;
  1246. if (!isRampEnable || totalTimeSec <= 0)
  1247. {
  1248. if (diff != 0) return true;
  1249. return false;
  1250. }
  1251. else
  1252. {
  1253. double rampRate = diff / totalTimeSec;
  1254. return (rampRate > 0 && rampRate >= maxRampUpRate) || (rampRate < 0 && rampRate <= -maxRampDownRate);
  1255. }
  1256. }
  1257. /// <summary>
  1258. /// Refresh datagrid cell data display
  1259. /// </summary>
  1260. /// <param name="moving2RunningStepPosition">True: moving to current running step position</param>
  1261. public void RefreshCellsDisplay(bool moving2RunningStepPosition = true)
  1262. {
  1263. try
  1264. {
  1265. if (RecipeRows == null || RecipeRows.Count < 2)
  1266. return;
  1267. Errors = new List<Tuple<int, int, string, string>>();
  1268. Dictionary<int, string> dicEndby = new Dictionary<int, string>();
  1269. Dictionary<int, string> dicPressureMode = new Dictionary<int, string>();
  1270. Dictionary<int, string> dicRfMode = new Dictionary<int, string>();
  1271. Dictionary<int, string> dicRfMatchProcessMode = new Dictionary<int, string>();
  1272. Dictionary<int, string> dicSetMatchPositionC1 = new Dictionary<int, string>();
  1273. Dictionary<int, string> dicSetMatchPositionC2 = new Dictionary<int, string>();
  1274. for (int i = 0; i < RecipeRows.Count; i++)
  1275. {
  1276. for (int j = 0; j < RecipeRows[i].RecipeItems.Count; j++)
  1277. {
  1278. var cell = RecipeRows[i].RecipeItems[j];
  1279. cell.RowIndex = i;
  1280. cell.ColIndex = j;
  1281. cell.ErrInfo = string.Empty;
  1282. bool logicEnable = true;
  1283. if (cell.RecipeVariableDefine.TechnicalName == "EndBy")
  1284. dicEndby[j] = cell.Value;
  1285. if (cell.RecipeVariableDefine.TechnicalName == "ThrottleValve.SetMode")
  1286. {
  1287. dicPressureMode[j] = cell.Value;
  1288. }
  1289. if (cell.RecipeVariableDefine.TechnicalName == "PressureControl.SetTVMode")
  1290. {
  1291. dicPressureMode[j] = cell.Value;
  1292. }
  1293. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetMode")
  1294. dicRfMode[j] = cell.Value;
  1295. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchProcessMode")
  1296. dicRfMatchProcessMode[j] = cell.Value;
  1297. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC1")
  1298. dicSetMatchPositionC1[j] = cell.Value;
  1299. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC2")
  1300. dicSetMatchPositionC2[j] = cell.Value;
  1301. if (cell.RecipeVariableDefine.TechnicalName == "Time")
  1302. {
  1303. logicEnable = dicEndby.ContainsKey(j) && (dicEndby[j] == "EndByStepTime" ||
  1304. dicEndby[j] == "EndByHeatUp" ||
  1305. dicEndby[j] == "EndByEndPoint");
  1306. }
  1307. if (cell.RecipeVariableDefine.TechnicalName == "ThrottleValve.SetPosition")
  1308. {
  1309. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPositionCtrl";
  1310. }
  1311. if (cell.RecipeVariableDefine.TechnicalName == "ThrottleValve.SetPressure")
  1312. {
  1313. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPressureCtrl";
  1314. }
  1315. if (cell.RecipeVariableDefine.TechnicalName == "PressureControl.SetTVPosition")
  1316. {
  1317. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPositionCtrl";
  1318. }
  1319. if (cell.RecipeVariableDefine.TechnicalName == "PressureControl.SetTVPressure")
  1320. {
  1321. logicEnable = dicPressureMode.ContainsKey(j) && dicPressureMode[j] == "TVPressureCtrl";
  1322. }
  1323. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetPulsingFrequency")
  1324. {
  1325. logicEnable = dicRfMode.ContainsKey(j) && dicRfMode[j] == "PulsingMode";
  1326. }
  1327. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetPulsingDuty")
  1328. {
  1329. logicEnable = dicRfMode.ContainsKey(j) && dicRfMode[j] == "PulsingMode";
  1330. }
  1331. if (cell.RecipeVariableDefine.TechnicalName == "Rf.SetPowerOnTime")
  1332. {
  1333. logicEnable = dicEndby.ContainsKey(j) && dicEndby[j] == "EndByRfTime";
  1334. }
  1335. if (cell.RecipeVariableDefine.TechnicalName == "Rf1.SetPowerOnTime")
  1336. {
  1337. logicEnable = dicEndby.ContainsKey(j) && dicEndby[j] == "EndByRfTime";
  1338. }
  1339. if (cell.RecipeVariableDefine.TechnicalName == "Rf2.SetPowerOnTime")
  1340. {
  1341. logicEnable = dicEndby.ContainsKey(j) && dicEndby[j] == "EndByRfTime";
  1342. }
  1343. if (cell.RecipeVariableDefine.TechnicalName == "EPD.SetConfig")
  1344. {
  1345. logicEnable = dicEndby.ContainsKey(j) && dicEndby[j] == "EndByEndPoint";
  1346. if (string.IsNullOrEmpty(cell.Value) || cell.Value.StartsWith("n/a"))
  1347. cell.Value = _defaultEndPointValue;
  1348. }
  1349. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchProcessMode")
  1350. {
  1351. logicEnable = dicRfMatchProcessMode.ContainsKey(j);// && dicRfMatchProcessMode[j] == "TritonPresetMode";
  1352. }
  1353. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC1")
  1354. {
  1355. logicEnable = dicSetMatchPositionC1.ContainsKey(j);// && dicRfMatchProcessMode[j] == "TritonPresetMode";
  1356. }
  1357. if (cell.RecipeVariableDefine.TechnicalName == "Match.SetMatchPositionC2")
  1358. {
  1359. logicEnable = dicSetMatchPositionC2.ContainsKey(j);// && dicRfMatchProcessMode[j] == "TritonPresetMode";
  1360. }
  1361. cell.IsMasked = !logicEnable;
  1362. //update diff variable numbers
  1363. if (cell.RecipeVariableDefine.TechnicalName == "Ramp")
  1364. {
  1365. //更新当前步骤中Ramp的变量数据
  1366. if (j == 0)
  1367. {
  1368. cell.Tag = 0;
  1369. }
  1370. else
  1371. {
  1372. int rampNum = 0;
  1373. for (int s1 = 0; s1 < RecipeRows.Count; s1++)
  1374. {
  1375. if (RecipeRows[s1].CatalogName == "StepInfo")// RecipeRows[s1].RecipeItems[j].RecipeVariableDefine.CellType == CellType.ReadOnly)
  1376. continue;
  1377. string preValue = RecipeRows[s1].RecipeItems[j - 1].Value;
  1378. string curValue = RecipeRows[s1].RecipeItems[j].Value;
  1379. if (RecipeRows[s1].RecipeItems[j].RecipeVariableDefine.CellType == CellType.NumInput)
  1380. {
  1381. double pd, cd;
  1382. if (double.TryParse(preValue, out pd) && double.TryParse(curValue, out cd))
  1383. if (pd != cd) rampNum++;
  1384. }
  1385. else if (String.Compare(preValue, curValue, false) != 0)
  1386. {
  1387. rampNum++;
  1388. }
  1389. }
  1390. cell.Tag = rampNum;
  1391. }
  1392. cell.InvokePropertyChanged();
  1393. }
  1394. #region mask (hide or show cell content)
  1395. if ((MaskedTechNames != null && MaskedTechNames.Contains(cell.RecipeVariableDefine.TechnicalName)) ||
  1396. (MaskedCatalogNames != null && MaskedCatalogNames.Contains(cell.RecipeVariableDefine.CatalogName)) || !logicEnable)
  1397. cell.IsMasked = true;
  1398. else
  1399. cell.IsMasked = false;
  1400. #endregion mask (hide or show cell content)
  1401. #region check cell data range
  1402. switch (cell.RecipeVariableDefine.CellType)
  1403. {
  1404. case CellType.CheckBox:
  1405. {
  1406. if (string.Compare(cell.Value, "true", true) == 0 || string.Compare(cell.Value, "false", true) == 0)
  1407. {
  1408. cell.ErrInfo = "";
  1409. cell.Background = Brushes.Transparent;
  1410. }
  1411. else
  1412. {
  1413. string reason = string.Format("Value '{0}' not valid", cell.Value);
  1414. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1415. cell.ErrInfo = reason;
  1416. cell.Background = Brushes.Pink;
  1417. }
  1418. }
  1419. break;
  1420. case CellType.EditableSelection:
  1421. {
  1422. cell.ErrInfo = "";
  1423. cell.Background = Brushes.Transparent;
  1424. }
  1425. break;
  1426. case CellType.NumInput:
  1427. {
  1428. double min = cell.RecipeVariableDefine.MinValue;
  1429. double max = cell.RecipeVariableDefine.MaxValue;
  1430. double v;
  1431. if (!double.TryParse(cell.Value, out v))
  1432. {
  1433. string reason = string.Format("Value '{0}' not valid", cell.Value);
  1434. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1435. cell.ErrInfo = reason;
  1436. cell.Background = Brushes.Pink;
  1437. }
  1438. else if (v > max || v < 0 || (v < min && v > max * 0.1 / 100))
  1439. {
  1440. string reason = string.Format("Value'{0}',Out of Range {1}~{2}", cell.Value, min, max);
  1441. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1442. cell.ErrInfo = reason;
  1443. cell.Background = Brushes.Pink;
  1444. }
  1445. else
  1446. {
  1447. cell.ErrInfo = "";
  1448. cell.Background = Brushes.Transparent;
  1449. }
  1450. }
  1451. break;
  1452. case CellType.ReadOnlySelection:
  1453. {
  1454. if (cell.RecipeVariableDefine.DropdownItemList != null && cell.RecipeVariableDefine.DropdownItemList.Find((o) => o.Item1 == cell.Value) != null)
  1455. {
  1456. cell.ErrInfo = "";
  1457. cell.Background = Brushes.Transparent;
  1458. }
  1459. else
  1460. {
  1461. string reason = string.Format("Value'{0}' is not valid", cell.Value);
  1462. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1463. cell.ErrInfo = reason;
  1464. cell.Background = Brushes.Pink;
  1465. }
  1466. }
  1467. break;
  1468. case CellType.ReadOnly:
  1469. case CellType.TextInput:
  1470. cell.ErrInfo = "";
  1471. cell.Background = Brushes.Transparent;
  1472. break;
  1473. case CellType.TimeInput:
  1474. {
  1475. string[] arr = cell.Value.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  1476. int h, mi, s;
  1477. 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)
  1478. {
  1479. cell.ErrInfo = "";
  1480. cell.Background = Brushes.Transparent;
  1481. }
  1482. else
  1483. {
  1484. string reason = string.Format("value'{0}' is not valid", cell.Value);
  1485. Errors.Add(new Tuple<int, int, string, string>(i, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1486. cell.ErrInfo = reason;
  1487. cell.Background = Brushes.Pink;
  1488. }
  1489. }
  1490. break;
  1491. }
  1492. #endregion check cell data range
  1493. #region mark data trend / hide same content
  1494. if (j == 0) //step one
  1495. {
  1496. cell.Foreground = Brushes.Black;
  1497. cell.FontWeight = FontWeights.Normal;
  1498. cell.IsHidden = false;
  1499. cell.InvokePropertyChanged();
  1500. cell.IsMasked = !logicEnable;
  1501. continue;
  1502. }
  1503. var preCell = RecipeRows[i].RecipeItems[j - 1];
  1504. if (cell.RecipeVariableDefine.CellType == CellType.NumInput)
  1505. {
  1506. double preValue = 0;
  1507. double.TryParse(preCell.Value.ToString(), out preValue);
  1508. double curValue = 0;
  1509. double.TryParse(cell.Value.ToString(), out curValue);
  1510. if (curValue > preValue)
  1511. {
  1512. cell.Foreground = Brushes.Red;
  1513. cell.FontWeight = FontWeights.Bold;
  1514. }
  1515. else if (curValue < preValue)
  1516. {
  1517. cell.Foreground = Brushes.Blue;
  1518. cell.FontWeight = FontWeights.Bold;
  1519. }
  1520. else
  1521. {
  1522. cell.Foreground = Brushes.Black;
  1523. cell.FontWeight = FontWeights.Normal;
  1524. }
  1525. }
  1526. else
  1527. {
  1528. //not number type
  1529. cell.Foreground = Brushes.Black;
  1530. cell.FontWeight = FontWeights.Normal;
  1531. }
  1532. if (IsHideSameContent && cell.Value == preCell.Value)
  1533. cell.IsHidden = true;
  1534. else
  1535. cell.IsHidden = false;
  1536. //!logicEnable;
  1537. cell.IsMasked = !logicEnable;
  1538. //if (!logicEnable)
  1539. //{
  1540. // cell.Background = Brushes.DarkGray;
  1541. // cell.IsMasked = true;
  1542. //}
  1543. #endregion mark data trend / hide same content
  1544. cell.InvokePropertyChanged();
  1545. }
  1546. }
  1547. #region check loop
  1548. int loopRowId = -1;
  1549. for (int i = 0; i < RecipeRows.Count; i++)
  1550. {
  1551. if (RecipeRows[i].TechnicalName == "Loop")
  1552. {
  1553. loopRowId = i;
  1554. break;
  1555. }
  1556. }
  1557. for (int j = 0; j < RecipeRows[loopRowId].RecipeItems.Count; j++)
  1558. {
  1559. var cell = RecipeRows[loopRowId].RecipeItems[j];
  1560. bool isLoopStart = Regex.IsMatch(cell.Value, @"^Loop\x20\d+$");
  1561. bool isLoopEnd = Regex.IsMatch(cell.Value, @"^Loop End$");
  1562. bool isNullOrEmpty = string.IsNullOrWhiteSpace(cell.Value);
  1563. if (!isLoopEnd && !isLoopStart && !isNullOrEmpty)
  1564. {
  1565. string reason = string.Format("Value '{0}' not valid", cell.Value);
  1566. cell.ErrInfo = reason;
  1567. cell.Background = Brushes.Pink;
  1568. Errors.Add(new Tuple<int, int, string, string>(loopRowId, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1569. }
  1570. if (isLoopEnd)
  1571. {
  1572. string reason = "Loop Start 缺失";
  1573. cell.ErrInfo = reason;
  1574. cell.Background = Brushes.Pink;
  1575. Errors.Add(new Tuple<int, int, string, string>(loopRowId, j, cell.RecipeVariableDefine.FriendlyName, reason));
  1576. }
  1577. else if (isLoopStart)
  1578. {
  1579. for (int k = j + 1; k < RecipeRows[loopRowId].RecipeItems.Count; k++)
  1580. {
  1581. cell = RecipeRows[loopRowId].RecipeItems[k];
  1582. bool isCurStepLoopStart = Regex.IsMatch(cell.Value, @"^Loop\x20\d+$");
  1583. bool isCurStepLoopEnd = Regex.IsMatch(cell.Value, @"^Loop End$");
  1584. isNullOrEmpty = string.IsNullOrWhiteSpace(cell.Value);
  1585. if (!isCurStepLoopEnd && !isCurStepLoopStart && !isNullOrEmpty)
  1586. {
  1587. string reason = string.Format("Value '{0}' not valid", cell.Value);
  1588. cell.ErrInfo = reason;
  1589. cell.Background = Brushes.Pink;
  1590. Errors.Add(new Tuple<int, int, string, string>(loopRowId, k, cell.RecipeVariableDefine.FriendlyName, reason));
  1591. }
  1592. else if (isCurStepLoopStart)
  1593. {
  1594. string reason = "前面循环没有结束,不能设置新的Loop Start标志";
  1595. cell.ErrInfo = reason;
  1596. cell.Background = Brushes.Pink;
  1597. Errors.Add(new Tuple<int, int, string, string>(loopRowId, k, cell.RecipeVariableDefine.FriendlyName, reason));
  1598. }
  1599. else if (isCurStepLoopEnd)
  1600. {
  1601. //mark loop steps with blue background
  1602. for (int m1 = j; m1 <= k; m1++)
  1603. {
  1604. var curCell = RecipeRows[loopRowId].RecipeItems[m1];
  1605. if (curCell.Background == Brushes.Transparent)
  1606. curCell.Background = Brushes.LightGreen;
  1607. curCell.InvokePropertyChanged();
  1608. }
  1609. j = k;
  1610. break;
  1611. }
  1612. if (k == RecipeRows[loopRowId].RecipeItems.Count - 1)
  1613. {
  1614. j = k;
  1615. string reason = "Loop End 缺失";
  1616. cell.ErrInfo = reason;
  1617. cell.Background = Brushes.Pink;
  1618. Errors.Add(new Tuple<int, int, string, string>(loopRowId, k, cell.RecipeVariableDefine.FriendlyName, reason));
  1619. }
  1620. }
  1621. }
  1622. }
  1623. #endregion check loop
  1624. #region recipe parameter validation
  1625. //using (var lua = new LuaInterface.Lua())
  1626. //{
  1627. // //is special recipe?
  1628. // //bool IsSpecialRecipe = true;
  1629. // //{
  1630. // // int heaterModeRowIndex = RowVarNameDic["Heater.Mode"];
  1631. // // int aZoneSetpointIndex = RowVarNameDic["AZone.Setpoint"];
  1632. // // int bZoneSetpointIndex = RowVarNameDic["BZone.Setpoint"];
  1633. // // int cZoneSetpointIndex = RowVarNameDic["CZone.Setpoint"];
  1634. // // int dZoneSetpointIndex = RowVarNameDic.ContainsKey("DZone.Setpoint") ? RowVarNameDic["DZone.Setpoint"] : aZoneSetpointIndex;
  1635. // // for (int stepIndex = 0; stepIndex < RecipeRows[0].RecipeItems.Count; stepIndex++)
  1636. // // {
  1637. // // if (RecipeRows[heaterModeRowIndex].RecipeItems[stepIndex].Value != "CurrentControl" ||
  1638. // // RecipeRows[aZoneSetpointIndex].RecipeItems[stepIndex].Value != "0" ||
  1639. // // RecipeRows[bZoneSetpointIndex].RecipeItems[stepIndex].Value != "0" ||
  1640. // // RecipeRows[cZoneSetpointIndex].RecipeItems[stepIndex].Value != "0" ||
  1641. // // RecipeRows[dZoneSetpointIndex].RecipeItems[stepIndex].Value != "0")
  1642. // // {
  1643. // // IsSpecialRecipe = false;
  1644. // // break;
  1645. // // }
  1646. // // }
  1647. // //}
  1648. // ////set get ramp rate function
  1649. // //lua.RegisterFunction("CheckRampRate", this, GetType().GetMethod("CheckRampRate"));
  1650. // //lua.DoString(string.Format("IsProductionRecipe={0};",(!IsSpecialRecipe).ToString().ToLower()));
  1651. // for (int stepIndex = 0; stepIndex < RecipeRows[0].RecipeItems.Count; stepIndex++)
  1652. // {
  1653. // //set stepNo
  1654. // lua.DoString(string.Format("StepNo={0};", stepIndex));
  1655. // //reading var from current recipe step
  1656. // foreach (var checkVar in _checkVariables)
  1657. // {
  1658. // if (!RowVarNameDic.ContainsKey(checkVar))
  1659. // {
  1660. // System.Diagnostics.Debug.WriteLine("检查不到变量定义," + checkVar);
  1661. // continue;
  1662. // }
  1663. // try
  1664. // {
  1665. // int varId = RowVarNameDic[checkVar];
  1666. // if (RecipeRows[varId].RecipeItems[stepIndex].RecipeVariableDefine.CellType == CellType.NumInput)
  1667. // lua.DoString(string.Format("{0}={1};", RecipeRows[varId].RecipeItems[stepIndex].RecipeVariableDefine.TechnicalName.Replace(".", "_"), RecipeRows[varId].RecipeItems[stepIndex].Value));
  1668. // else
  1669. // lua.DoString(string.Format("{0}=\"{1}\";", RecipeRows[varId].RecipeItems[stepIndex].RecipeVariableDefine.TechnicalName.Replace(".", "_"), RecipeRows[varId].RecipeItems[stepIndex].Value));
  1670. // }
  1671. // catch (Exception ex)
  1672. // {
  1673. // System.Diagnostics.Debug.WriteLine("校验异常," + ex);
  1674. // }
  1675. // }
  1676. // //reading from recipe format file
  1677. // foreach (string key in _preDefinedRecipeVars.Keys)
  1678. // {
  1679. // string varValueString = _preDefinedRecipeVars[key];
  1680. // double varValue;
  1681. // if (double.TryParse(varValueString, out varValue))
  1682. // lua.DoString(string.Format("{0}={1};", key, varValue));
  1683. // else
  1684. // lua.DoString(string.Format("{0}=\"{1}\";", key, varValueString));
  1685. // }
  1686. // //do valation
  1687. // foreach (var rule in _validationRules)
  1688. // {
  1689. // lua.DoString(string.Format("if {0} then hasErr=1 else hasErr=0 end", rule.Item2));
  1690. // bool hasError = ((int)lua.GetNumber("hasErr")) == 1;
  1691. // if (hasError)
  1692. // {
  1693. // lua.DoString(string.Format("message=string.format({0});", rule.Item3));
  1694. // string reason = lua.GetString("message");
  1695. // var rowId = RowVarNameDic[rule.Item1];
  1696. // var cell = RecipeRows[rowId].RecipeItems[stepIndex];
  1697. // cell.ErrInfo = reason;
  1698. // cell.Background = Brushes.Pink;
  1699. // Errors.Add(new Tuple<int, int, string, string>(rowId, stepIndex, cell.RecipeVariableDefine.FriendlyName, reason));
  1700. // cell.InvokePropertyChanged();
  1701. // }
  1702. // }
  1703. // }
  1704. //}
  1705. #endregion recipe parameter validation
  1706. #region update material cell data
  1707. int materialRowId = -1;
  1708. for (int colId = 0; colId < RecipeRows[0].RecipeItems.Count; colId++)
  1709. {
  1710. string materialName = "";
  1711. for (int rowId = 0; rowId < RecipeRows.Count; rowId++)
  1712. {
  1713. string curMo = "";
  1714. if (materialRowId == -1 && RecipeRows[rowId].RecipeItems[colId].RecipeVariableDefine.TechnicalName == "Material")
  1715. {
  1716. materialRowId = rowId;
  1717. }
  1718. var cell = RecipeRows[rowId].RecipeItems[colId];
  1719. if (cell.RecipeVariableDefine.CellType == CellType.ReadOnlySelection && String.Compare(cell.Value, "flow", true) == 0)
  1720. {
  1721. string moName = cell.RecipeVariableDefine.TechnicalName.Split('.')[0].ToLower();
  1722. string displayName = cell.RecipeVariableDefine.FriendlyName.Replace("_", ".").Split('.')[0].ToLower();
  1723. if (moName.Contains("cp2mg_1") || displayName.Contains("cp2mg_1")) curMo = "Mg1";
  1724. else if (moName.Contains("cp2mg_2") || displayName.Contains("cp2mg_2")) curMo = "Mg2";
  1725. else if (moName.Contains("cp2mg_3") || displayName.Contains("cp2mg_3")) curMo = "Mg3";
  1726. else if (moName.Contains("cp2mg_4") || displayName.Contains("cp2mg_4")) curMo = "Mg4";
  1727. else if (moName.Contains("cp2mg") || displayName.Contains("cp2mg")) curMo = "Mg";
  1728. else if (moName.Contains("tmin") || displayName.Contains("tmin")) curMo = "In";
  1729. else if (moName.Contains("tmin_1") || displayName.Contains("tmin_1")) curMo = "In1";
  1730. else if (moName.Contains("tmin_2") || displayName.Contains("tmin_2")) curMo = "In2";
  1731. else if (moName.Contains("tmin_3") || displayName.Contains("tmin_3")) curMo = "In3";
  1732. else if (moName.Contains("tmin_4") || displayName.Contains("tmin_4")) curMo = "In4";
  1733. else if (moName.Contains("tmga") || displayName.Contains("tmga")) curMo = "TMG";
  1734. else if (moName.Contains("tmga_1") || displayName.Contains("tmga_1")) curMo = "TMG1";
  1735. else if (moName.Contains("tmga_2") || displayName.Contains("tmga_2")) curMo = "TMG2";
  1736. else if (moName.Contains("tmga_3") || displayName.Contains("tmga_3")) curMo = "TMG3";
  1737. else if (moName.Contains("tmga_4") || displayName.Contains("tmga_4")) curMo = "TMG4";
  1738. else if (moName.Contains("tega") || displayName.Contains("tega")) curMo = "TEG";
  1739. else if (moName.Contains("tega_1") || displayName.Contains("tega_1")) curMo = "TEG1";
  1740. else if (moName.Contains("tega_2") || displayName.Contains("tega_2")) curMo = "TEG2";
  1741. else if (moName.Contains("tega_3") || displayName.Contains("tega_3")) curMo = "TEG3";
  1742. else if (moName.Contains("tega_4") || displayName.Contains("tega_4")) curMo = "TEG4";
  1743. else if (moName.Contains("tmal") || displayName.Contains("tmal")) curMo = "TAl";
  1744. else if (moName.Contains("tmal_1") || displayName.Contains("tmal_1")) curMo = "TAl1";
  1745. else if (moName.Contains("tmal_2") || displayName.Contains("tmal_2")) curMo = "TAl2";
  1746. else if (moName.Contains("tmal_3") || displayName.Contains("tmal_3")) curMo = "TAl3";
  1747. else if (moName.Contains("tmal_4") || displayName.Contains("tmal_4")) curMo = "TAl4";
  1748. else if (moName.Contains("nh3source") || displayName.Contains("nh3source")) curMo = "NH3";
  1749. else if (moName.Contains("si")) curMo = "Si";
  1750. if (!string.IsNullOrEmpty(curMo))
  1751. {
  1752. if (string.IsNullOrEmpty(materialName))
  1753. materialName = curMo;
  1754. else
  1755. materialName += "|" + curMo;
  1756. }
  1757. }
  1758. }
  1759. if (materialRowId >= 0)
  1760. {
  1761. RecipeRows[materialRowId].RecipeItems[colId].Value = materialName;
  1762. RecipeRows[materialRowId].RecipeItems[colId].InvokePropertyChanged();
  1763. }
  1764. }
  1765. #endregion update material cell data
  1766. #region update column header
  1767. if (DataGridControl.Columns.Count - 1 == RecipeRows[0].RecipeItems.Count)
  1768. {
  1769. var redColHeader = (DataTemplate)DataGridControl.FindResource("columnRedTitleTemplate");
  1770. var blackColHeader = (DataTemplate)DataGridControl.FindResource("columnBlackTitleTemplate");
  1771. for (int j = 0; j < RecipeRows[0].RecipeItems.Count; j++)
  1772. {
  1773. DataGridControl.Columns[j + 1].Title = string.Format("{0}|{2}\r\n{1}", j + 1, RecipeRows[0].RecipeItems[j].Value, RecipeRows[2].RecipeItems[j].Value);
  1774. if (Errors.Find((o) => o.Item2 == j) != null)
  1775. DataGridControl.Columns[j + 1].TitleTemplate = redColHeader;
  1776. else
  1777. DataGridControl.Columns[j + 1].TitleTemplate = blackColHeader;
  1778. }
  1779. }
  1780. #endregion update column header
  1781. #region if running state, highlight current running step, move horizontal bar to current running step
  1782. if (CurrentRunningStepNo > 0 && DataGridControl.Columns.Count > 2)
  1783. {
  1784. for (int rowId = 0; rowId < RecipeRows.Count; rowId++)
  1785. {
  1786. for (int colId = 0; colId < RecipeRows[0].RecipeItems.Count; colId++)
  1787. {
  1788. var cell = RecipeRows[rowId].RecipeItems[colId];
  1789. if (colId + 1 == CurrentRunningStepNo)
  1790. {
  1791. cell.IsRunning = true;
  1792. }
  1793. else
  1794. {
  1795. cell.IsRunning = false;
  1796. }
  1797. cell.InvokePropertyChanged("IsRunning");
  1798. }
  1799. }
  1800. if (moving2RunningStepPosition)
  1801. {
  1802. Task.Factory.StartNew(() =>
  1803. {
  1804. System.Threading.Thread.Sleep(200);
  1805. DataGridControl.Dispatcher.Invoke(new Action(() =>
  1806. {
  1807. double singleWidth = DataGridControl.Columns[1].Width;
  1808. double horizontalOffset = (CurrentRunningStepNo - 2) * singleWidth;
  1809. if (DataGridControl.ScrollViewer != null)
  1810. {
  1811. if (horizontalOffset > DataGridControl.ScrollViewer.ScrollableWidth)
  1812. horizontalOffset = DataGridControl.ScrollViewer.ScrollableWidth;
  1813. if (horizontalOffset < 0)
  1814. horizontalOffset = 0;
  1815. DataGridControl.ScrollViewer.ScrollToHorizontalOffset(horizontalOffset);
  1816. }
  1817. }));
  1818. });
  1819. }
  1820. }
  1821. #endregion if running state, highlight current running step, move horizontal bar to current running step
  1822. //calc recipe time
  1823. CalcRecipeTime();
  1824. //invoke property
  1825. InvokePropertyChanged("Errors");
  1826. }
  1827. catch (Exception ex)
  1828. {
  1829. MessageBox.Show("工艺程序校验出错!\r\n\r\n" + ex.Message, "出错", MessageBoxButton.OK, MessageBoxImage.Error);
  1830. System.Diagnostics.Debug.WriteLine(ex.Message);
  1831. }
  1832. }
  1833. /// <summary>
  1834. /// reload datagrid content
  1835. /// </summary>
  1836. private void RefreshDataGrid()
  1837. {
  1838. try
  1839. {
  1840. //generate columns in Grid
  1841. DataGridControl.CurrentColumn = null;
  1842. if (DataGridControl.Columns.Count > 0)
  1843. DataGridControl.Columns.Clear();
  1844. var template = (DataTemplate)DataGridControl.FindResource("CustomTemplate");
  1845. var rowTemplate = (DataTemplate)DataGridControl.FindResource("RowHeadTemplate");
  1846. DataGridControl.Columns.Add(new Xceed.Wpf.DataGrid.Column()
  1847. {
  1848. Width = 140,
  1849. Title = " ",
  1850. FieldName = ".",
  1851. CellContentTemplate = rowTemplate
  1852. });
  1853. var cellEditor = DataGridControl.DefaultCellEditors[typeof(SmartCellData)];// DefaultCellEditorSelector.SelectCellEditor(typeof(SmartCellData));
  1854. for (int index = 0; index < RecipeRows[0].RecipeItems.Count; index++)
  1855. {
  1856. //var col = new Xceed.Wpf.DataGrid.Column();
  1857. DataGridControl.Columns.Add(new Xceed.Wpf.DataGrid.Column()
  1858. {
  1859. Title = string.Format("【{0}】\r\n{1}", index + 1, RecipeRows[0].RecipeItems[index].Value),
  1860. FieldName = string.Format("RecipeItems[{0}]", index),
  1861. CellContentTemplate = template,
  1862. AllowSort = false,
  1863. Width = 120,
  1864. MaxWidth = 120,
  1865. CellEditor = cellEditor
  1866. });
  1867. }
  1868. InvokePropertyChanged("RecipeRows");
  1869. InvokePropertyChanged("RecipeHead");
  1870. }
  1871. catch (Exception ex)
  1872. {
  1873. System.Diagnostics.Debug.WriteLine(ex.Message);
  1874. }
  1875. }
  1876. /// <summary>
  1877. /// calc recipe total time
  1878. /// </summary>
  1879. private void CalcRecipeTime()
  1880. {
  1881. int timeStepRowId = -1;
  1882. int loopStepRowId = -1;
  1883. for (int i = 0; i < RecipeRows.Count; i++)
  1884. {
  1885. if (RecipeRows[i].TechnicalName == "Time")
  1886. timeStepRowId = i;
  1887. if (RecipeRows[i].TechnicalName == "Loop")
  1888. loopStepRowId = i;
  1889. if (loopStepRowId != -1 && timeStepRowId != -1)
  1890. break;
  1891. }
  1892. TimeSpan tspan = new TimeSpan();
  1893. for (int stepNo = 0; stepNo < RecipeRows[timeStepRowId].RecipeItems.Count; stepNo++)
  1894. {
  1895. string loopStr = RecipeRows[loopStepRowId].RecipeItems[stepNo].Value;
  1896. bool isLoopStart = Regex.IsMatch(loopStr, @"^Loop\x20\d+$");
  1897. if (isLoopStart)
  1898. {
  1899. int loopNum = int.Parse(loopStr.ToLower().Replace("loop", "").Replace(" ", ""));
  1900. TimeSpan ts = new TimeSpan();
  1901. for (int innerStepNo = stepNo; innerStepNo < RecipeRows[timeStepRowId].RecipeItems.Count; innerStepNo++)
  1902. {
  1903. loopStr = RecipeRows[loopStepRowId].RecipeItems[innerStepNo].Value;
  1904. stepNo = innerStepNo;
  1905. string timeDuration = RecipeRows[timeStepRowId].RecipeItems[innerStepNo].Value;
  1906. string[] timeArr = timeDuration.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  1907. if (timeArr.Length == 3)
  1908. {
  1909. int h, mi, s;
  1910. if (int.TryParse(timeArr[0], out h) && int.TryParse(timeArr[1], out mi) && int.TryParse(timeArr[2], out s))
  1911. {
  1912. var tt = new TimeSpan(h, mi, s);
  1913. ts += tt;
  1914. }
  1915. }
  1916. bool isLoopEnd = Regex.IsMatch(loopStr, @"^Loop End$");
  1917. if (isLoopEnd)
  1918. {
  1919. tspan += new TimeSpan(ts.Ticks * loopNum);
  1920. break;
  1921. }
  1922. }
  1923. }
  1924. else
  1925. {
  1926. string timeDuration = RecipeRows[timeStepRowId].RecipeItems[stepNo].Value;
  1927. string[] timeArr = timeDuration.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
  1928. if (timeArr.Length == 3)
  1929. {
  1930. int h, mi, s;
  1931. if (int.TryParse(timeArr[0], out h) && int.TryParse(timeArr[1], out mi) && int.TryParse(timeArr[2], out s))
  1932. {
  1933. var ts = new TimeSpan(h, mi, s);
  1934. tspan += ts;
  1935. }
  1936. }
  1937. }
  1938. }
  1939. RecipeInfo = string.Format("共{0}步,总时间{1}:{2}:{3}", RecipeRows[0].RecipeItems.Count, (int)tspan.TotalHours, tspan.Minutes.ToString("00"), tspan.Seconds.ToString("00"));
  1940. InvokePropertyChanged("RecipeInfo");
  1941. }
  1942. #region INotifyPropertyChanged
  1943. public event PropertyChangedEventHandler PropertyChanged;
  1944. public void InvokePropertyChanged(string propertyName)
  1945. {
  1946. if (PropertyChanged != null)
  1947. {
  1948. PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
  1949. }
  1950. }
  1951. #endregion INotifyPropertyChanged
  1952. }
  1953. public class RecipeRow
  1954. {
  1955. private ObservableCollection<SmartCellData> _recipeItems = new ObservableCollection<SmartCellData>();
  1956. public RecipeRow(params SmartCellData[] vars)
  1957. {
  1958. foreach (var var in vars)
  1959. _recipeItems.Add(var);
  1960. }
  1961. public string CatalogName { get; set; }
  1962. public string FriendlyName { get; set; }
  1963. public string TechnicalName { get; set; }
  1964. public ObservableCollection<SmartCellData> RecipeItems
  1965. {
  1966. get { return _recipeItems; }
  1967. set { _recipeItems = value; }
  1968. }
  1969. }
  1970. /// <summary>
  1971. /// Recipe head
  1972. /// </summary>
  1973. public class RecipeHead
  1974. {
  1975. public string RecipeVariation { get; set; }
  1976. public string CreationTime { get; set; }
  1977. public string LastRevisionTime { get; set; }
  1978. public string CreatedBy { get; set; }
  1979. public string LastModifiedBy { get; set; }
  1980. public string PressureMode { get; set; }
  1981. public string Description { get; set; }
  1982. public string BasePressure
  1983. {
  1984. get; set;
  1985. }
  1986. public string PumpDownLimit
  1987. {
  1988. get; set;
  1989. }
  1990. public string PurgeActive
  1991. {
  1992. get; set;
  1993. }
  1994. public string NotToPurgeOrVent
  1995. {
  1996. get; set;
  1997. }
  1998. public string Barcode
  1999. {
  2000. get; set;
  2001. }
  2002. public string Chamber1Temp
  2003. {
  2004. get; set;
  2005. }
  2006. public string Chamber2Temp
  2007. {
  2008. get; set;
  2009. }
  2010. public string PumpingPinState
  2011. {
  2012. get; set;
  2013. }
  2014. public string VentingPinState
  2015. {
  2016. get; set;
  2017. }
  2018. public string PinDownPressure
  2019. {
  2020. get; set;
  2021. }
  2022. }
  2023. public class EndPointConfigItem : INotifyPropertyChanged
  2024. {
  2025. public event PropertyChangedEventHandler PropertyChanged;
  2026. public void InvokePropertyChanged(string propertyName)
  2027. {
  2028. if (PropertyChanged != null)
  2029. {
  2030. PropertyChanged.Invoke(this, new PropertyChangedEventArgs(propertyName));
  2031. }
  2032. }
  2033. public string ExposureTime { get; set; }
  2034. public string WaveLengthA { get; set; }
  2035. public string BinningA { get; set; }
  2036. public string WaveLengthB { get; set; }
  2037. public string BinningB { get; set; }
  2038. public string WaveLengthC { get; set; }
  2039. public string BinningC { get; set; }
  2040. public string WaveLengthD { get; set; }
  2041. public string BinningD { get; set; }
  2042. public string Fd { get; set; }
  2043. public string PrefilterTime { get; set; }
  2044. public string PostfilterTime { get; set; }
  2045. public string AlgorithmType { get; set; }
  2046. public string Criteria { get; set; }
  2047. public string DelayTime { get; set; }
  2048. public string ValidationTime { get; set; }
  2049. public string ValidationValue { get; set; }
  2050. public string TimeWindow { get; set; }
  2051. public string MinimalTime { get; set; }
  2052. public string PostponeTime { get; set; }
  2053. public bool Control { get; set; }
  2054. public bool Normalization { get; set; }
  2055. public bool EnablePostponePercent { get; set; }
  2056. public bool EnableCriterialPercent { get; set; }
  2057. public bool EnableEventTrigger { get; set; }
  2058. public bool IsFaultIfNoTrigger { get; set; }
  2059. public string ToValue()
  2060. {
  2061. return
  2062. $@"ExposureTime={ExposureTime};WaveLengthA={WaveLengthA};BinningA={BinningA};WaveLengthB={WaveLengthB};" +
  2063. $@"BinningB={BinningB};WaveLengthC={WaveLengthC};BinningC={BinningC};WaveLengthD={WaveLengthD};BinningD={BinningD};Fd={Fd};" +
  2064. $@"PrefilterTime={PrefilterTime};PostfilterTime={PostfilterTime};AlgorithmType={AlgorithmType};Criteria={Criteria};DelayTime={DelayTime};ValidationTime={ValidationTime};" +
  2065. $@"ValidationValue={ValidationValue};TimeWindow={TimeWindow};MinimalTime={MinimalTime};PostponeTime={PostponeTime};Control={Control};Normalization={Normalization};" +
  2066. $@"EnablePostponePercent={EnablePostponePercent};EnableCriterialPercent={EnableCriterialPercent};EnableEventTrigger={EnableEventTrigger};IsFaultIfNoTrigger={IsFaultIfNoTrigger};"
  2067. ;
  2068. }
  2069. public void SetValue(string config)
  2070. {
  2071. if (string.IsNullOrEmpty(config))
  2072. return;
  2073. string[] items = config.Split(';');
  2074. foreach (var item in items)
  2075. {
  2076. if (string.IsNullOrEmpty(item))
  2077. continue;
  2078. string[] pairs = item.Split('=');
  2079. if (pairs.Length != 2)
  2080. continue;
  2081. Parallel.ForEach(this.GetType().GetProperties(),
  2082. property =>
  2083. {
  2084. PropertyInfo pi = (PropertyInfo) property;
  2085. if (pi.Name == pairs[0])
  2086. {
  2087. try
  2088. {
  2089. var convertedValue = Convert.ChangeType(pairs[1], pi.PropertyType);
  2090. var originValue = Convert.ChangeType(pi.GetValue(this, null), pi.PropertyType);
  2091. if (originValue != convertedValue)
  2092. {
  2093. pi.SetValue(this, convertedValue, null);
  2094. }
  2095. }
  2096. catch (Exception)
  2097. {
  2098. }
  2099. }
  2100. });
  2101. }
  2102. }
  2103. }
  2104. }