using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Autodesk.AutoCAD.DatabaseServices;
using Autodesk.AutoCAD.Runtime;
using System.ComponentModel;
/// Quick/dirty - strip xdata from entities created by
/// the OFFSET command, in this example uses the XDATA
/// appname "MYXDATA"
namespace Autodesk.AutoCAD.ApplicationServices.MyExtensions
{
public class MyApplication : IExtensionApplication
{
public void Initialize()
{
OffsetCommandObserver.Inititlize();
}
public void Terminate()
{
}
}
public abstract class XDataManagerOverrule : ObjectOverrule
{
string appname = null;
TypedValue[] empty = null;
Document doc = null;
Database db = null;
public XDataManagerOverrule( Document doc, string appname )
{
this.appname = appname;
this.doc = doc;
this.db = doc.Database;
empty
= new TypedValue
[] { new TypedValue
( 1001, appname
) }; AddOverrule
( RXClass
.GetClass( typeof( Entity
) ),
this,
true ); SetXDataFilter( appname );
}
public override void Close( DBObject dbObject )
{
if( dbObject.IsNewObject && dbObject.IsWriteEnabled && dbObject.Database == db )
{
using( ResultBuffer rb = dbObject.GetXDataForApplication( appname ) )
{
if( rb != null )
{
UpdateXData( dbObject, rb );
}
}
}
base.Close( dbObject );
}
protected virtual void UpdateXData( DBObject dbObject, ResultBuffer rb )
{
}
bool disposed = false;
protected override void Dispose( bool disposing )
{
if( disposing && ! disposed )
RemoveOverrule
( RXClass
.GetClass( typeof( Entity
) ),
this ); disposed = true;
base.Dispose( disposing );
}
}
/// <summary>
/// Avoids full-time handling of end-command events;
/// </summary>
public abstract class CommandObserver : IDisposable
{
bool disposed = false;
Document doc = null;
bool handled = false;
public CommandObserver( Document doc )
{
if( doc == null )
throw new ArgumentNullException
( "doc" ); this.doc = doc;
this.doc.CommandWillStart += commandWillStart;
}
public enum State
{
Starting = 0,
Ended = 1,
Cancelled = 2,
Failed = 3
}
public Document Document
{
get
{
return this.doc;
}
}
void commandWillStart( object sender, CommandEventArgs e )
{
if( OnCommandStarting( e.GlobalCommandName ) )
{
AddEndHandlers();
}
}
void AddEndHandlers()
{
if( !this.handled )
{
doc.CommandEnded += doc_CommandEnded;
doc.CommandFailed += doc_CommandFailed;
doc.CommandCancelled += doc_CommandCancelled;
this.handled = true;
}
}
void RemoveEndHandlers()
{
if( this.handled )
{
doc.CommandEnded -= doc_CommandEnded;
doc.CommandFailed -= doc_CommandFailed;
doc.CommandCancelled -= doc_CommandCancelled;
this.handled = false;
}
}
/// Overrides should return true to be notified
/// when a command ends (otherwise, there is no
/// end-of-command notification).
protected virtual bool OnCommandStarting( string name )
{
return false;
}
protected virtual void OnCommandEnded( string name, State state )
{
}
void doc_CommandCancelled( object sender, CommandEventArgs e )
{
RemoveEndHandlers();
OnCommandEnded( e.GlobalCommandName, State.Cancelled );
}
void doc_CommandFailed( object sender, CommandEventArgs e )
{
RemoveEndHandlers();
OnCommandEnded( e.GlobalCommandName, State.Failed );
}
void doc_CommandEnded( object sender, CommandEventArgs e )
{
RemoveEndHandlers();
OnCommandEnded( e.GlobalCommandName, State.Ended );
}
protected virtual void Dispose( bool disposing )
{
if( !disposed )
{
doc.CommandWillStart -= this.commandWillStart;
RemoveEndHandlers();
disposed = true;
}
}
public void Dispose()
{
Dispose( true );
}
}
public class OffsetCommandObserver : CommandObserver
{
OffsetXDataOverrule overrule = null;
static DocData<OffsetCommandObserver> manager = null;
public static void Inititlize()
{
// Dummy method to invoke static c'tor
}
static OffsetCommandObserver()
{
manager
= new DocData
<OffsetCommandObserver
>( doc
=> new OffsetCommandObserver
( doc
) ); }
public OffsetCommandObserver( Document doc )
: base( doc )
{
}
protected override bool OnCommandStarting( string name )
{
if( name.Equals( "OFFSET", StringComparison.OrdinalIgnoreCase ) )
{
overrule
= new OffsetXDataOverrule
( this.Document,
"MYXDATA" ); return true;
}
return false;
}
protected override void OnCommandEnded( string name, State state )
{
if( overrule != null )
{
overrule.Dispose();
overrule = null;
}
}
class OffsetXDataOverrule : XDataManagerOverrule
{
TypedValue[] empty = null;
public OffsetXDataOverrule( Document doc, string appname )
: base( doc, appname )
{
empty
= new TypedValue
[] { new TypedValue
( 1001, appname
) }; }
protected override void UpdateXData( DBObject dbObject, ResultBuffer rb )
{
using( ResultBuffer buffer
= new ResultBuffer
( empty
) ) {
dbObject.XData = buffer;
}
}
}
}
public class DocData<T>
{
static Type key
= typeof( T
); Func<Document, T> factory = null;
public DocData( Func<Document, T> factory )
{
this.factory = factory;
DocumentCollection docs = Application.DocumentManager;
foreach( Document doc in docs )
{
Add( doc );
}
docs.DocumentCreated += documentCreated;
docs.DocumentToBeDestroyed += documentToBeDestroyed;
}
void documentToBeDestroyed( object sender, DocumentCollectionEventArgs e )
{
if( e.Document.UserData.ContainsKey( key ) )
{
IDisposable disposable = e.Document.UserData[key] as IDisposable;
if( disposable != null )
disposable.Dispose();
}
}
void documentCreated( object sender, DocumentCollectionEventArgs e )
{
Add( e.Document );
}
private void Add( Document document )
{
document.UserData[key] = factory( document );
}
}
}