The following sample automatically sets a prefix when new attributes or enumeration literals are added to your UModel project. The sample uses both the UModel API and the UModel IDE Plug-In library and is available in the following file: ..\UModelExamples\IDEPlugIn\DefaultPrefix\DefaultPrefix.cs.
To build and run the sample, the same requirements as for other UModel IDE Plug-ins apply, see the topic Build and Run the Plug-In in the UModel user manual.
|
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices.ComTypes;
using UModelLib;
using UModelPlugInLib;
/*
* DefaultPrefix sample
* listen for newly added UML data and
* set the prefix of properties ('m_') and EnumerationLiterals ('k_')
* if the corresponding option is turned on
*/
namespace DefaultPrefix
{
/* UModelDefaultPrefix is the main class of this plugin and implements UModelPlugInLib.IUModelPlugIn
* it is also responsible for attaching/detaching UModelApplicationEvents to/from UModels IApplication interface
* and implements the handling of turning on/off the whole "SetPrefix" functionality
*/
public class UModelDefaultPrefix : UModelPlugInLib.IUModelPlugIn
{
// variable which defines whether "SetPrefix" functionality is turned on or off
bool m_bSetPrefix = true;
// reference to UModelApplicationEvents; is only used when "SetPrefix" functionality is turned on (to reduce overhead in the other case)
UModelApplicationEvents m_AppEvents = null;
#region helpers
protected string GetPlugInPath()
{
string sDLLPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
return System.IO.Path.GetDirectoryName(sDLLPath);
}
#endregion
// create UModelApplicationEvents and attach it to IApplication
protected void AttachAppEvents( IApplication iUModelApp )
{
if (m_AppEvents == null && iUModelApp != null)
{
m_AppEvents = new UModelApplicationEvents();
m_AppEvents.Attach(iUModelApp);
}
}
// detach UModelApplicationEvents;
protected void DetachAppEvents()
{
if (m_AppEvents != null)
{
m_AppEvents.Detach();
m_AppEvents = null;
}
}
#region IUModelPlugIn Members
public string GetDescription()
{
return "DefaultPrefix sample Plug-in for UModel;This Plug-in demonstrates how to attach to several callback interfaces and how to add a prefix to newly inserted elements.";
}
public string GetUIModifications()
{
try
{
string sPath = GetPlugInPath();
System.IO.StreamReader myFile = new System.IO.StreamReader(sPath + "\\config.xml");
string sRet = myFile.ReadToEnd();
myFile.Close();
// this replaces the token "**path**" from the XML file with
// the actual installation path of the plug-in to get the image file
return sRet.Replace("**path**", sPath);
}
catch (System.Exception ex)
{
System.Windows.Forms.MessageBox.Show("Error in GetUIModifications:" + ex.Message);
throw ex;
}
}
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 UModelApplicationEvents
AttachAppEvents( (IApplication)pUModel );
}
public void OnShutdown(object pUModel)
{
// detach UModelApplicationEvents; stop receiving events
DetachAppEvents();
// application will shutdown; release all unused objects
GC.Collect();
}
public UModelUpdateAction OnUpdateCommand(int nID, object pUModel)
{
UModelUpdateAction action = UModelUpdateAction.UModelUpdateAction_Disable;
// check if automatically setting the prefix is turned on:
if (nID == 3 || nID == 4)
{
action = UModelUpdateAction.UModelUpdateAction_Enable;
if (m_bSetPrefix)
action |= UModelUpdateAction.UModelUpdateAction_Check;
}
// release unused objects
//GC.Collect(); not necessary since we do not access objects here
return action;
}
public void OnCommand(int nID, object pUModel)
{
// toggle automatically setting the prefix:
if (nID == 3 || nID == 4)
m_bSetPrefix = !m_bSetPrefix;
// attach UModelApplicationEvents when "SetPrefix" functionality is turned on; detach otherwise
if (m_bSetPrefix)
AttachAppEvents((IApplication)pUModel);
else
DetachAppEvents();
// release unused objects
GC.Collect();
}
#endregion
}
/* UModelApplicationEvents is an eventhandler to receive _IApplicationEvents
* that we know when UModel documents are opened or closed
* and that we can Attach/Detach UModelDataEvents
* We are interested in all _IApplicationEvents and use a connectionpoint to connect to all these events
*/
public class UModelApplicationEvents : UModelLib._IApplicationEvents
{
// connection point to _IApplicationEvents
System.Runtime.InteropServices.ComTypes.IConnectionPoint m_cpApplicationEvents = null;
// connection cookie
int m_nApplicationtEventsCookie = 0;
// we always hold a reference to UModelDataEvents
UModelDataEvents m_UMLDataEvents = new UModelDataEvents();
public void Attach(IApplication iApp)
{
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);
// also attach UModelDataEvents to the current document and start receiving events there
m_UMLDataEvents.Attach(iApp.ActiveDocument);
}
}
public void Detach()
{
if (m_cpApplicationEvents != null)
{
// also detach UModelDataEvents and stop receiving events there
m_UMLDataEvents.Detach();
// terminate established connection to _IApplicationEvents
m_cpApplicationEvents.Unadvise(m_nApplicationtEventsCookie);
m_cpApplicationEvents = null;
}
}
#region _IApplicationEvents Members
public void OnNewDocument(Document ipDocument)
{
Debug.WriteLine("UModelApplicationEvents.OnNewDocument " + ipDocument.Name);
// a new document has been created in UModel => (re-)connect UModelDataEvents
m_UMLDataEvents.Attach(ipDocument);
}
public void OnDocumentOpened(Document ipDocument)
{
Debug.WriteLine("UModelApplicationEvents.OnDocumentOpened " + ipDocument.Name);
// a document has been opened in UModel => (re-)connect UModelDataEvents
m_UMLDataEvents.Attach(ipDocument);
}
public void OnDocumentClosed(Document ipDocument)
{
Debug.WriteLine("UModelApplicationEvents.OnDocumentClosed " + ipDocument.Name);
// document has been closed in UModel => disconnect UModelDataEvents
m_UMLDataEvents.Detach();
}
public void OnShutdown()
{
Debug.WriteLine("UModelApplicationEvents.OnShutdown");
}
#endregion
}
/* UModelDataEvents is an eventhandler to receive _IUMLDataEvents
* from the root-package and all its children.
* We are only interested in 'OnAfterAddChild' events, so we use a delegate to connect to this event.
*/
public class UModelDataEvents : UModelLib._IUMLDataEvents
{
// hold a reference to the current UML Root package; this is safe as long as we listen to when it is deleted
protected UMLData m_RootPackage = null;
// attach this eventhandler to the root-package of the (current) document
public void Attach(IDocument iDoc)
{
if (m_RootPackage == null && iDoc != null && iDoc.RootPackage != null)
{
// hold a reference to the current UML Root package
m_RootPackage = (UMLData)iDoc.RootPackage;
// ensure we get 'OnAfterAddChild' events for *any* added child of the rootpackage
// (added to the root-package or one of its children)
m_RootPackage.EventFilter = (int)ENUMUMLDataEventFilter.eUMLDataEvent_AddChildOrGrandChild;
// ensure we get informed when m_RootPackage (and only itself; we do not care about its chidlren) is deleted
m_RootPackage.EventFilter |= (int)ENUMUMLDataEventFilter.eUMLDataEvent_EraseData;
// we are only interested in 'OnAfterAddChild' and 'OnBeforeErase' events so use and connect the delegates
m_RootPackage.OnAfterAddChild += new _IUMLDataEvents_OnAfterAddChildEventHandler(OnAfterAddChild);
m_RootPackage.OnBeforeErase += new _IUMLDataEvents_OnBeforeEraseEventHandler(OnBeforeErase);
}
}
// detach eventhandler from the current UML Root package
public void Detach()
{
if (m_RootPackage != null)
{
m_RootPackage.OnAfterAddChild -= OnAfterAddChild;
m_RootPackage.OnBeforeErase -= OnBeforeErase;
m_RootPackage = null;
// release unused objects
GC.Collect();
}
}
#region _IUMLDataEvents Members
public void OnAfterAddChild(IUMLData ipUMLParent, IUMLData ipUMLChild)
{
if (ipUMLParent == null || ipUMLChild == null)
return;
Debug.WriteLine("UModelDataEvents.OnAfterAddChild " + GetName(ipUMLChild) + " to " + GetName(ipUMLParent));
// verify if newly added child is of interesting kind:
bool bIsEnumerationLiteral = (ipUMLChild is IUMLEnumerationLiteral);
bool bIsProperty = (ipUMLChild is IUMLProperty);
if (bIsProperty || bIsEnumerationLiteral)
{
try
{
// check if child was added by undo/redo
// (we are not allowed to modify anything during Undo/Redo !!)
IDocument iDoc = (IDocument)ipUMLChild.Parent;
if (!iDoc.IsInUndoRedo)
{
// we only make one single modification here
// no need to use iDoc.BeginModification / iDoc.EndModification in this case
// get the wanted prefix for the element kind
string sPrefix = null;
if (bIsProperty)
sPrefix = "m_";
if (bIsEnumerationLiteral)
sPrefix = "k_";
IUMLNamedElement iNamedChild = (IUMLNamedElement)ipUMLChild;
// set prefix only if not already set:
if (sPrefix != null && !iNamedChild.Name.StartsWith(sPrefix))
{
// use SetName (instead of Name) that UModel automatically generates a valid, unique name starting with 'sPrefix + iNamedChild.Name'
iNamedChild.SetName(sPrefix + iNamedChild.Name);
}
}
}
catch (System.Exception e)
{
Debug.WriteLine("EXCEPTION: " + e.Message);
}
}
// release unused objects
GC.Collect();
}
public void OnBeforeErase(IUMLData ipUMLData)
{
if (ipUMLData != null && m_RootPackage != null && ipUMLData.IsSameUMLData((IUMLData)m_RootPackage)) // should always be
{
// Detach ourself, since the UML data of m_RootPackage has been deleted in UModel and we may not access it anymore
Detach();
}
}
public void OnChanged(IUMLData ipUMLData, string strHint)
{
// unused
}
public void OnMoveData(IUMLData ipUMLParent, IUMLData ipUMLChild, bool bAttach)
{
// unused
}
#endregion
protected string GetName(IUMLData iUMLData)
{
if (iUMLData is IUMLNamedElement)
return ((IUMLNamedElement)iUMLData).Name;
return "";
}
}
}
|