3. TextStyleManager

Теперь, имея на руках абстрактный класс, в котором реализована львиная доля необходимого функционала, можно приступать к разработке менеджеров стилей, ориентированных на конкретный тип стиля. Менеджеры будут представлены классами, унаследованными от StyleManager<T>. В этих классах необходимо переопределить небольшой набор методов:



Итак, приступаю к реализации первого менеджера - менеджера текстовых стилей...

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  //Acad
   6:  using acad = Autodesk.AutoCAD.ApplicationServices.Application;
   7:  using Autodesk.AutoCAD.ApplicationServices;
   8:  using Autodesk.AutoCAD.LayerManager;
   9:  using Autodesk.AutoCAD.Colors;
  10:  using Autodesk.AutoCAD.DatabaseServices;
  11:  using Autodesk.AutoCAD.EditorInput;
  12:  using Autodesk.AutoCAD.Runtime;
  13:  using ClipboardUse;
  14:  using System.Xml.Linq;
  15:  using Autodesk.AutoCAD.GraphicsInterface;
  16:  using Autodesk.AutoCAD.Interop.Common;
  17:   
  18:  namespace Bushman.Autodesk.AutoCAD.Styles
  19:  {
  20:      /// <summary>
  21:      /// Менеджер текстовых стилей AutoCAD
  22:      /// </summary>
  23:      public sealed class TextStyleManager : StyleManager<TextStyleTableRecord>
  24:      {
  25:          /// <summary>
  26:          /// Добавить в базу данных чертежа новый текстовый стиль
  27:          /// </summary>
  28:          /// <param name="style">Объект текстового стиля, который должен быть добавлен в базу данных чертежа</param>
  29:          public override void AddToDwg(TextStyleTableRecord style)
  30:          {
  31:              //Запускаю транзакцию
  32:              using (Transaction trs = Drawing.TransactionManager.StartTransaction())
  33:              {
  34:                  try
  35:                  {
  36:                      TextStyleTable tStyles = (TextStyleTable)trs.GetObject(db.TextStyleTableId, OpenMode.ForRead);
  37:                      //Блокирую документ от изменений извне
  38:                      using (Drawing.LockDocument())
  39:                      {
  40:                          //Если стиль уже существует и соответствует стандарту - завершаю работу метода.
  41:                          if (ExistInDrawing(style.Name) && EqualWithXml(style.Name))
  42:                          {
  43:                              return;
  44:                          }
  45:                          //Если стиль уже существует, но не соответствует стандарту - произвожу синхронизацию.
  46:                          else if (ExistInDrawing(style.Name) && !EqualWithXml(style.Name))
  47:                          {
  48:                              SynchronizationStyle(style.Name);
  49:                          }
  50:                          else
  51:                          {
  52:                              tStyles.UpgradeOpen();
  53:                              tStyles.Add(style);
  54:                              trs.AddNewlyCreatedDBObject(style, true);
  55:                          }
  56:                          //Завершаю транзакцию, сохраняя все изменения
  57:                          trs.Commit();
  58:                      }
  59:                  }
  60:                  catch (System.Exception e)
  61:                  {
  62:                      //Вывожу в командной строке AutoCAD текст ошибки и выполняю откат транзакции
  63:                      ed.WriteMessage(string.Format("\n{0}", e.Message));
  64:                      trs.Abort();                    
  65:                  }
  66:              }
  67:          }
  68:          
  69:          public override bool CanBeRemoved(string styleName)
  70:          {
  71:              return base.CanBeRemoved(styleName);
  72:          }
  73:          public override void ChangeStyleForPrimitives(TextStyleTableRecord oldStyle, TextStyleTableRecord newStyle)
  74:          {
  75:              base.ChangeStyleForPrimitives(oldStyle, newStyle);            
  76:          }
  77:   
  78:          private XElement temp;//Переменная используется в методах SynchronizationStyle.
  79:   
  80:          /// <summary>
  81:          /// Синхронизировать текстовый стиль с его одноимённым описанием в xml-файле
  82:          /// </summary>
  83:          /// <param name="styleName">Имя стиля</param>
  84:          public override void SynchronizationStyle(string styleName)
  85:          {
  86:              TextStyleTableRecord dwgStyle;
  87:              TextStyleTableRecord xmlStyle;
  88:   
  89:              if (!ExistInDrawing(styleName))
  90:              {
  91:                  throw new System.Exception("В чертеже не содержится текстового стиля с указанным именем!");
  92:              }
  93:              else if (!ExistInXml(styleName))
  94:              {
  95:                  xmlStyle = GetStyleFromXml(defaultStyleName);
  96:              }
  97:              else
  98:              {
  99:                  xmlStyle = GetStyleFromXml(styleName);
 100:              }
 101:   
 102:              dwgStyle = GetDrawingStyle(styleName);
 103:   
 104:              lock (Drawing.LockDocument())
 105:              {
 106:                  using (Transaction trs = Drawing.TransactionManager.StartTransaction())
 107:                  {
 108:                      if (!dwgStyle.IsWriteEnabled) dwgStyle.UpgradeOpen();
 109:   
 110:                      temp = new XElement(xmlStyle.Name);
 111:   
 112:                      if (dwgStyle.Name != xmlStyle.Name)
 113:                      {
 114:                          dwgStyle.Name = xmlStyle.Name;
 115:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "Name"),
 116:                              new XAttribute("OldValue", dwgStyle.Name), new XAttribute("NewValue", xmlStyle.Name));
 117:                          temp.Add(mod);
 118:                      }
 119:                      if (dwgStyle.FileName != xmlStyle.FileName)
 120:                      {
 121:                          dwgStyle.FileName = xmlStyle.FileName;
 122:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "FileName"),
 123:                              new XAttribute("OldValue", dwgStyle.FileName), new XAttribute("NewValue", xmlStyle.FileName));
 124:                          temp.Add(mod);
 125:                      }
 126:                      if (dwgStyle.Annotative != xmlStyle.Annotative)
 127:                      {
 128:                          dwgStyle.Annotative = xmlStyle.Annotative;
 129:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "Annotative"),
 130:                              new XAttribute("OldValue", dwgStyle.Annotative), new XAttribute("NewValue", xmlStyle.Annotative));
 131:                          temp.Add(mod);
 132:                      }
 133:                      if (dwgStyle.ObliquingAngle != xmlStyle.ObliquingAngle)
 134:                      {
 135:                          dwgStyle.ObliquingAngle = xmlStyle.ObliquingAngle;
 136:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "ObliquingAngle"),
 137:                              new XAttribute("OldValue", dwgStyle.ObliquingAngle), new XAttribute("NewValue", xmlStyle.ObliquingAngle));
 138:                          temp.Add(mod);
 139:                      }
 140:                      if (xmlStyle.PaperOrientation == PaperOrientationStates.True ? true : false)
 141:                      {
 142:                          bool parerOrientation = xmlStyle.PaperOrientation == PaperOrientationStates.True ? true : false;
 143:                          dwgStyle.SetPaperOrientation(parerOrientation);
 144:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "PaperOrientation"),
 145:                              new XAttribute("OldValue", dwgStyle.PaperOrientation), new XAttribute("NewValue", xmlStyle.PaperOrientation));
 146:                          temp.Add(mod);
 147:                      }
 148:                      if (dwgStyle.Font != xmlStyle.Font)
 149:                      {
 150:                          dwgStyle.Font = xmlStyle.Font;
 151:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "Font"),
 152:                              new XAttribute("OldValue", dwgStyle.Font), new XAttribute("NewValue", xmlStyle.Font));
 153:                          temp.Add(mod);
 154:                      }
 155:                      if (dwgStyle.BigFontFileName != xmlStyle.BigFontFileName)
 156:                      {
 157:                          dwgStyle.BigFontFileName = xmlStyle.BigFontFileName;
 158:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "BigFontFileName"),
 159:                              new XAttribute("OldValue", dwgStyle.BigFontFileName), new XAttribute("NewValue", xmlStyle.BigFontFileName));
 160:                          temp.Add(mod);
 161:                      }
 162:                      if (dwgStyle.FlagBits != xmlStyle.FlagBits)
 163:                      {
 164:                          dwgStyle.FlagBits = xmlStyle.FlagBits;
 165:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "FlagBits"),
 166:                              new XAttribute("OldValue", dwgStyle.FlagBits), new XAttribute("NewValue", xmlStyle.FlagBits));
 167:                          temp.Add(mod);
 168:                      }
 169:                      if (dwgStyle.TextSize != xmlStyle.TextSize)
 170:                      {
 171:                          dwgStyle.TextSize = xmlStyle.TextSize;
 172:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "TextSize"),
 173:                              new XAttribute("OldValue", dwgStyle.TextSize), new XAttribute("NewValue", xmlStyle.TextSize));
 174:                          temp.Add(mod);
 175:                      }
 176:                      if (dwgStyle.XScale != xmlStyle.XScale)
 177:                      {
 178:                          dwgStyle.XScale = xmlStyle.XScale;
 179:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "XScale"),
 180:                              new XAttribute("OldValue", dwgStyle.XScale), new XAttribute("NewValue", xmlStyle.XScale));
 181:                          temp.Add(mod);
 182:                      }
 183:                      if (dwgStyle.IsVertical != xmlStyle.IsVertical)
 184:                      {
 185:                          dwgStyle.IsVertical = xmlStyle.IsVertical;
 186:                          XElement mod = new XElement("ChangeProperty", new XAttribute("PropertyName", "IsVertical"),
 187:                              new XAttribute("OldValue", dwgStyle.IsVertical), new XAttribute("NewValue", xmlStyle.IsVertical));
 188:                          temp.Add(mod);
 189:                      }                    
 190:                      trs.Commit();
 191:                  }
 192:              }
 193:          }
 194:          /// <summary>
 195:          /// Синхронизировать текстовый стиль с его одноимённым описанием в xml-файле
 196:          /// </summary>
 197:          /// <param name="styleName">Имя стиля</param>
 198:          /// <param name="log">Ссылка на объект, в котором инкапсулируется лог хода выполнения операций</param>
 199:          public override void SynchronizationStyle(string styleName, ref XElement log)
 200:          {
 201:              SynchronizationStyle(styleName);
 202:              log.Add(temp);
 203:          }
 204:   
 205:          /// <summary>
 206:          /// Создать xml-описание текстового стиля
 207:          /// </summary>
 208:          /// <param name="style">Исходный объект текстового стиля</param>
 209:          /// <returns>Xml-объект, содержащий в себе полное описание текстового стиля</returns>
 210:          public override XElement CreateXml(TextStyleTableRecord style)
 211:          {
 212:              XElement xTextStyle = new XElement("TextStyle",  new XAttribute("Name", style.Name), new XAttribute("Use", true));
 213:   
 214:              XElement xFont = new XElement("Font", new XAttribute("FontName", style.FileName), new XAttribute("BigFont", style.BigFontFileName));
 215:              xTextStyle.Add(xFont);
 216:              XElement xSize = new XElement("Size", new XAttribute("Annotative", style.Annotative), 
 217:                  new XAttribute("OrientationToLayout", style.PaperOrientation), new XAttribute("TextHeight", style.TextSize));
 218:              xTextStyle.Add(xSize);
 219:   
 220:              XElement xEffects = new XElement("Effects", new XAttribute("UpsideDown", style.FlagBits),
 221:                  new XAttribute("Backwards", style.FlagBits), new XAttribute("Vertical", style.IsVertical),
 222:                  new XAttribute("WidthFactor", style.XScale), new XAttribute("ObliqueAngle", style.ObliquingAngle * 108 / Math.PI));
 223:              xTextStyle.Add(xEffects);
 224:              return xTextStyle;
 225:          }
 226:          
 227:          /// <summary>
 228:          /// Проверка текстового стиля на соответствие стандарту, указанному в xml-файле
 229:          /// </summary>
 230:          /// <param name="styleName">Имя стиля</param>
 231:          /// <returns>True - стиль соответствует требованиям стандарта; 
 232:          /// False - стиль не соответствует требованиям стандарта</returns>
 233:          public override bool EqualWithXml(string styleName)
 234:          {
 235:              TextStyleTableRecord ts1 = GetDrawingStyle(styleName);
 236:              TextStyleTableRecord ts2 = GetStyleFromXml(styleName);
 237:              if (!ExistInDrawing(styleName))
 238:              {
 239:                  throw new System.Exception("В чертежа отсутствует стиль текста с указанным именем!");
 240:              }
 241:              if (ExistInXml(styleName))
 242:              {
 243:                  return (ts1.Name.ToUpper() == ts2.Name.ToUpper() &&
 244:                  ts1.FileName.ToUpper() == ts2.FileName.ToUpper() &&
 245:                  ts1.Annotative == ts2.Annotative &&
 246:                  ts1.ObliquingAngle == ts2.ObliquingAngle &&
 247:                  ts1.PaperOrientation == ts2.PaperOrientation &&
 248:                  ts1.Font == ts2.Font &&
 249:                  ts1.BigFontFileName == ts2.BigFontFileName &&
 250:                  ts1.FlagBits == ts2.FlagBits &&
 251:                  ts1.TextSize == ts2.TextSize &&
 252:                  ts1.XScale == ts2.XScale &&
 253:                  ts2.IsVertical == ts2.IsVertical);
 254:              }
 255:              else
 256:              {
 257:                  return false;
 258:              }
 259:          }
 260:          
 261:          /// <summary>
 262:          /// Метод проверяет, есть ли в базе данных чертежа текстовый стиль с определённым именем
 263:          /// </summary>
 264:          /// <param name="styleName">Имя текстового стиля</param>
 265:          /// <returns>True - стиль найден; False - стиля с таким именем в базе данных чертежа нет</returns>
 266:          public override bool ExistInDrawing(string styleName)
 267:          {
 268:              using (Transaction trs = Drawing.TransactionManager.StartTransaction())
 269:              {
 270:                  TextStyleTable tst = (TextStyleTable)trs.GetObject(db.TextStyleTableId, OpenMode.ForRead);
 271:                  foreach (ObjectId item in tst)
 272:                  {
 273:                      TextStyleTableRecord ts = (TextStyleTableRecord)trs.GetObject(item, OpenMode.ForRead);
 274:                      if (ts.Name.ToUpper() == styleName.ToUpper()) return true;
 275:                  }
 276:                  return false;
 277:              }
 278:          }
 279:   
 280:          /// <summary>
 281:          /// Получить все текстовые стили, имеющиеся в чертеже
 282:          /// </summary>
 283:          /// <returns>Возвращается массив объектов текстовых стилей</returns>
 284:          public override TextStyleTableRecord[] GetDrawingStyles()
 285:          {
 286:              List<TextStyleTableRecord> list = new List<TextStyleTableRecord>();
 287:              using (Transaction trs = Drawing.TransactionManager.StartTransaction())
 288:              {
 289:                  TextStyleTable tst = (TextStyleTable)trs.GetObject(db.TextStyleTableId, OpenMode.ForRead);
 290:                  foreach (ObjectId item in tst)
 291:                  {
 292:                      list.Add((TextStyleTableRecord)trs.GetObject(item, OpenMode.ForRead));                    
 293:                  }
 294:                  return list.ToArray();
 295:              }
 296:          }
 297:          /// <summary>
 298:          /// Получение объекта текстового стиля, соответствующего требованиям стандарта
 299:          /// </summary>
 300:          /// <param name="styleName">Имя текстового стиля</param>
 301:          /// <returns>Возвращается объект текстового стиля</returns>
 302:          public override TextStyleTableRecord GetStyleFromXml(string styleName)
 303:          {
 304:              TextStyleTableRecord ts = new TextStyleTableRecord();
 305:   
 306:              //Считываю из xml-файла настройки, относящиеся к нужному текстовому стилю
 307:              //************************************************************************************************************************
 308:              XElement xTextStyle = XElement.Load("AcadStyles.xml").Element("Styles").Element("TextStyles").Elements("TextStyle")
 309:                  .Where(n => Boolean.Parse(n.Attribute("Use").Value) == true && n.Attribute("Name").Value == styleName).DefaultIfEmpty().First();
 310:   
 311:              //Если в xml-файле отсутствует текстовый стиль с указанным именем - сообщаю пользователю об этом и завершаю работу.
 312:              if (xTextStyle == null)
 313:              {
 314:                  //Вывожу в командной строке AutoCAD текст ошибки и выполняю откат транзакции
 315:                  ed.WriteMessage(string.Format("\n{0}", "В файле 'AcadStyles.xml' отсутствует описание текстового стиля с указанным Вами именем."));
 316:                  return null;
 317:              }
 318:              //Считываю значения всех свойств текстового стиля:
 319:              string fontName = xTextStyle.Element("Font").Attribute("FontName").Value;
 320:              string bigFont = xTextStyle.Element("Font").Attribute("BigFont").Value;
 321:   
 322:              bool annotative = Boolean.Parse(xTextStyle.Element("Size").Attribute("Annotative").Value);
 323:              bool orientationToLayout = Boolean.Parse(xTextStyle.Element("Size").Attribute("OrientationToLayout").Value);
 324:              double textHeight = Double.Parse(xTextStyle.Element("Size").Attribute("TextHeight").Value);
 325:   
 326:              bool upsideDown = Boolean.Parse(xTextStyle.Element("Effects").Attribute("UpsideDown").Value);
 327:              bool backwards = Boolean.Parse(xTextStyle.Element("Effects").Attribute("Backwards").Value);
 328:              bool vertical = Boolean.Parse(xTextStyle.Element("Effects").Attribute("Vertical").Value);
 329:              double widthFactor = Double.Parse(xTextStyle.Element("Effects").Attribute("WidthFactor").Value);
 330:              double obliqueAngle = Double.Parse(xTextStyle.Element("Effects").Attribute("ObliqueAngle").Value);
 331:              //************************************************************************************************************************
 332:              ts.Name = styleName;
 333:              ts.FileName = fontName;
 334:              ts.Annotative = (AnnotativeStates)Enum.Parse(typeof(AnnotativeStates), annotative.ToString());
 335:              ts.ObliquingAngle = obliqueAngle * Math.PI / 180;
 336:              ts.SetPaperOrientation(orientationToLayout);
 337:              ts.Font = new Autodesk.AutoCAD.GraphicsInterface.FontDescriptor();
 338:              ts.BigFontFileName = bigFont;
 339:              ts.FlagBits = (byte)0;
 340:              ts.FlagBits += upsideDown ? (byte)2 : (byte)0;
 341:              ts.FlagBits += backwards ? (byte)4 : (byte)0;
 342:              ts.TextSize = textHeight;
 343:              ts.XScale = widthFactor;
 344:              ts.IsVertical = vertical;
 345:              return ts;
 346:          }
 347:   
 348:          /// <summary>
 349:          /// Удаляем текстовый стиль из базы данных чертежа
 350:          /// </summary>
 351:          /// <param name="styleName">Имя удаляемого текстового стиля</param>
 352:          public override void RemoveStyleFromDrawing(string styleName)
 353:          {
 354:              if (ExistInDrawing(styleName))
 355:              {
 356:                  lock (Drawing.LockDocument())
 357:                  {
 358:                      using (Transaction trs = Drawing.TransactionManager.StartTransaction())
 359:                      {
 360:                          TextStyleTable tst = (TextStyleTable)trs.GetObject(db.TextStyleTableId, OpenMode.ForRead);
 361:                          TextStyleTableRecord ts = (TextStyleTableRecord)trs.GetObject(tst[styleName], OpenMode.ForRead);
 362:                          if (db.Textstyle != ts.ObjectId)
 363:                          {
 364:                              ts.Erase();
 365:                              trs.Commit();
 366:                          }
 367:                          else
 368:                          {
 369:                              db.Textstyle = GetDrawingStyles()[0].ObjectId;
 370:                          }
 371:                      }
 372:                  }
 373:              }
 374:          }
 375:      }
 376:  }

В данном коде я пока оставил не переопределёнными два метода: CanBeRemoved и ChangeStyleForPrimitives, т.к. разбираюсь с тем, как грамотней извлечь любые примитивы, использующие рассматриваемый стиль.


Comments