Altova UModel 2025

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:

um_plugin_activex

This code is available in the following file: ..\UModelExamples\IDEPlugIn\StatisticsActiveX\StatisticsActiveX.cs.

 

To build and run the sample, the same requirements as for other UModel IDE Plug-ins apply, see Build and Run the Plug-In.

 

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
  }
}

© 2018-2024 Altova GmbH