// BlockTableRecordExtentions.cs
// © Andrey Bushman, 2014
// Extention methods for the BlockTableRecord class
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
/// В целях переносимости кода и отсутствия в псевдонимах наименований
/// конкретного САПР, целесообразней формировать псевдонимы в 
/// нейтральной форме, например: cad, вместо acad, Ap вместо AcAp, Db 
/// вместо AcDb и т.д. Построенная таким способом система наименований
/// будет более удобной программисту, портирующему ваш код под другую 
/// САПР. Ниже приведён вариант определений таких нейтральных псевдонимов
/// под некоторый набор различных САПР.
#if AUTOCAD
using cad = Autodesk.AutoCAD.ApplicationServices.Application;
using Ap = Autodesk.AutoCAD.ApplicationServices;
using Db = Autodesk.AutoCAD.DatabaseServices;
using Ed = Autodesk.AutoCAD.EditorInput;
using Gm = Autodesk.AutoCAD.Geometry;
using Rt = Autodesk.AutoCAD.Runtime;
#elif BRICSCAD
using cad = Bricscad.ApplicationServices.Application;
using Ap = Bricscad.ApplicationServices;
using Db = Teigha.DatabaseServices;
using Ed = Bricscad.EditorInput;
using Gm = Teigha.Geometry;
using Rt = Bricscad.Runtime;
#elif NANOCAD
using cad = HostMgd.ApplicationServices.Application;
using Ap = HostMgd.ApplicationServices;
using Db = Teigha.DatabaseServices;
using Ed = HostMgd.EditorInput;
using Gm = Teigha.Geometry;
using Rt = Teigha.Runtime; 
#endif
 
namespace Bushman.CAD.Extentions {
        /// <summary>
        /// Методы расширения для экземпляров класса BlockTableRecord
        /// </summary>
        public static class BlockTableRecordExtentions {
                /// <summary>
                /// Данный метод проверяет наличие экземпляров <c>Db.AttributeDefinition</c> в
                /// составе объекта <c>BlockTableRecord</c> и представляет собой замену методу
                /// <c>BlockTableRecord.HasAttributeDefinitions</c>, который реализован 
                /// неверно - в виду этого и возникла необходимость написать корректный вариант
                /// реализации. Информация о некорректной работе 
                /// <c>BlockTableRecord.HasAttributeDefinitions</c> была подтверждена и
                /// отправлена в ADN. Подробности на странице 
                /// http://adn-cis.org/forum/index.php?topic=625.0
                /// </summary>
                /// <param name="btr">экземпляр <c>BlockTableRecord</c>, подлежащий проверке.</param>
                /// <returns>true - в составе указанного объекта <c>BlockTableRecord</c>
                /// содержатся элементы <c>Db.AttributeDefinition</c>, иначе - false.</returns>
                public static Boolean HasAttDefs(this Db.BlockTableRecord btr) {
                        String name = Rt.RXClass.GetClass(typeof(Db.AttributeDefinition)).Name;
                        return btr.Cast<Db.ObjectId>().Any(n => !n.IsNull && n.IsValid
                                && !n.IsErased && !n.IsEffectivelyErased && String.Equals(
                                n.ObjectClass.Name, name, StringComparison.InvariantCulture));
                }
 
#if DEBUG
                /// <summary>
                /// Команда, демонструрующая некорректную работу 
                /// <c>BlockTableRecord.HasAttributeDefinitions</c>
                /// и корректность работы метода <c>HasAttDefs</c>.
                /// За основу взят код 
                /// http://adn-cis.org/forum/index.php?topic=625.msg2168#msg2168
                /// </summary>
                [Rt.CommandMethod("TestBlock")]
                public static void TestBlock() {
                        Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
                        Ed.Editor ed = doc.Editor;
                        Ed.PromptResult res = ed.GetString("\nType name of block: ");
                        if (res.Status != Ed.PromptStatus.OK) return;
                        using (Db.Transaction tr = doc.TransactionManager.StartTransaction()) {
                                Db.BlockTable bt = tr.GetObject(doc.Database.BlockTableId,
                                        Db.OpenMode.ForRead) as Db.BlockTable;
                                if (bt != null) {
                                        if (bt.Has(res.StringResult)) {
                                                Db.BlockTableRecord btr = tr.GetObject(bt[res.StringResult],
                                                        Db.OpenMode.ForRead) as Db.BlockTableRecord;
                                                if (btr != null) {
                                                        ed.WriteMessage("\nAutodesk: Block {0} has{1} attribute definitions.\n",
                                                                res.StringResult, btr.HasAttributeDefinitions ? "" : " not");
                                                        // Мною добавлена эта строка кода:
                                                        ed.WriteMessage("\nBushman: Block {0} has{1} attribute definitions.\n",
                                                                res.StringResult, btr.HasAttDefs() ? "" : " not");
                                                }
                                        }
                                        else {
                                                ed.WriteMessage("\nBlock {0} not found", res.StringResult);
                                        }
                                }
                                tr.Commit();
                        }
                }
#endif
        }
}