В качестве исходного материала возьмём скрипт на JavaScript, преобразующий абзацы, заданные стилем «ramka» и «inv», в таблицу.
	
	
	
		
Необходимый инструментарий: MS Visual C++ .NET 2003 (далее MSVC), Adobe InDesign/InCopy CS SDK (далее SDK). SDK я установил в каталог С:\Adobe\InDesignCSAndInCopyCSSDK (далее <SDK>). Adobe InDesign CS я установил в каталог С:\Adobe\InDesignCS (далее <ID>).
Первым делом нам необходимо сделать «скелет» плагина. Для этого воспользуемся программой DollyXS, входящей в состав SDK (<SDK>\devtools\sdktools\dollyxs). Запустим на выполнение файл dollyxsgui.bat и в появившемся окне заполним следующие поля:
Теперь самое время приступить к наполнению нашего плагина необходимой функциональностью.
1. Изменим название пункта меню вызывающего наш плагин: откроем файл «Brdr_enUS.fr» (содержит строки, которые подлежат локализации на другие языки) и изменим строку
	
	
	
		
на
	
	
	
		
2. Добавим код предназначенный для взаимодействия с «selection» (подробнее см. <SDK>\docs\guides\selection.pdf, стр. 35-46).
2.1. Добавим в наш проект файлы IBrdrSuite.h и BrdrSuiteASB.cpp (меню «Project/Add Existing Item…»).
2.2. В раздел «ClassDescriptionTable» файла «Brdr.fr» добавим строки
 
	
	
	
		
2.3. В файле «BrdrActionComponent.cpp» содержимое метода
	
	
	
		
заменим на
  
	
	
	
		
2.4. В файл «BrdrFactoryList.h» добавим
	
	
	
		
2.5. В файл «BrdrID.h» добавим
	
	
	
		
3. Теперь приступим к рассмотрению реализации алгоритма замены абзаца на таблицу (файл «BrdrSuiteLayoutCSB.cpp» приведён с сокращениями).
	
	
	
		
Получим указатель на «text model» - объект, управляющий символами и форматированием текстовых блоков
(<SDK>\docs\guides\programmingguide.pdf, стр. 359):
    
	
	
	
		
Получим указатель на интерфейс атрибутов объекта содержащего форматирование абзаца (<SDK>\docs\guides\programmingguide.pdf, стр. 369):
    
	
	
	
		
Получим указатель на интерфейс таблицы стилей текущего документа:
    
	
	
	
		
Получим UID (уникальный идентификатор) объекта представляющего стиль параграфа в базе данных документа:
    
	
	
	
		
Получим UID объекта представляющего цвет в базе данных документа:
    
	
	
	
		
Найдём длину содержимого текстового блока:
    
	
	
	
		
Найдём длину абзаца:
      
	
	
	
		
Получим UID объекта представляющего стиль параграфа в текущей позиции:
     
	
	
	
		
Зададим цвет текста абзаца:
          
	
	
	
		
Преобразуем абзац в таблицу:
          
	
	
	
		
Получим указатель на «table model» - объект, управляющий таблицами (<SDK>\docs\guides\tables.pdf, стр. 29):
          
	
	
	
		
Зададим цвет фона таблицы:
          
	
	
	
		
В приложенном файле находятся:
- версия этого туториала в формате Word;
- откомпилированный плагин;
- исходные тексты плагина (расположены в каталоге plugin).
				
			
		Код: 
	
	const ramka = "ramka";
const inv = "inv";
with(app)
{
  var myDoc = activeDocument;
  var myStory = myDoc.selection[0].parentStory;
  var myParagraphs = myStory.paragraphs;
  var paperColor = myDoc.swatches.item("Paper");
  var blackColor = myDoc.swatches.item("Black");
  for(var myCount=0; myCount < myStory.paragraphs.length; myCount ++)
  {
    var myStyle = myParagraphs[myCount].appliedParagraphStyle.name;
    var myParagraph = myParagraphs[myCount];
    if(myStyle == ramka)
    {
      var myStart = myParagraph.characters[0].index;
      var myEnd = myParagraph.characters[-2].index;
      var myText = myStory.characters.itemByRange(myStart, myEnd);
      var myTable = myText.convertToTable();
      var myCell = myTable.cells[0];
      myCell.fillColor = paperColor;
      myCell.paragraphs[0].fillColor = blackColor;
    }
    else if(myStyle == inv)
    {
      var myStart = myParagraph.characters[0].index;
      var myEnd = myParagraph.characters[-2].index;
      var myText = myStory.characters.itemByRange(myStart, myEnd);
      var myTable = myText.convertToTable();
      var myCell = myTable.cells[0];
      myCell.fillColor = blackColor;
      myCell.paragraphs[0].fillColor = paperColor;
    }
  }
}
alert("ok");Необходимый инструментарий: MS Visual C++ .NET 2003 (далее MSVC), Adobe InDesign/InCopy CS SDK (далее SDK). SDK я установил в каталог С:\Adobe\InDesignCSAndInCopyCSSDK (далее <SDK>). Adobe InDesign CS я установил в каталог С:\Adobe\InDesignCS (далее <ID>).
Первым делом нам необходимо сделать «скелет» плагина. Для этого воспользуемся программой DollyXS, входящей в состав SDK (<SDK>\devtools\sdktools\dollyxs). Запустим на выполнение файл dollyxsgui.bat и в появившемся окне заполним следующие поля:
Generate Windows project to the folder below: C:\Adobe\InDesignCSAndInCopyCSSDK/build/win/sdkprj
Output folder for the generated code below: C:\Adobe\InDesignCSAndInCopyCSSDK/source/sdksamples
Plug-in long name: border
Plug-in short name: Brdr
Plug-in prefix ID: 0x78470
В итоге в каталоге <SDK>\source\border мы получим набор файлов-исходников для «скелета» плагина. Откомпилируем их с целью получения двоичного образа плагина (файл с расширением pln). Для этого загрузим среду разработки MSVC, откроем проект нашего плагина (меню «File/Open solution»), выберем релизную конфигурацию (меню «Build/Configuration Manager…, Active Solution Configuration: Release») и запустим процесс компиляции (меню «Project/Build solution»). В результате в каталоге <SKD>\build\win\release\sdk мы получим файл border.pln. Скопируем его в каталог <ID>\Plug-Ins. Загрузим InDesign.Output folder for the generated code below: C:\Adobe\InDesignCSAndInCopyCSSDK/source/sdksamples
Plug-in long name: border
Plug-in short name: Brdr
Plug-in prefix ID: 0x78470
Теперь самое время приступить к наполнению нашего плагина необходимой функциональностью.
1. Изменим название пункта меню вызывающего наш плагин: откроем файл «Brdr_enUS.fr» (содержит строки, которые подлежат локализации на другие языки) и изменим строку
		Код: 
	
	kBrdrMenuItem1MenuItemKey,  "MenuItem1[US]",
		Код: 
	
	kBrdrMenuItem1MenuItemKey,  "Start bordering",2. Добавим код предназначенный для взаимодействия с «selection» (подробнее см. <SDK>\docs\guides\selection.pdf, стр. 35-46).
2.1. Добавим в наш проект файлы IBrdrSuite.h и BrdrSuiteASB.cpp (меню «Project/Add Existing Item…»).
2.2. В раздел «ClassDescriptionTable» файла «Brdr.fr» добавим строки
		Код: 
	
	 AddIn
    {
        kIntegratorSuiteBoss,
        kInvalidClass,
        {
            IID_IBORDERSUITE, kBorderSuiteASBImpl,
        }
    },
  AddIn
    {
        kLayoutSuiteBoss,
        kInvalidClass,
        {
            IID_IBORDERSUITE, kBorderSuiteLayoutCSBImpl,
        }
    },
    CAlert::InformationAlert(kBrdrMenuItem1StringKey);2.3. В файле «BrdrActionComponent.cpp» содержимое метода
		Код: 
	
	void BrdrActionComponent::DoMenuItem1(IActiveContext* ac)заменим на
		Код: 
	
	do
  {
    TESTNIL(IActiveContext, ac)
    InterfacePtr<IBorderSuite> borderSuite(ac->GetContextSelection(), UseDefaultIID());
    TESTNIL(IBorderSuite, borderSuite)
    if(borderSuite->CanBordering()) borderSuite->DoBordering();
  }
  while(kFalse);2.4. В файл «BrdrFactoryList.h» добавим
		Код: 
	
	REGISTER_PMINTERFACE(BorderSuiteASB, kBorderSuiteASBImpl)
REGISTER_PMINTERFACE(BorderSuiteLayoutCSB, kBorderSuiteLayoutCSBImpl)2.5. В файл «BrdrID.h» добавим
		Код: 
	
	// InterfaceIDs:
DECLARE_PMID(kInterfaceIDSpace, IID_IBORDERSUITE, kBrdrPrefix + 0)
// ImplementationIDs:
DECLARE_PMID(kImplementationIDSpace, kBorderSuiteASBImpl, kBrdrPrefix + 1)
DECLARE_PMID(kImplementationIDSpace, kBorderSuiteLayoutCSBImpl, kBrdrPrefix + 2)3. Теперь приступим к рассмотрению реализации алгоритма замены абзаца на таблицу (файл «BrdrSuiteLayoutCSB.cpp» приведён с сокращениями).
		Код: 
	
	ErrorCode BorderSuiteLayoutCSB::DoBordering()
{
  ErrorCode status = kFailure;
  do
  {Получим указатель на «text model» - объект, управляющий символами и форматированием текстовых блоков
(<SDK>\docs\guides\programmingguide.pdf, стр. 359):
		Код: 
	
	const UIDRef textModelUIDRef = GetTextModelUIDRef();
    InterfacePtr<ITextModel> textModel(textModelUIDRef, UseDefaultIID());
    IDocument* document = gSession->GetActiveContext()->GetContextDocument();
    IDataBase* database = ::GetDataBase(textModel);
    Utils<ITableUtils> tableUtils;Получим указатель на интерфейс атрибутов объекта содержащего форматирование абзаца (<SDK>\docs\guides\programmingguide.pdf, стр. 369):
		Код: 
	
	InterfacePtr<IAttributeStrand> paraAttributeStrand(static_cast<IAttributeStrand*>(textModel->QueryStrand(kParaAttrStrandBoss, IID_IATTRIBUTESTRAND)));
    InterfacePtr<IStrand> paraStrand(paraAttributeStrand, UseDefaultIID());Получим указатель на интерфейс таблицы стилей текущего документа:
		Код: 
	
	InterfacePtr<const IStyleNameTable> styleNameTable(document->GetDocWorkSpace(), IID_IPARASTYLENAMETABLE);Получим UID (уникальный идентификатор) объекта представляющего стиль параграфа в базе данных документа:
		Код: 
	
	const UID paraStyle1UID = styleNameTable->FindByName(PMString("ramka"));Получим UID объекта представляющего цвет в базе данных документа:
		Код: 
	
	const UID swatch1UID = Utils<ISwatchUtils>()->GetNamedSwatch(PMString("Black"), database);
    TextIndex position = 0;
    int32 length = 0;Найдём длину содержимого текстового блока:
		Код: 
	
	const int32 totalLength = textModel->TotalLength();
    while(length < totalLength)
    {
      bool paraChanged = false;Найдём длину абзаца:
		Код: 
	
	const int32 paraLength = paraStrand->GetRunLength(position);Получим UID объекта представляющего стиль параграфа в текущей позиции:
		Код: 
	
	 int32 tmp = 0;
      const UID paraStyleUID = paraAttributeStrand->GetStyleUID(position, &tmp);
      if(paraStyleUID != kInvalidUID)
      {
        const Text::StoryRange textRange(position, position + paraLength - 1);
        if(paraStyleUID == paraStyle1UID)
        {Зададим цвет текста абзаца:
		Код: 
	
	SetTextColor(textModel, position, paraLength, swatch1UID);Преобразуем абзац в таблицу:
		Код: 
	
	const UIDRef tableUIDRef = tableUtils->ConvertTextToTable(textModel, textRange);Получим указатель на «table model» - объект, управляющий таблицами (<SDK>\docs\guides\tables.pdf, стр. 29):
		Код: 
	
	InterfacePtr<ITableModel> tableModel(tableUIDRef, UseDefaultIID());Зададим цвет фона таблицы:
		Код: 
	
	const GridArea cell(0, 0, 1, 1);
          SetFillColor(tableModel, cell, swatch2UID);
          paraChanged = true;
        }
      }
      position += paraChanged ? 2 : paraLength;
      length += paraLength;
    }
    status = kSuccess;
  }
  while(kFalse);
  return(status);
}В приложенном файле находятся:
- версия этого туториала в формате Word;
- откомпилированный плагин;
- исходные тексты плагина (расположены в каталоге plugin).
 
	
 
 
		