using Aitex.Core.RT.Log; using Aitex.Core.UI.View.Common; using Caliburn.Micro.Core; using MECF.Framework.Common.DataCenter; using MECF.Framework.Common.Equipment; using Microsoft.VisualBasic; using Microsoft.Win32; using Prism.Commands; using Prism.Mvvm; using Prism.Regions; using Prism.Services.Dialogs; using RecipeEditorLib.DGExtension.CustomColumn; using RecipeEditorLib.RecipeModel.Params; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.IO; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Xml; using Venus_Core; using Venus_MainPages.PMs; using Venus_MainPages.Sequence; using Venus_MainPages.Views; using WPF.Themes.UserControls; namespace Venus_MainPages.ViewModels { internal class SequenceViewModel:BindableBase { #region 私有字段 //private IUiSequenceManager m_uiSequenceManager = new UiSequenceManager(); private SequenceView m_SequenceView; private bool m_IsPageLoad = true; private SequenceData m_CurrentSequence; private SequenceColumnBuilder columnBuilder = new SequenceColumnBuilder(); private SequenceDataProvider provider = new SequenceDataProvider(new UiSequenceManager()); #endregion #region 命令 private DelegateCommand m_LoadedCommand; public DelegateCommand LoadedCommand => m_LoadedCommand ?? (m_LoadedCommand = new DelegateCommand(OnLoaded)); private DelegateCommand m_AddStepCommand; public DelegateCommand AddStepCommand => m_AddStepCommand ?? (m_AddStepCommand = new DelegateCommand(AddStep)); private DelegateCommand m_InsertCommand; public DelegateCommand InsertCommand => m_InsertCommand ?? (m_InsertCommand = new DelegateCommand(InsertStep)); private DelegateCommand m_CopyCommand; public DelegateCommand CopyCommand => m_CopyCommand ?? (m_CopyCommand = new DelegateCommand(CopyStep)); private DelegateCommand m_PasteCommand; public DelegateCommand PasteCommand => m_PasteCommand ?? (m_PasteCommand = new DelegateCommand(PasteStep)); private DelegateCommand m_DeleteStepCommand; public DelegateCommand DeleteStepCommand => m_DeleteStepCommand ?? (m_DeleteStepCommand = new DelegateCommand(DeleteStep)); private DelegateCommand m_ReloadSequenceCommand; public DelegateCommand ReloadSequenceCommand => m_ReloadSequenceCommand ?? (m_ReloadSequenceCommand = new DelegateCommand(ReloadSequence)); private DelegateCommand m_SaveSequenceCommand; public DelegateCommand SaveSequenceCommand => m_SaveSequenceCommand ?? (m_SaveSequenceCommand = new DelegateCommand(SaveSequence)); private DelegateCommand m_SelectRecipeCommand; public DelegateCommand SelectRecipeCommand => m_SelectRecipeCommand ?? (m_SelectRecipeCommand = new DelegateCommand(SelectRecipe)); private DelegateCommand m_TreeSelectChangedCommand; public DelegateCommand TreeSelectChangedCommand => m_TreeSelectChangedCommand ?? (m_TreeSelectChangedCommand = new DelegateCommand(TreeSelectChanged)); private DelegateCommand m_TreeRightMouseDownCommand; public DelegateCommand TreeRightMouseDownCommand => m_TreeRightMouseDownCommand ?? (m_TreeRightMouseDownCommand = new DelegateCommand(TreeRightMouseDown)); private DelegateCommand m_NewSequenceCommand; public DelegateCommand NewSequenceCommand => m_NewSequenceCommand ?? (m_NewSequenceCommand = new DelegateCommand(NewSequence)); private DelegateCommand m_RenameCommand; public DelegateCommand RenameCommand => m_RenameCommand ?? (m_RenameCommand = new DelegateCommand(RenameSequence)); private DelegateCommand m_DeleteCommand; public DelegateCommand DeleteSequenceCommand => m_DeleteCommand ?? (m_DeleteCommand = new DelegateCommand(DeleteSequence)); private DelegateCommand m_SaveAsCommand; public DelegateCommand SaveAsCommand => m_SaveAsCommand ?? (m_SaveAsCommand = new DelegateCommand(SaveAsSequence)); #endregion #region 属性 ObservableCollection m_Files = new ObservableCollection(); public ObservableCollection Files { get { return m_Files; } set { SetProperty(ref m_Files, value); } } private string m_SequenceName = String.Empty; public string SequenceName { get { return m_SequenceName; } set { if (value == m_SequenceName) return; SetProperty(ref m_SequenceName, value); ApplyFilter(); } } public SequenceData CurrentSequence { get { return m_CurrentSequence; } set { SetProperty(ref m_CurrentSequence, value); } } public FileNode CurrentFileNode { get; private set; } public ObservableCollection Columns { get; private set; } #endregion #region page_load private void OnLoaded(Object sequenceView) { if (m_IsPageLoad) { m_IsPageLoad = false; GetFiles(provider.GetSequenceNameList()); this.CurrentSequence = new SequenceData(); this.Columns = this.columnBuilder.Build(); SequenceColumnBuilder.ApplyTemplate((UserControl)sequenceView, this.Columns); m_SequenceView = sequenceView as SequenceView; this.Columns.Apply((c) => { c.Header = c; m_SequenceView.dgCustom.Columns.Add(c); }); m_SequenceView.dgCustom.ItemsSource = CurrentSequence.Steps; if (Files.Count > 0) { this.CurrentFileNode = this.Files[0]; this.SelectDefault(this.CurrentFileNode); } } } private void GetFiles(List names) { Files = new ObservableCollection(RecipeSequenceTreeBuilder.GetFiles("", names)); } #endregion #region tree action public void NewSequence() { InputFileNameDialogView dialog = new InputFileNameDialogView("Input New Sequence Name") { Owner = Application.Current.MainWindow }; if (dialog.ShowDialog() == true) { string fullpath = dialog.FileName; if (this.CurrentFileNode.IsFile) fullpath = (string.IsNullOrEmpty(this.CurrentFileNode.Parent.FullPath) ? dialog.FileName : this.CurrentFileNode.Parent.FullPath + "\\" + dialog.FileName); else fullpath = (string.IsNullOrEmpty(this.CurrentFileNode.FullPath) ? dialog.FileName : this.CurrentFileNode.FullPath + "\\" + dialog.FileName); if (fullpath.Length > 25) { WPFMessageBox.ShowError("SequenceName Length can not over 25"); return; } if (string.IsNullOrEmpty(fullpath)) { MessageBox.Show("SequenceName cannot be null or empty!"); return; } if (this.IsExist(fullpath)) { MessageBox.Show("Sequence already existed!"); } else { SequenceData sequence = new SequenceData(); sequence.Name = fullpath; sequence.Creator = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; ; sequence.CreateTime = DateTime.Now; sequence.Revisor = sequence.Creator; sequence.ReviseTime = DateTime.Now; sequence.Description = string.Empty; if (this.Save(sequence)) { this.CurrentSequence.Name = sequence.Name; this.CurrentSequence.Creator = sequence.Creator; this.CurrentSequence.CreateTime = sequence.CreateTime; this.CurrentSequence.Revisor = sequence.Revisor; this.CurrentSequence.ReviseTime = sequence.ReviseTime; this.CurrentSequence.Description = sequence.Description; this.CurrentSequence.Steps.Clear(); FileNode file = new FileNode(); file.Name = dialog.FileName; file.FullPath = this.CurrentSequence.Name; file.IsFile = true; file.Parent = this.CurrentFileNode.IsFile ? this.CurrentFileNode.Parent : this.CurrentFileNode; if (this.CurrentFileNode.IsFile) this.CurrentFileNode.Parent.Files.Insert(this.FindInsertPosition(this.CurrentFileNode.Parent.Files), file); else this.CurrentFileNode.Files.Insert(this.FindInsertPosition(this.CurrentFileNode.Files), file); } } } } public void RenameSequence() { if (this.CurrentFileNode.IsFile) { InputFileNameDialogView dialog = new InputFileNameDialogView("Rename Sequence") { Owner = Application.Current.MainWindow }; dialog.FileName = this.CurrentFileNode.Name; if (dialog.ShowDialog() == true) { string fullpath = this.CurrentFileNode.Parent.FullPath == "" ? dialog.FileName : this.CurrentFileNode.Parent.FullPath + "\\" + dialog.FileName; if (fullpath.Length > 25) { WPFMessageBox.ShowError("SequenceName Length can not over 25"); return; } if (string.IsNullOrEmpty(fullpath)) { MessageBox.Show("SequenceName cannot be null or empty!"); return; } if (this.IsExist(fullpath)) { MessageBox.Show("Sequence already existed!"); } else { this.CurrentSequence.Revisor = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; ; this.CurrentSequence.ReviseTime = DateTime.Now; if (this.provider.Rename(this.CurrentSequence.Name, fullpath)) { this.CurrentFileNode.Name = dialog.FileName; this.CurrentFileNode.FullPath = fullpath; this.CurrentSequence.Name = fullpath; } else MessageBox.Show("Rename failed!"); } } } } public void DeleteSequence() { if (this.CurrentFileNode.IsFile) { if (WPFMessageBox.ShowQuestion($"Do you want to delete this {this.CurrentSequence.Name}?", "删除后无法恢复!!!") == MessageBoxResult.Yes) { if (this.provider.Delete(this.CurrentSequence.Name)) { this.CurrentFileNode.Parent.Files.Remove(this.CurrentFileNode); } } } } public void SaveAsSequence() { if (this.CurrentFileNode.IsFile) { InputFileNameDialogView dialog = new InputFileNameDialogView("Input New Sequence Name") { Owner = Application.Current.MainWindow }; if (dialog.ShowDialog() == true) { string fullpath = (this.CurrentFileNode.Parent.FullPath == "" ? dialog.FileName : this.CurrentFileNode.Parent.FullPath + "\\" + dialog.FileName); if (string.IsNullOrEmpty(fullpath)) { MessageBox.Show("SequenceName cannot be null or empty!"); return; } if (this.IsExist(fullpath)) { MessageBox.Show("Sequence already existed!"); } else { this.CurrentSequence.Revisor = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; ; this.CurrentSequence.ReviseTime = DateTime.Now; string tempname = this.CurrentSequence.Name; this.CurrentSequence.Name = fullpath; if (this.provider.SaveAs(fullpath, this.CurrentSequence)) { FileNode node = new FileNode(); node.Parent = this.CurrentFileNode.Parent; node.Name = dialog.FileName; node.FullPath = fullpath; node.IsFile = true; this.CurrentFileNode.Parent.Files.Add(node); } else { this.CurrentSequence.Name = tempname; MessageBox.Show("SaveAs failed!"); } } } } } public void TreeSelectChanged(object selectItem) { FileNode file = (FileNode)selectItem; if (file != null && file.IsFile) { this.LoadData(file.FullPath); this.CurrentFileNode = file; } else { this.ClearData(); } } private TreeViewItem GetParentObjectEx(DependencyObject obj) where TreeViewItem : FrameworkElement { DependencyObject parent = VisualTreeHelper.GetParent(obj); while (parent != null) { if (parent is TreeViewItem) { return (TreeViewItem)parent; } parent = VisualTreeHelper.GetParent(parent); } return null; } public void TreeRightMouseDown(MouseButtonEventArgs e) { if (e != null) { var item = GetParentObjectEx(e.OriginalSource as DependencyObject) as TreeViewItem; if (item != null) { item.Focus(); } } } #endregion #region sequence action public void AddStep() { this.CurrentSequence.Steps.Add(CurrentSequence.CreateStep(this.Columns)); int index = 1; foreach (ObservableCollection parameters in this.CurrentSequence.Steps) { (parameters[0] as StepParam).Value = index.ToString(); index++; } } public void InsertStep() { int index = -1; bool found = false; for (var i = 0; i < this.CurrentSequence.Steps.Count; i++) { if (this.CurrentSequence.Steps[i][0] is StepParam && ((StepParam)this.CurrentSequence.Steps[i][0]).Checked) { index = i; found = true; break; } } if (found) { this.CurrentSequence.Steps.Insert(index, this.CurrentSequence.CreateStep(this.Columns)); index = 1; foreach (ObservableCollection parameters in this.CurrentSequence.Steps) { (parameters[0] as StepParam).Value = index.ToString(); index++; } } } private ObservableCollection> copySteps = new ObservableCollection>(); public void CopyStep() { this.copySteps.Clear(); for (var i = 0; i < this.CurrentSequence.Steps.Count; i++) { if (this.CurrentSequence.Steps[i][0] is StepParam && ((StepParam)this.CurrentSequence.Steps[i][0]).Checked) { this.copySteps.Add(this.CurrentSequence.CloneStep(this.Columns, this.CurrentSequence.Steps[i])); } } } public void PasteStep() { if (this.copySteps.Count > 0) { if (this.CurrentSequence.Steps.Count > 0) { for (var i = 0; i < this.CurrentSequence.Steps.Count; i++) { if (this.CurrentSequence.Steps[i][0] is StepParam && ((StepParam)this.CurrentSequence.Steps[i][0]).Checked) { for (var copyindex = 0; copyindex < this.copySteps.Count; copyindex++) { this.CurrentSequence.Steps.Insert(i, this.CurrentSequence.CloneStep(this.Columns, this.copySteps[copyindex])); i++; } break; } } } else { for (var copyindex = 0; copyindex < this.copySteps.Count; copyindex++) { this.CurrentSequence.Steps.Insert(copyindex, this.CurrentSequence.CloneStep(this.Columns, this.copySteps[copyindex])); } } SetStepIndex(); } } public void DeleteStep() { List> steps = this.CurrentSequence.Steps.ToList(); for (var i = 0; i < steps.Count; i++) { if (steps[i][0] is StepParam && ((StepParam)steps[i][0]).Checked) { this.CurrentSequence.Steps.Remove(steps[i]); } } SetStepIndex(); } public void ReloadSequence() { this.LoadData(this.CurrentSequence.Name); } public void SelectRecipe(object select) { PathFileParam param = (PathFileParam)select; NewRecipeSequenceSelectView dialog = new NewRecipeSequenceSelectView(param.Value) { Owner = Application.Current.MainWindow }; dialog.Title = "Select Recipe"; var dataContext = new RecipeSequenceSelectViewModel(); dialog.DataContext = dataContext; ObservableCollection parameters = param.Parent; PositionParam posParam = null; for (var index = 0; index < parameters.Count; index++) { if (parameters[index] is PositionParam) { posParam = parameters[index] as PositionParam; break; } } List lstFiles=new List(); string moduleName=param.Name.Substring(0,3); var Clean = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == moduleName && x.Split('\\')[1] == "Clean").ToList();//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}"); Clean.Add($"{moduleName}\\Clean\\"); var Process = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == moduleName && x.Split('\\')[1] == "Process").ToList(); //Process.Add($"{moduleName}\\Process\\"); dataContext.Files.AddRange(new ObservableCollection(RecipeSequenceTreeBuilder.GetFiles("", Clean))); dataContext.Files.AddRange(new ObservableCollection(RecipeSequenceTreeBuilder.GetFiles("", Process))); //if (param.Name.Contains("PMA")) //{ //} //else if (param.Name.Contains("PMB")) //{ // lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMB" && x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}"); // lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMB" && x.Split('\\')[1] == "Process").ToList(); //} //else if (param.Name.Contains("PMC")) //{ // lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMC" && x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}"); // lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMC" && x.Split('\\')[1] == "Process").ToList(); //} //else if (param.Name.Contains("PMD")) //{ // lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMD" && x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}"); // lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[0] == "PMD" && x.Split('\\')[1] == "Process").ToList(); //} //else //{ // lstFiles.AddRange(provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[1] == "Clean").ToList());//m_uiSequenceManager.GetRecipesByPath($"{param.PrefixPath}"); // lstFiles = provider.GetRecipesByPath($"{param.PrefixPath}").Where(x => x.Split('\\')[1] == "Process").ToList(); //} //if (param.Name.Contains("Clean")) //{ //} //else //{ //} //lstFiles.ForEach(x => //{ // dataContext.Files.Add(new ObservableCollection(RecipeSequenceTreeBuilder.GetFiles("", x))); //}); //dataContext.Files = new ObservableCollection(RecipeSequenceTreeBuilder.GetFiles("", lstFiles)); if (dialog.ShowDialog() == true) { //param.Value = dialog.FullPath; //param.Value = $"{param.PrefixPath}\\" + dialog.FullPath; //param.FileName = param.Value; string path = dialog.FullPath; //int index = path.LastIndexOf("\\"); //if (index > -1) //{ // param.FileName = path.Substring(index + 1); // param.Value = path.Substring(index + 1); //} //else //{ // param.FileName = path; // param.Value = path; //} param.FileName =path; param.Value = path; param.IsSaved = false; } } public void SaveSequence() { this.Save(this.CurrentSequence); } private void SetStepIndex() { int index = 1; foreach (ObservableCollection parameters in this.CurrentSequence.Steps) { (parameters[0] as StepParam).Value = index.ToString(); index++; } } #endregion #region private private void ApplyFilter() { var sequenceList = provider.GetSequenceNameList() ?? new List(); GetFiles(sequenceList.Where(p => { return string.IsNullOrWhiteSpace(SequenceName) || p.IndexOf(SequenceName, StringComparison.OrdinalIgnoreCase) > -1; }).ToList()); } private void ClearData() { this.CurrentSequence.Steps.Clear(); this.CurrentSequence.Name = string.Empty; this.CurrentSequence.Description = string.Empty; } private bool Save(SequenceData seq) { bool result = false; if (string.IsNullOrEmpty(seq.Name)) { MessageBox.Show("Sequence name can't be empty"); return false; } string ruleCheckMessage = null; if (!ValidateSequenceRules(seq, ref ruleCheckMessage)) { MessageBox.Show(string.Format($"{seq.Name} rules check failed, don't allow to save: {ruleCheckMessage}")); return false; } seq.Revisor = Venus_MainPages.Unity.GlobalUser.Instance.User.Name; seq.ReviseTime = DateTime.Now; result = this.provider.Save(seq); if (result) { foreach (ObservableCollection parameters in seq.Steps) { parameters.Apply(param => param.IsSaved = true); } } else MessageBox.Show("Save failed!"); return result; } private bool ValidateSequenceRules(SequenceData currentSequence, ref string ruleCheckMessage) { int preIndex = -1; for (var i = 0; i < currentSequence.Steps.Count; i++) { var stepInfo = currentSequence.Steps[i]; if (string.IsNullOrEmpty((stepInfo[1] as PositionParam).Value)) { ruleCheckMessage = $"Step{(stepInfo[0] as StepParam).Value}, Position Is Empty"; return false; } if ((stepInfo[1] as PositionParam).Value == "LL") { if (preIndex != -1 && (i - preIndex) == 1) { ruleCheckMessage = $"Step{(stepInfo[0] as StepParam).Value}, The LL is set around the pm "; return false; } preIndex = i; } } return true; } private XmlAttribute CreateAttribute(XmlNode node, string attributeName, string value) { try { XmlDocument doc = node.OwnerDocument; XmlAttribute attr = null; attr = doc.CreateAttribute(attributeName); attr.Value = value; node.Attributes.SetNamedItem(attr); return attr; } catch (Exception err) { string desc = err.Message; return null; } } private void SelectDefault(FileNode node) { if (!node.IsFile) { if (node.Files.Count > 0) { foreach (FileNode file in node.Files) { if (file.IsFile) { this.TreeSelectChanged(file); //break; } } } } } public void TreeSelectChanged(FileNode file) { if (file != null && file.IsFile) { //if (this.IsChanged) // if (MessageBox.Show("This sequence is changed,do you want to save it?", "", MessageBoxButton.OKCancel) == MessageBoxResult.OK) // this.Save(this.CurrentSequence); this.LoadData(file.FullPath); this.CurrentFileNode = file; } else { //this.ClearData(); //this.editMode = EditMode.None; this.CurrentSequence.Steps.Clear(); } //this.UpdateView(); } private void LoadData(string newSeqName) { SequenceData Sequence = this.provider.GetSequenceByName(this.Columns, newSeqName); this.CurrentSequence.Name = Sequence.Name; this.CurrentSequence.Creator = Sequence.Creator; this.CurrentSequence.CreateTime = Sequence.CreateTime; this.CurrentSequence.Revisor = Sequence.Revisor; this.CurrentSequence.ReviseTime = Sequence.ReviseTime; this.CurrentSequence.Description = Sequence.Description; this.CurrentSequence.Steps.Clear(); Sequence.Steps.ToList().ForEach(step => this.CurrentSequence.Steps.Add(step)); //int index = 1; //foreach (ObservableCollection parameters in this.CurrentSequence.Steps) //{ // (parameters[0] as StepParam).Value = index.ToString(); // index++; // foreach (var para in parameters) // { // var pathFile = para as PathFileParam; // if (pathFile != null) // { // pathFile.Value = pathFile.Value.Replace($"{pathFile.PrefixPath}\\", ""); // } // } //} //this.IsSavedDesc = true; //this.NotifyOfPropertyChange("IsSavedDesc"); //this.editMode = EditMode.Normal; } private bool IsExist(string sequencename) { bool existed = false; FileNode filenode = this.CurrentFileNode.IsFile ? this.CurrentFileNode.Parent : this.CurrentFileNode; for (var index = 0; index < filenode.Files.Count; index++) { if (filenode.Files[index].FullPath.ToLower() == sequencename.ToLower()) { existed = true; break; } } return existed; } private int FindInsertPosition(ObservableCollection files) { int pos = -1; if (files.Count == 0) pos = 0; else { bool foundfolder = false; for (var index = 0; index < files.Count; index++) { if (!files[index].IsFile) { foundfolder = true; pos = index; break; } } if (!foundfolder) pos = files.Count; } return pos; } #endregion } }