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