The "Statistics" sample listens for data modifications and counts elements of different element kinds. The sample uses both the UModel API and the UModel IDE Plug-In library. Since the plug-in derives from System.Windows.Forms.UserControl, it also acts as an ActiveX control and the results can be shown in a custom window inside UModel:
This code is available in the following file: ..\UModelExamples\IDEPlugIn\StatisticsActiveX\StatisticsActiveX.cs.
using System; using System.Collections; using System.Collections.Generic; using System.Text; using System.Drawing; using System.Runtime.InteropServices.ComTypes; using System.Windows.Forms; using UModelLib; using UModelPlugInLib; /* * StatisticsActiveX sample * listen for data modifications and count the elements of the different element kinds * show the result in a listview of an ActiveX control */ namespace StatisticsActiveX { /* StatisticsActiveX is the main class of this plugin and implements UModelPlugInLib.IUModelPlugIn * it is also responsible for attaching/detaching _IApplicationEvents and _ITransactionEvents */ public partial class StatisticsActiveX : UserControl, IUModelPlugIn, _IApplicationEvents, _ITransactionEvents { // a sorted dictionary to count the different element kinds private Statistics m_Statistics; // reference to the transaction notifier of a UModel document private TransactionNotifier m_TransactionNotifier; // connection point to _IApplicationEvents private IConnectionPoint m_cpApplicationEvents = null; // connection cookie int m_nApplicationtEventsCookie = 0; public StatisticsActiveX() { InitializeComponent(); } #region IUModelPlugIn Members public string GetDescription() { return "PlugIn with ActiveX;This Plug-in demonstrates how to show an ActiveX control inside UModel."; } public string GetUIModifications() { // We don't add any menu or toolbar modifications. return "<ConfigurationData><Modifications/></ConfigurationData>"; } public void OnInitialize(object pUModel) { // before processing DDE or batch commands } public void OnRunning(object pUModel) { // DDE or batch commands are processed; application is fully initialized // and we can attach to get _IApplicationEvents IApplication iApp = (IApplication)pUModel; if (m_cpApplicationEvents == null && iApp != null) { // find connection point of _IApplicationEvents IConnectionPointContainer icpc = (IConnectionPointContainer)iApp; Guid IID = typeof(UModelLib._IApplicationEvents).GUID; icpc.FindConnectionPoint(ref IID, out m_cpApplicationEvents); // advise UModelApplicationEvents as sink for _IApplicationEvents m_cpApplicationEvents.Advise(this, out m_nApplicationtEventsCookie); } AttachTransactionEvents(iApp.ActiveDocument); } public void OnShutdown(object pUModel) { // detach application events; stop receiving events DetachTransactionEvents(); if (m_cpApplicationEvents != null) { // terminate established connection to _IApplicationEvents m_cpApplicationEvents.Unadvise(m_nApplicationtEventsCookie); m_cpApplicationEvents = null; } // application will shutdown; release all unused objects GC.Collect(); } public void OnCommand(int nID, object pUModel) { // unused; we did not add any menu- or toolbar-commands } public UModelUpdateAction OnUpdateCommand(int nID, object pUModel) { // unused; we did not add any menu- or toolbar-commands return UModelUpdateAction.UModelUpdateAction_Disable; } #endregion private void AttachTransactionEvents(IDocument iDoc) { if (iDoc != null) { m_TransactionNotifier = iDoc.TransactionNotifier; if (m_TransactionNotifier != null) { // we are only interested in 'OnEndDataModification' events so use and connect the delegate m_TransactionNotifier.OnEndDataModification += new _ITransactionEvents_OnEndDataModificationEventHandler(OnEndDataModification); } } UpdateStatistics(iDoc); } // detach eventhandler from the transaction notifier private void DetachTransactionEvents() { if (m_TransactionNotifier != null) { m_TransactionNotifier.OnEndDataModification -= OnEndDataModification; m_TransactionNotifier = null; } UpdateStatistics(null); } void UpdateStatistics(IDocument iDoc) { // count current elements Statistics statistics = new Statistics(); if (iDoc != null && iDoc.RootPackage != null) CountElements(iDoc.RootPackage, ref statistics); // anything changed to last update ? if (!statistics.IsEqual(m_Statistics)) { m_Statistics = statistics; PopulateListView(m_Statistics); } // release unused objects GC.Collect(); } private void CountElements(IUMLElement iElem, ref Statistics statistics) { // we only count editable elements if (iElem == null || iElem.IsEditable == false) return; string sKindName = iElem.KindName; if (!statistics.ContainsKey(sKindName)) statistics[sKindName] = 1; else statistics[sKindName]++; foreach (IUMLElement iChild in iElem.OwnedElements) CountElements(iChild, ref statistics); } private void PopulateListView(Statistics statistics) { listView1.BeginUpdate(); listView1.Items.Clear(); foreach (KeyValuePair<string, int> kvp in statistics) { ListViewItem item = new ListViewItem(kvp.Key); item.SubItems.Add(Convert.ToString(kvp.Value)); listView1.Items.Add(item); } listView1.EndUpdate(); } #region _ITransactionEvents Members public void OnBeginDataModification(Document ipDocument) { // begin of transaction } public void OnEndDataModification(Document ipDocument) { // end of transaction - update statistics if (ipDocument != null && ipDocument.TransactionNotifier == m_TransactionNotifier) UpdateStatistics(ipDocument); } #endregion #region _IApplicationEvents Members public void OnNewDocument(Document ipDocument) { // a new document has been created in UModel => (re-)connect transaction events AttachTransactionEvents(ipDocument); } public void OnDocumentOpened(Document ipDocument) { // a document has been opened in UModel => (re-)connect transaction events AttachTransactionEvents(ipDocument); } public void OnDocumentClosed(Document ipDocument) { // document has been closed in UModel => disconnect transaction events if (ipDocument != null && ipDocument.TransactionNotifier == m_TransactionNotifier) DetachTransactionEvents(); } public void OnShutdown() { } #endregion #region Statistics dictionary private class Statistics : SortedDictionary<string, int> { public bool IsEqual(Statistics other) { if (other == null) return false; if (Count != other.Count) return false; Enumerator e1 = GetEnumerator(); Enumerator e2 = other.GetEnumerator(); while (e1.MoveNext() && e2.MoveNext()) { if ((e1.Current.Key != e2.Current.Key) || (e1.Current.Value != e2.Current.Value)) return false; } return true; } } #endregion } } |