using log4net; using PdmSwPlugin.Commmon.Util.UI; using PdmSwPlugin.Common.Util; using PdmSwPlugin.Common.Util.Http; using PdmSwPlugin.PropertySetting.Interface; using SolidWorks.Interop.sldworks; using SolidWorks.Interop.swconst; using System; using System.Collections.Generic; using System.ComponentModel; using System.Net.Http; using System.Runtime.CompilerServices; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using PdmSwPlugin.Common.Interface; using PdmSwPlugin.Common; using PdmSwPlugin.PropertySetting.Entity; using PdmSwPlugin.PropertySetting.Panel; using System.Windows.Threading; using PdmSwPlugin.Common.Setting; using System.IO; using System.Runtime.InteropServices; namespace PdmSwPlugin.PropertySetting { /// /// CommonSettingControl.xaml 的交互逻辑 /// [PdmSwPlugin(Title = "属性设置")] public partial class SettingControl : UserControl, ISwAppSetter, INotifyPropertyChanged , IActiveDocChangeHandler, ITabControlSelectionChangeHandler { private static ILog Logger = LogManager.GetLogger("PropertySetting"); #region 不能公用的东西,真有你的啊C# public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string name) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name)); } public void RaiseAndSetIfChanged(ref T old, T @new, [CallerMemberName] string propertyName = null) { old = @new; if (propertyName != null) { RaisePropertyChanged(propertyName); } } #endregion public readonly Dictionary controlCache = new Dictionary(); #region 属性 public SldWorks SwApp { get; private set; } /// /// 激活的文档 /// public ModelDoc2 activeDoc { set; get; } /// /// 上次读取的文档 /// public ModelDoc2 LastReadDoc { get; set; } /// /// 当前读取的文档 /// public ModelDoc2 ReadDoc { get; set; } /// /// 当前读取的组件 /// public Component2 ReadComponent { get; set; } private HttpClient Client { get; set; } Dictionary settings; #endregion #region UI绑定 private string _readDocPath; public string ReadDocPath { get => _readDocPath; set => RaiseAndSetIfChanged(ref _readDocPath, value); } #endregion private HttpClientCreator clientCreator { get; set; } private UserControl ActiveOpter { get; set; } public SettingControl() { clientCreator = new HttpClientCreator(new HttpConfig(PluginSetting.Instance.BaseAddress)); InitializeComponent(); DataContext = this; } public SettingControl(SldWorks SwApp) : this() { this.SwApp = SwApp; } public void InitPropertyData() { if (Client == null) { Client = clientCreator.GetClient(); } DefaultPanel defaultPanel = new DefaultPanel(); controlCache.Add("default", defaultPanel); JgjPartPanel jgjPart = new JgjPartPanel(); controlCache.Add("jgjPart", jgjPart); JgjModulePanel jgjModule = new JgjModulePanel(); controlCache.Add("jgjModule", jgjModule); var stPart = new StandardPartPanel(); controlCache.Add("standardPart", stPart); var stModule = new StandardModulePanel(); controlCache.Add("standardModule", stModule); LoadComboxItemSource(); Refresh_Click(null, null); } private void Jgj_SinglePropertyChanged(object sender, string name, object value) { // CustomPropertyUtil.SetCustomProperties(ReadDoc, name, (string)value); } /// /// 从服务器加载各种选项 /// private void LoadComboxItemSource() { try { Result> res = Client.GetSyncAction>("design/rule/openApi/test"); Dictionary datas = res.HandleResult(); settings = datas; foreach (var key in controlCache.Keys) { (controlCache[key] as IPropertyOpt).SetSettings(settings); } } catch (Exception ex) { Logger.Error("Request Jgj properties failed.", ex); this.Error($"请求加工件属性失败!{ex.Message}"); } } private void UpdateActiveDoc() { if (activeDoc != null) { DetachDocNotify(activeDoc); } activeDoc = SwApp.ActiveDoc; if (activeDoc != null) { AttachDocNotify(activeDoc); int docType = activeDoc.GetType(); if (docType == (int)swDocumentTypes_e.swDocASSEMBLY) { activeDoc.ClearSelection2(true); } } UpdateUI(activeDoc); } /// /// 附加一些插件范围内的事件 /// /// private void AttachDocNotify(ModelDoc2 doc) { int docType = doc.GetType(); if (docType == (int)swDocumentTypes_e.swDocASSEMBLY) { AssemblyDoc ass = doc as AssemblyDoc; ass.UserSelectionPostNotify += Ass_UserSelectionPostNotify; ass.DestroyNotify2 += ActiveDocDestroyNotify2; } else if (docType == (int)swDocumentTypes_e.swDocPART) { PartDoc part = doc as PartDoc; part.DestroyNotify2 += ActiveDocDestroyNotify2; } else if (docType == (int)swDocumentTypes_e.swDocDRAWING) { DrawingDoc draw = doc as DrawingDoc; draw.DestroyNotify2 += ActiveDocDestroyNotify2; } } /// /// 移除插件范围内的一些事件 /// /// private void DetachDocNotify(ModelDoc2 doc) { try { int docType = doc.GetType(); if (docType == (int)swDocumentTypes_e.swDocASSEMBLY) { AssemblyDoc ass = doc as AssemblyDoc; ass.UserSelectionPostNotify -= Ass_UserSelectionPostNotify; ass.DestroyNotify2 -= ActiveDocDestroyNotify2; } else if (docType == (int)swDocumentTypes_e.swDocPART) { PartDoc part = doc as PartDoc; part.DestroyNotify2 -= ActiveDocDestroyNotify2; } else if (docType == (int)swDocumentTypes_e.swDocDRAWING) { DrawingDoc draw = doc as DrawingDoc; draw.DestroyNotify2 -= ActiveDocDestroyNotify2; } } catch (COMException e) { // 如果sw把不是装配体/零件体/工程图的文档关了,有时会报这个问题,留个日志不报错了 Logger.Warn("COMObject detach event failed.", e); activeDoc = null; } } private int ActiveDocDestroyNotify2(int DestroyType) { if (activeDoc == null) { return 0; } DetachDocNotify(activeDoc); activeDoc = null; ReadComponent = null; UpdateUI(null); return 0; } public void UpdateUI(ModelDoc2 doc) { AlertSaveWindow(); LastReadDoc = ReadDoc; ReadDoc = doc; Dispatcher.Invoke(() => { SwitchVisiable(); // LoadDocProperties(); }); } /// /// 判断是否需要弹窗提示保存 /// public void AlertSaveWindow() { IPropertyOpt opt = ActiveOpter as IPropertyOpt; if (opt != null && opt.GetDocChanged()) { // 历史文档直接重置 string fullName = Path.GetFileName(ReadDocPath); if (NameUtil.IsHistoryDoc(fullName)) { opt.ResetProperty(out string errMsg); return; } string Message = $"{fullName}属性发生变更,是否保存?"; if (SwApp.SendMsgToUser2(Message, (int)swMessageBoxIcon_e.swMbWarning , (int)swMessageBoxBtn_e.swMbYesNo) == (int)swMessageBoxResult_e.swMbHitYes) { SaveDoc(true); } else { opt.ResetProperty(out string errMsg); } } } private int Ass_UserSelectionPostNotify() { var swSelMgr = (SelectionMgr)activeDoc.SelectionManager; var i = swSelMgr.GetSelectedObjectCount2(-1); if (i > 0) { try { Component2 component = swSelMgr.GetSelectedObjectsComponent4(1, -1); ModelDoc2 doc = activeDoc; ReadComponent = null; if (component != null) { doc = component.IGetModelDoc(); ReadComponent = component; } UpdateUI(doc); } catch (Exception ex) { Logger.Error("Ass Change Component Error.", ex); this.Error($"刷新属性失败!{ex.Message}"); } } return 1; } /// /// 根据激活的文档类型,变更属性可视 /// private void SwitchVisiable() { HashSet skipName = new HashSet { NameConstant.materialCode }; IPropertyOpt last = ActiveOpter as IPropertyOpt; string contentKey = "default"; int? docType = ReadDoc?.GetType(); UserControl control; IPropertyOpt newOne; Dictionary properties; if (docType == (int)swDocumentTypes_e.swDocDRAWING) { ReadDocPath = ReadDoc.GetPathName(); contentKey = "default"; control = controlCache[contentKey]; newOne = control as IPropertyOpt; newOne.SetProperties(null, "当前不支持工程图", true, out _); } else if (docType == (int)swDocumentTypes_e.swDocPART) { ReadDocPath = ReadDoc.GetPathName(); properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName); string fileType = properties.Get(NameConstant.docType); /*if (fileType == "加工件" || fileType == "模组") { contentKey = "jgjPart"; }*/ if (BomIniterHolder.Instance.IsJgj(ReadDoc)) { contentKey = "jgjPart"; } else { contentKey = "standardPart"; } control = controlCache[contentKey]; newOne = control as IPropertyOpt; newOne.SetProperties(ReadDoc, properties, true, out _); } else if (docType == (int)swDocumentTypes_e.swDocASSEMBLY) { ReadDocPath = ReadDoc.GetPathName(); if (ReadDoc.IsOpenedViewOnly()) { contentKey = "default"; control = controlCache[contentKey]; newOne = control as IPropertyOpt; newOne.SetProperties(null, "当前处于只读模式", true, out _); } else if (ReadDoc.IsOpenedReadOnly()) { contentKey = "default"; control = controlCache[contentKey]; newOne = control as IPropertyOpt; newOne.SetProperties(null, "当前处于只读模式", true, out _); } else { // !Equals(LastReadDoc, ReadDoc) properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName); string fileType = properties.Get(NameConstant.docType); /*if (fileType == "加工件" || fileType == "模组") { contentKey = "jgjPart"; }*/ if (BomIniterHolder.Instance.IsJgj(ReadDoc)) { contentKey = "jgjModule"; } else { contentKey = "standardModule"; } control = controlCache[contentKey]; newOne = control as IPropertyOpt; newOne.SetProperties(ReadDoc, properties, true, out _); } } else { contentKey = "default"; control = controlCache[contentKey]; newOne = control as IPropertyOpt; string PathName = ReadComponent?.GetPathName(); if (PathName == null) { ReadDocPath = ""; newOne.SetProperties(ReadDoc, "请打开一个文档", true, out _); } else { ReadDocPath = PathName; string name = Path.GetFileNameWithoutExtension(PathName); newOne.SetProperties(ReadDoc, $"【{name}】未找到文档,请检查是否被压缩或轻量化", true, out _); } } if (last != null) { last.UpdateProperty -= Jgj_SinglePropertyChanged; last = null; } ActiveOpter = control; contentPanel.Children.Clear(); newOne.UpdateProperty += Jgj_SinglePropertyChanged; contentPanel.Children.Add(control); } /// /// 根据激活的文档类型,变更属性可视 /// private void SwitchVisiable2() { HashSet skipName = new HashSet { NameConstant.materialCode }; IPropertyOpt last = ActiveOpter as IPropertyOpt; string contentKey = "default"; int? docType = ReadDoc?.GetType(); UserControl control; IPropertyOpt newOne; Dictionary properties; if (docType == (int)swDocumentTypes_e.swDocDRAWING) { ReadDocPath = ReadDoc.GetPathName(); control = new DefaultPanel(); newOne = control as IPropertyOpt; newOne.SetSettings(settings); newOne.SetProperties(null, "当前不支持工程图", true, out _); } else if (docType == (int)swDocumentTypes_e.swDocPART) { ReadDocPath = ReadDoc.GetPathName(); properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName); string fileType = properties.Get(NameConstant.docType); /*if (fileType == "加工件" || fileType == "模组") { contentKey = "jgjPart"; }*/ if (BomIniterHolder.Instance.IsJgj(ReadDoc)) { control = new JgjPartPanel(); } else { control = new StandardPartPanel(); } newOne = control as IPropertyOpt; newOne.SetSettings(settings); newOne.SetProperties(ReadDoc, properties, true, out _); } else if (docType == (int)swDocumentTypes_e.swDocASSEMBLY) { ReadDocPath = ReadDoc.GetPathName(); // !Equals(LastReadDoc, ReadDoc) properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName); string fileType = properties.Get(NameConstant.docType); /*if (fileType == "加工件" || fileType == "模组") { contentKey = "jgjPart"; }*/ if (BomIniterHolder.Instance.IsJgj(ReadDoc)) { control = new JgjModulePanel(); } else { control = new StandardModulePanel(); } newOne = control as IPropertyOpt; newOne.SetSettings(settings); newOne.SetProperties(ReadDoc, properties, true, out _); } else { control = new DefaultPanel(); newOne = control as IPropertyOpt; string PathName = ReadComponent?.GetPathName(); if (PathName == null) { ReadDocPath = ""; newOne.SetSettings(settings); newOne.SetProperties(ReadDoc, "请打开一个文档", true, out _); } else { ReadDocPath = PathName; string name = Path.GetFileNameWithoutExtension(PathName); newOne.SetSettings(settings); newOne.SetProperties(ReadDoc, $"【{name}】未找到文档,请检查是否被压缩或轻量化", true, out _); } } if (last != null) { last.UpdateProperty -= Jgj_SinglePropertyChanged; last = null; } ActiveOpter = control; contentPanel.Children.Clear(); newOne.UpdateProperty += Jgj_SinglePropertyChanged; contentPanel.Children.Add(control); } /// /// 从激活的文档中读取参数 /// private void LoadDocProperties() { IPropertyOpt opt = ActiveOpter as IPropertyOpt; string ErrMsg = null; if (ReadDoc == null) { string PathName = ReadComponent?.GetPathName(); if (PathName == null) { ReadDocPath = ""; opt.SetProperties(ReadDoc, "请打开一个文档", true, out ErrMsg); return; } ReadDocPath = PathName; string name = Path.GetFileNameWithoutExtension(PathName); opt.SetProperties(ReadDoc, $"【{name}】未找到文档,请检查是否被压缩或轻量化", true, out ErrMsg); return; } int docType = ReadDoc.GetType(); ReadDocPath = ReadDoc.GetPathName(); if (docType == (int)swDocumentTypes_e.swDocDRAWING) { opt.SetProperties(null, "当前不支持工程图", true, out ErrMsg); return; } HashSet skipName = new HashSet { NameConstant.materialCode }; Dictionary properties = CustomPropertyUtil.GetCustomProperties2(ReadDoc, true, skipName); opt.SetProperties(ReadDoc, properties, !Equals(LastReadDoc, ReadDoc), out ErrMsg); } private void ClearDocProperties() { IPropertyOpt opt = ActiveOpter as IPropertyOpt; opt.ClearAllProperties(out string ErrMsg); } /// /// 将属性设置进文档,注意,并没有保存 /// /// 文档 private void SetDocProperty(ModelDoc2 doc, Dictionary props) { CustomPropertyUtil.SetCustomProperties(doc, props); } public void SetSwApp(SldWorks SwApp) { this.SwApp = SwApp; } private void SaveDoc(bool qiaoqiaode) { int errors = 0, warnings = 0; if ((ActiveOpter as IPropertyOpt).SaveDoc(ref errors, ref warnings)) { // if (!qiaoqiaode) this.Info("保存成功"); } } private void SaveButton_Click(object sender, RoutedEventArgs e) { if (ReadDoc == null) { return; } SaveDoc(false); } public void RefreshData() { MaskAdorner.ShowMask(content, "属性加载中,请稍候..."); Task.Run(() => { try { UpdateActiveDoc(); } catch (COMException come) { // 频繁关闭会抛出这个异常,不管了 Logger.Warn("Read property COMObject failed.", come); } catch (Exception ex) { Logger.Error($"读取参数异常,文件:[{ReadDocPath}]!", ex); this.Error($"读取参数异常:{ex.Message}"); } finally { MaskAdorner.HideMask(content); } }); } private void Refresh_Click(object sender, RoutedEventArgs e) { RefreshData(); } private void LoadComboBox_Click(object sender, RoutedEventArgs e) { MaskAdorner.ShowMask(content, "加载MES设置,请稍候..."); Task.Run(() => { try { LoadComboxItemSource(); } finally { MaskAdorner.HideMask(content); } }); } private void PropertySettingControl_Initialized(object sender, EventArgs e) { InitPropertyData(); } /// /// 激活的文档变更触发 /// /// /// /// public void OnSwActiveDocChange(ModelDoc2 lastDoc, ModelDoc2 doc, Component2 comp) { // CurrentChanged(); RefreshData(); } public void OnSwActiveDocSaved(ModelDoc2 doc, Component2 comp) { // 读取文件,设置参数 // LoadDocProperties(); } public void OnCustomPropertyChange(string propName, string Configuration, string oldValue, string NewValue, int valueType) { if (oldValue == NewValue) { return; } IPropertyOpt opt = ActiveOpter as IPropertyOpt; opt.UpdateSingleProperty(propName, NewValue); } public void OnDocDestroy(ModelDoc2 doc) { } public void AfterDocDestroy() { } public void OnTabControlSelectionChange(object sender, SelectionChangedEventArgs e) { if (e.RemovedItems == null) { return; } foreach (object obj in e.RemovedItems) { if (obj is TabItem item) { if (item.Content == this) { AlertSaveWindow(); break; } } else { return; } } } } }