public Result Execute(
ExternalCommandData commandData,
ref string message,
ElementSet elements)
{
UIApplication uiapp = commandData.Application;
UIDocument uidoc = uiapp.ActiveUIDocument;
Application app = uiapp.Application;
Document doc = uidoc.Document;
using ( Transaction tx = new Transaction( doc ) )
{
tx.Start( "Mirror and List Added" );
//Line line = app.Create.NewLine(
// XYZ.Zero, XYZ.BasisX, true ); // 2011
//ElementSet els = uidoc.Selection.Elements; // 2011
//Plane plane = new Plane( XYZ.BasisY, XYZ.Zero ); // added in 2012, used until 2016
Plane plane = Plane.CreateByNormalAndOrigin( XYZ.BasisY, XYZ.Zero ); // 2017
ICollection<ElementId> elementIds
= uidoc.Selection.GetElementIds(); // 2012
using ( SubTransaction t = new SubTransaction( doc ) )
{
// determine newly added elements relying on the
// element sequence as returned by the filtered collector.
// this approach works in both Revit 2010 and 2011:
t.Start();
int n = GetElementCount( doc );
//doc.Mirror( els, line ); // 2011
//ElementTransformUtils.MirrorElements(
// doc, elementIds, plane ); // 2012-2015
ElementTransformUtils.MirrorElements(
doc, elementIds, plane, true ); // 2016
List<Element> a = GetElementsAfter( n, doc );
t.RollBack();
}
using ( SubTransaction t = new SubTransaction( doc ) )
{
// here is an idea for a new approach in 2011:
// determine newly added elements relying on
// monotonously increasing element id values:
t.Start();
FilteredElementCollector a = GetElements( doc );
int i = a.Max<Element>( e => e.Id.IntegerValue );
ElementId maxId = new ElementId( i );
// doc.Mirror( els, line ); // 2011
//ElementTransformUtils.MirrorElements(
// doc, elementIds, plane ); // 2012-2015
ElementTransformUtils.MirrorElements(
doc, elementIds, plane, true ); // 2016
// get all elements in document with an
// element id greater than maxId:
a = GetElementsAfter( doc, maxId );
Report( a );
t.RollBack();
}
using ( SubTransaction t = new SubTransaction( doc ) )
{
// similar to the above approach relying on
// monotonously increasing element id values,
// but apply a quick filter first:
t.Start();
FilteredElementCollector a = GetElements( doc );
int i = a.Max<Element>( e => e.Id.IntegerValue );
ElementId maxId = new ElementId( i );
//doc.Mirror( els, line ); // 2011
//ElementTransformUtils.MirrorElements(
// doc, elementIds, plane ); // 2012-2015
ElementTransformUtils.MirrorElements(
doc, elementIds, plane, true ); // 2016
// only look at non-ElementType elements
// instead of all document elements:
a = GetElements( doc );
a = GetElementsAfter( a, maxId );
Report( a );
t.RollBack();
}
using ( SubTransaction t = new SubTransaction( doc ) )
{
// use a local and temporary DocumentChanged event
// handler to directly obtain a list of all newly
// created elements.
// unfortunately, this canot be tested in this isolated form,
// since the DocumentChanged event is only triggered when the
// real outermost Revit transaction is committed, i.e. our
// local sub-transaction makes no difference. since we abort
// the sub-transaction before the command terminates and no
// elements are really added to the database, our event
// handler is never called:
t.Start();
app.DocumentChanged
+= new EventHandler<DocumentChangedEventArgs>(
app_DocumentChanged );
//doc.Mirror( els, line ); // 2011
//ElementTransformUtils.MirrorElements(
// doc, elementIds, plane ); // 2012-2015
ElementTransformUtils.MirrorElements(
doc, elementIds, plane, true ); // 2016
app.DocumentChanged
-= new EventHandler<DocumentChangedEventArgs>(
app_DocumentChanged );
Debug.Assert( null == _addedElementIds,
"never expected the event handler to be called" );
if ( null != _addedElementIds )
{
int n = _addedElementIds.Count;
string s = string.Format( _msg, n,
Util.PluralSuffix( n ) );
foreach ( ElementId id in _addedElementIds )
{
Element e = doc.GetElement( id );
s += string.Format( "\r\n {0}",
Util.ElementDescription( e ) );
}
Util.InfoMsg( s );
}
t.RollBack();
}
tx.RollBack();
}
return Result.Succeeded;
}