В качестве исходного материала возьмём скрипт на 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).