В качестве исходного материала возьмём скрипт на 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>).Код: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");
Первым делом нам необходимо сделать «скелет» плагина. Для этого воспользуемся программой DollyXS, входящей в состав SDK (<SDK>\devtools\sdktools\dollyxs). Запустим на выполнение файл dollyxsgui.bat и в появившемся окне заполним следующие поля:
Generate Windows project to the folder below: C:\Adobe\InDesignCSAndInCopyCSSDK/build/win/sdkprjВ итоге в каталоге <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]",
2. Добавим код предназначенный для взаимодействия с «selection» (подробнее см. <SDK>\docs\guides\selection.pdf, стр. 35-46).Код:kBrdrMenuItem1MenuItemKey, "Start bordering",
2.1. Добавим в наш проект файлы IBrdrSuite.h и BrdrSuiteASB.cpp (меню «Project/Add Existing Item…»).
2.2. В раздел «ClassDescriptionTable» файла «Brdr.fr» добавим строки
2.3. В файле «BrdrActionComponent.cpp» содержимое методаКод:AddIn { kIntegratorSuiteBoss, kInvalidClass, { IID_IBORDERSUITE, kBorderSuiteASBImpl, } }, AddIn { kLayoutSuiteBoss, kInvalidClass, { IID_IBORDERSUITE, kBorderSuiteLayoutCSBImpl, } }, CAlert::InformationAlert(kBrdrMenuItem1StringKey);
заменим наКод:void BrdrActionComponent::DoMenuItem1(IActiveContext* ac)
2.4. В файл «BrdrFactoryList.h» добавимКод:do { TESTNIL(IActiveContext, ac) InterfacePtr<IBorderSuite> borderSuite(ac->GetContextSelection(), UseDefaultIID()); TESTNIL(IBorderSuite, borderSuite) if(borderSuite->CanBordering()) borderSuite->DoBordering(); } while(kFalse);
2.5. В файл «BrdrID.h» добавимКод:REGISTER_PMINTERFACE(BorderSuiteASB, kBorderSuiteASBImpl) REGISTER_PMINTERFACE(BorderSuiteLayoutCSB, kBorderSuiteLayoutCSBImpl)
3. Теперь приступим к рассмотрению реализации алгоритма замены абзаца на таблицу (файл «BrdrSuiteLayoutCSB.cpp» приведён с сокращениями).Код:// InterfaceIDs: DECLARE_PMID(kInterfaceIDSpace, IID_IBORDERSUITE, kBrdrPrefix + 0) // ImplementationIDs: DECLARE_PMID(kImplementationIDSpace, kBorderSuiteASBImpl, kBrdrPrefix + 1) DECLARE_PMID(kImplementationIDSpace, kBorderSuiteLayoutCSBImpl, kBrdrPrefix + 2)
Получим указатель на «text model» - объект, управляющий символами и форматированием текстовых блоковКод:ErrorCode BorderSuiteLayoutCSB::DoBordering() { ErrorCode status = kFailure; do {
(<SDK>\docs\guides\programmingguide.pdf, стр. 359):
Получим указатель на интерфейс атрибутов объекта содержащего форматирование абзаца (<SDK>\docs\guides\programmingguide.pdf, стр. 369):Код:const UIDRef textModelUIDRef = GetTextModelUIDRef(); InterfacePtr<ITextModel> textModel(textModelUIDRef, UseDefaultIID()); IDocument* document = gSession->GetActiveContext()->GetContextDocument(); IDataBase* database = ::GetDataBase(textModel); Utils<ITableUtils> tableUtils;
Получим указатель на интерфейс таблицы стилей текущего документа:Код:InterfacePtr<IAttributeStrand> paraAttributeStrand(static_cast<IAttributeStrand*>(textModel->QueryStrand(kParaAttrStrandBoss, IID_IATTRIBUTESTRAND))); InterfacePtr<IStrand> paraStrand(paraAttributeStrand, UseDefaultIID());
Получим UID (уникальный идентификатор) объекта представляющего стиль параграфа в базе данных документа:Код:InterfacePtr<const IStyleNameTable> styleNameTable(document->GetDocWorkSpace(), IID_IPARASTYLENAMETABLE);
Получим UID объекта представляющего цвет в базе данных документа:Код:const UID paraStyle1UID = styleNameTable->FindByName(PMString("ramka"));
Найдём длину содержимого текстового блока:Код: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;
Получим UID объекта представляющего стиль параграфа в текущей позиции:Код:const int32 paraLength = paraStrand->GetRunLength(position);
Зададим цвет текста абзаца:Код: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);
Получим указатель на «table model» - объект, управляющий таблицами (<SDK>\docs\guides\tables.pdf, стр. 29):Код:const UIDRef tableUIDRef = tableUtils->ConvertTextToTable(textModel, textRange);
Зададим цвет фона таблицы:Код: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).


Цитата
