Macromedia InDesign - CS6 Plug-In Development User Guide

ADOBE® INDESIGN® CS6
GETTING STARTED WITH ADOBE
INDESIGN CS6
PLUG-IN DEVELOPMENT
2012 Adobe Systems Incorporated. All rights reserved.
If this guide is distributed with software that includes an end user agreement, this guide, as well as the software described in it, is furnished under license and may be used or copied only in accordance with the terms of such license. Except as permitted by any such license, no part of this guide may be reproduced, stored in a retrieval system, or transmitted, in any form or by any means, electronic, mechanical, recording, or otherwise, without the prior written permission of Adobe Systems Incorporated. Please note that the content in this guide is protected under copyright law even if it is not distributed with software that includes an end user license agreement.
The content of this guide is furnished for informational use only, is subject to change without notice, and should not be construed as a commitment by Adobe Systems Incorporated. Adobe Systems Incorporated assumes no responsibility or liability for any errors or inaccuracies that may appear in the informational content contained in this guide.
Please remember that existing artwork or images that you may want to include in your project may be protected under copyright law. The unauthorized incorporation of such material into your new work could be a violation of the rights of the copyright owner. Please be sure to obtain any permission required from the copyright owner.
Any references to company names in sample templates are for demonstration purposes only and are not intended to refer to any actual organization.
Adobe, the Adobe logo, InCopy, and InDesign are either registered trademarks or trademarks of Adobe Systems Incorporated in the United States and/or other countries. Windows s either a registered trademark or a trademark of Microsoft Corporation in the United States and/or other countries. Mac OS is a trademark of Apple Computer, Incorporated, registered in the United States and other countries. All other trademarks are the property of their respective owners.
Adobe Systems Incorporated, 345 Park Avenue, San Jose, California 95110, USA. Notice to U.S. Government End Users. The Software and Documentation are “Commercial Items,” as that term is defined at 48 C.F.R. §2.101, consisting of “Commercial Computer Software” and “Commercial Computer Software Documentation,” as such terms are used in 48 C.F.R. §12.212 or 48 C.F.R. §227.7202, as applicable. Consistent with 48 C.F.R. §12.212 or 48 C.F.R. §§227.7202-1 through
227.7202-4, as applicable, the Commercial Computer Software and Commercial Computer Software Documentation are being licensed to U.S. Government end users (a) only as Commercial Items and (b) with only those rights as are granted to all other end users pursuant to the terms and conditions herein. Unpublished-rights reserved under the copyright laws of the United States. Adobe Systems Incorporated, 345 Park Avenue, San Jose, CA 95110-2704, USA. For U.S. Government End Users, Adobe agrees to comply with all applicable equal opportunity laws including, if appropriate, the provisions of Executive Order 11246, as amended, Section 402 of the Vietnam Era Veterans Readjustment Assistance Act of 1974 (38 USC 4212), and Section 503 of the Rehabilitation Act of 1973, as amended, and the regulations at 41 CFR Parts 60-1 through 60-60, 60-250, and 60-741. The affirmative action clause and regulations contained in the preceding sentence shall be incorporated by reference.
Contents
1 Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
About this document . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
About InDesign plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
Plug-in classification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
How InDesign plug-ins are developed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2 Getting Started with the InDesign SDK . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
SDK Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
Development environments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
Anatomy of a plug-in’s project files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 15
Tutorial: Creating a plug-in from scratch . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
Step 1: Use DollyXs to generate a dialog-based plug-in project . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
Files included in the project generated by DollyXs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
Create an InDesign SDK Xcode project from the template (Mac OS only) . . . . . . . . . . . . . . . . . . . . . . 25
Step 2: Add a DropDownListWidget to the dialog . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
Step 3: Add a TextEditBoxWidget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
Step 4: Add a StaticTextWidget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
Using resources in plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
Step 5: Obtain a value from DropDownListWidget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Step 6: Get the text in the TextEditBoxWidget . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Using boss classes in plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
Using interfaces in plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Using databases and objects in plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Step 7: Insert a string into a text frame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
Using commands in plug-ins . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Step 8: Disable the menu with no text selection . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
Step 9: Initialize dialog widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
Conclusion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
3 Introduction to ODFRC . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
FR file compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
FR file contents . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
PluginVersion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
PluginDependency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
ExtraPluginInfo . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
3
4
CriticalTags and IgnoreTags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
SchemaList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
ImplementationAlias . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
ClassDescriptionTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
FactoryList . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
LocaleIndex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
StringTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
UserErrorTable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
Other resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
4 Introduction to the InDesign Object Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Boss classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
Writing your own interface . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
Writing your own implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
Constructing a boss instance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Persistence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Making a boss persistent . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Writing your own persistent implementation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Examples of Persistent Implementations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
Changing persistent data with commands . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
Writing your own command . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
Facades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
PluginVersion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
The lifecycle of a plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
5 Localization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
InDesign locales . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Checking the locale in C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Controlling plug-in loading . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
PMString . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
String-translation tables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Localizing other resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
6 Building Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Boss-object web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Iterating the draw order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Service providers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Startup and shutdown services . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81
Responders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
5
Draw event handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
Page-item adornments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Selection suites . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
List Plug-ins in Extension Manager . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 86
7 InDesign Server Plug-in Techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Introduction . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Terminology . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
Key concepts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
How desktop InDesign and InDesign Server differ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 90
Minimum requirements for an InDesign Server plug-in . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
Removing calls to APIs that depend on active context or something in “front” . . . . . . . . . . . . . . . . . 94
Using MessageLog or IErrorList in place of custom error/warning dialogs (other than CAlert) . . 95
Adding custom features to InDesign Server . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
Performance considerations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 97
64-bit plug-ins (Windows only) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
Testing techniques . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
8 Feature Development with Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Scripting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
Scripting versus C++ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
Building blocks for using ExtendScript to implement a feature with scripting . . . . . . . . . . . . . . . . . 111
Tips and hints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
Building blocks for using ActionScript to implement user interfaces . . . . . . . . . . . . . . . . . . . . . . . . . 124
Frequently asked questions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
Resources . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
1

Introduction

This document is for C++ programmers who want to learn how to write Adobe® InDesign® plug-ins. It also is appropriate reading for experienced InDesign programmers who need a refresher. It is designed to give an introduction to plug-in development, show how to create some simple plug-ins, and teach the architecture behind InDesign products—InDesign, Adobe InCopy®, and Adobe InDesign® Server.

About this document

Chapter 2, “Getting Started with the InDesign SDK introduces the files in the SDK, covers development
tools, and provides an initial plug-in development tutorial. If you are new to InDesign development, completing the tutorial in that chapter will provide you the context necessary to review or try what is discussed in the rest of this document.
Chapter 3, “Introduction to ODFRC.” InDesign makes heavy use of the OpenDoc Framework Resource
Compiler. This chapter introduces some of the most common resources types that you will encounter in ODFRC FR files,
Chapter 4, “Introduction to the InDesign Object Model,” discusses boss classes, interfaces, persistence,
commands, facades, and the lifecycle of a plug-in.
Chapter 5, “Localization,” covers the basic mechanisms for localizing strings and other resources used
by your plug-in.
Chapter 6, “Building Blocks,” introduces a set of concepts and patterns that are used in many different
scenarios. These concepts are the building blocks on which you will make things happen with your plug-in.
Chapter 7, “InDesign Server Plug-in Techniques,” provides technical details to help developers create
new plug-ins or port existing plug-ins to use with InDesign Server.
Chapter 8, “Feature Development with Scripting,”describes how to go beyond automation to
developing new features for InDesign. It describes XHTML Export, whichs is a feature developed with ExtendScript, and FlexUIStroke, which is a use- interface sample developed with ActionScript and Creative Suite SDK
After finishing this document, you will be familiar enough with InDesign plug-in development to begin using the sample code, Adobe InDesign Plug-In Programming Guide, and Adobe InDesign SDK Solutions as needed.

About InDesign plug-ins

The InDesign Products SDK provides the necessary files to develop plug-ins for InDesign, InCopy, and InDesign Server. Before getting too far into the technical details, it is important to understand that all InDesign products are developed from the same code base. A plug-in can be written to load under any combination of InDesign products. Many Adobe plug-ins are compiled and deployed with all three applications. Each product application comprises a small executable that loads and initializes plug-ins. Each executable does very little that is recognizable by an end user; instead, nearly all features are
6
CHAPTER 1: Introduction Plug-in classification 7
contributed by plug-ins. This same plug-in architecture used by Adobe Engineering is made available to third-party developers in the InDesign products SDK.
On Windows, plug-in are DLLs with an “.apln” file extension. On Mac OS, they are Frameworks with an “.InDesignPlugin” file extension.

Plug-in classification

There are several ways to classify InDesign plug-ins:
By the applications under which they load. For example, you may create an InCopy-only plug-in.
As model or user-interface plug-ins. A model plug-in writes data to an InDesign document. A
user-interface plug-in provides a user interface. An InDesign plug-in must identify whether it supports model or user-interface operations.
Required or optional plug-ins implement core application features. Third-party plug-ins cannot be
considered required.

How InDesign plug-ins are developed

InDesign is written in C++ and makes heavy use of a resource compiler called ODFRC (OpenDoc Framework Resource Compiler). ODFRC files end with the “.fr” extension and are used for many things, including user interfaces, menus, and localization. Chapter 3, “ overview of most of what you can expect to encounter in an ODFRC file.
Perhaps most significantly, ODFRC is used to define and extend classes in the InDesign object model. These are not C++ classes, but rather an InDesign type of class called a boss. Working with bosses and instantiated boss objects is at the heart of InDesign plug-in development. Bosses are mentioned in passing in Chapter 3, “
“Introduction to the InDesign Object Model.”
Introduction to ODFRC,” then are covered more thoroughly in Chapter 4,
Introduction to ODFRC,” gives a high-level
2

Getting Started with the InDesign SDK

This chapter describes how to get started with the Adobe® InDesign® CS6 Products SDK. It provides an overview of the files in the SDK, instructions for working with the sample plug-ins, a tutorial for creating a basic plug-in, and information about where to go for help.
An InDesign plug-in is an extension library that is loaded dynamically by InDesign. It represents a standard interface to InDesign. On Windows®, it is a dynamic link library; on Mac OS®, it is a dynamic shared library packaged in a framework.

SDK Overview

The SDK (denoted in paths by <SDK>) includes several types of files. This section discusses these files and their respective locations within the SDK.

Documentation

To develop InDesign plug-ins, you must understand many concepts and design patterns implemented in C++ and OpenDoc Framework Resource Compiler (ODFRC) resource files. This chapter will help you get started compiling and building simple plug-ins. For a more thorough introduction, read Chapter 3,
“Introduction to ODFRC,” t h r o ug h Chapter 6, “Building Blocks.” After reading those chapters, you should
have enough familiarity with InDesign development to go deeper using the rest of the chapters, the sample code, and remaining documentation.
PDF versions of all SDK documentation are in the following location:
<SDK>/docs/guides
The SDK API Reference is provided in two files:
<SDK>/docs/references/index.chm <SDK>/docs/references/sdkdocs.tar.gz
Both files contain reference documentation for all public APIs and SDK sample code.
The index.chm file is a compressed HTML file for use on Windows. To view the contents, double-click the index.chm file icon.
The sdkdocs.tar.gz archive is for use on Mac OS. To expand this archive, double-click the file. It decompresses to a folder named sdkdocs. To view the reference, double-click on index.html.

Libraries

InDesign plug-in development requires the use of several libraries supplied by Adobe. On Windows, this amounts to only a handful of static lib files. Debug and release versions of these libraries are in the following locations:
<SDK>/build/win/objd <SDK>/build/win/objr
To support 64-bit InDesign Server plug-ins (Windows only), 64-bit versions are in the following location:
8
CHAPTER 2: Getting Started with the InDesign SDK SDK Overview 9
<SDK>/build/win/objdx64 <SDK>/build/win/objrx64
Compiling on the Mac requires many dynamic libraries and Framework files. These files are embedded in a directory structure that resembles the actual application package:
<SDK>/build/mac/debug/packagefolder/contents/macos <SDK>/build/mac/release/packagefolder/contents/macos
Several libraries also are available in the <SDK>/external directory. These libraries originated outside the InDesign engineering team. Windows typically uses these libraries in place; on the Mac, a copy is moved or a symlink is created into the appropriate package folder.

Source code

The InDesign Products SDK contains several different types of source-code files.
The public API
InDesign-specific public headers are in the following directory:
<SDK>\source\public
External APIs
Several header files are in the external folder:
<SDK>\external
These are not InDesign-specific header files, but they may be used in the InDesign code base. One example is the header files for the Boost C++ library, a non-Adobe library that is used in the InDesign code base. Another example is the header files for the Adobe File Library, an Adobe-engineered library that is not specific to InDesign.
Open folder
The goal of the “open” folder is to provide production InDesign user-interface code to developers, as examples of complex InDesign user-interface code, and to provide complete plug-ins. At a minimum, an open plug-in must be able to compile with the Release target. An open plug-in might or might not be able to compile with the Debug target.
The open folder is not a public API: The code may changed or be removed in the next version. Also, open plug-ins are not documented in the SDK.
The open folder has three subfolders:
Components<SDK>/source/open/components/. The source for the plug-ins.
Includes<SDK>/source/open/includes/. Subfolders that group the actual include files into
functional categories.
Interfaces — <SDK>/source/open/interfaces/. Subfolders that group the actual include interface files
into functional categories.
CHAPTER 2: Getting Started with the InDesign SDK SDK Overview 10
Project files for the Open plug-ins are located at: <SDK>/build/mac|win/prj/. The open project files are named with the following extensions:
.open.xcodeproj on Mac
.open.vcproj on Windows
Sample plug-ins
The SDK contains many sample plug-ins. The project files are in the following directory:
<SDK>/build/mac|win/prj
The source files for the sample projects are in the following directory:
<SDK>/source/sdksamples
Every sample has a design document, which is available in the index.chm or corresponding HTML API documents. The design document provides details about the functional area each sample illustrates and the architecture behind the plug-in.
Snippets
The SnippetRunner sample plug-in provides a convenient way to demonstrate and test small snippets of code.
The SnippetRunner interface has a drop-down list to choose the snippet to execute; control buttons to start the snippet, clear the log, and so on; areas to enter text; and a read-only log widget. SnippetRunner offers some services to its client code, such as an API to write to this log widget. The contents of the log can be saved to a file. The logging function is the same, regardless of whether the SnippetRunner is executing in the debug or release version.
Snippet Runner source code is supplied with the SDK in the following directory:
<SDK>/source/sdksamples/snippetrunner
And the project file is located in:
<SDK>/build/win│mac/prj/SnippetRunner.vcproj│xcodeproj
All the SDK code snippets included in Snippet Runner are located in the following directory:
<SDK>/source/sdksamples/codesnippets
For more detail about the SnippetRunner plug-in and the snippet framework, see the API documentation associated with the plug-in.
To facilitate the implementation of a code snippet, a snippet template, SnpTemplate.cpp, is included in the SnippetRunner project. Open this file in the project, and the comment block for the SnpTemplate class provides instructions for creating your own code snippet.
Tools
The <SDK>/devtools folder contains the following folders:
CHAPTER 2: Getting Started with the InDesign SDK Development environments 11
bin — This contains some tools that are essential to InDesign plug-in development. They primarily are used to help compile and merge resources with the plug-in executable. A typical SDK sample project should be set up to use these tools automatically. The projects in different platforms require different sets of tools, but you need not be concerned about how to use them, as long as your project settings are similar to the SDK samples.
scripts — There is a PList.py script on Mac OS for packaging a plug-in executable. It is used only by the
SDK’s Xcode project.
sdktools — This folder contains several tools to help facilitate the development of InDesign plug-ins.
DollyXs is a project wizard for generating a project that is ready to build in the SDK with some basic plug-in functionality, such as hooking up a basic user interface. The later part of this document discusses how to use DollyXs to generate a project.
sdktools/idmltools — This folder contains some Java-based tools for working with IDML, ICML, and
IDMS files. These tools allow you to validate package and nonpackage files, compress and decompress IDML packages, and generate and transform IDML files with XSLT. For details, see the readme file in <SDK>/devtools/sdktools/idmltools/.
statics_reporter — The Static Reporter tool searches InDesign’s object code for global and static
variables, producing a text file for each object file that contains globals or statics.

Development environments

This section describes the required tools and environment for developing plug-ins, how to compile and execute sample code, and how to start a debugging session.

Requirements

The required environment for developing plug-ins for InDesign CS6 varies by operating system.
All systems
The following table lists the basic component requirements for the InDesign CS6 plug-in development environment for all systems:
Required component Notes
Applications: InDesign CS6, Adobe InCopy® CS6, or InDesign Server CS6
OpenDoc Framework Resource Compiler (ODFRC) Included with the InDesign SDK.
We recommend that you have both the debug and release applications. The debug application is instrumented to detect bugs and is essential to successful plug-in development.
1 GB of memory or more (2 GB recommended)
Windows
Developing plug-ins under Windows has the following additional requirements:
CHAPTER 2: Getting Started with the InDesign SDK Development environments 12
Required component Notes
Intel® Pentium® 4 or AMD Athlon® 64 processor or better
Windows XP with Service Pack 2 or later
Visual C++ 10 A component of Visual Studio 2010.
Before building on Windows, you need to alter the environment so Visual Studio knows where to find our custom Adobe build tools, such as ODFRC:
1. Start Visual Studio 2010.
2. Bring up the Visual Studio Options dialog by clicking on the Tools menu and choosing Options.
3. In the widget on the left, expand Projects and Solutions, then click on VC++ Directories.
4. Add the path to your local copy of <SDK>\devtools\bin.
Mac OS
Developing plug-ins under Mac OS has the following additional requirements:
Required component
Intel® processor
Mac OS® X 10.6 or later
Xcode 3.2.5

Compiling and executing sample code

Building a sample plug-in
Start by double-clicking on any SDK sample project.
Windows
1. Use Build > Configuration Manager... to make sure you are building the desired configuration.
2. Choose Build > Clean to remove the previous build artifact.
3. Choose Build > Build to do the build.
Mac OS
1. Use the Active Target drop-down list on the top left corner of the project window to make sure you are building the desired target.
2. Choose Build > Rebuild ### to do a clean rebuild of the project.
CHAPTER 2: Getting Started with the InDesign SDK Development environments 13
Building samples from the command line
There are command-line utilities on both the PC and Mac for building project files. For your convenience, the SDK contains scripts to build all sample projects.
Windows
The devenv command can be used for command-line compilation of a project file. For example, the following builds the debug target of the Basic Dialog project. (The Rebuild option is equivalent to a clean followed by a build.)
devenv BasicDialog.sdk.vcproj /Rebuild Debug
The buildAllSamples.bat file (in <SDK>\build\win\prj) uses devenv to build all Windows sample projects. This script does not check build results. That is up to you. Before running the script, correct the path in the DEVENV variable if necessary. To run the script, type the following commands:
1. cd <SDK>\build\win\prj
2. buildAllSamples.bat
Mac OS
The xcodebuild utility is useful for building XCode projects on the command line. For example, the following builds the release target of the Basic dialog project:
xcodebuild -project BasicDialog.sdk.xcodeproj -target Release build
The buildAllSamples perl script (in <SDK>/build/mac/prj) uses xcodebuild to build all MacOS sample projects. This script does rudimentary error checking. It dies on the first project failure. To run the script, type the following commands:
1. cd <SDK>/build/mac/prj
2. buildAllSamples
Launching InDesign with the samples
For your plug-ins to be used in InDesign, InDesign must know about your plug-ins at launch time. You can do this in one of two ways: Use a special configuration file called PlugInConfig.txt or copy your plug-in to InDesign’s Plug-ins folder.
Using PlugInConfig.txt
1. If InDesign is running, exit it.
2. Go to the inDesign preference folder in the following directory (where <locale> is a locale-specific subdirectory; for example, en_US for English):
Windows XP: C:\Documents and Settings\<user>\Application Data\ Adobe\InDesign\Version 8.0\<locale> Windows Vista: C:\Users\<user>\AppData\Roaming\ Adobe\InDesign\Version 8.0\<locale> Mac OS: <user-home>/Library/Preferences/ Adobe InDesign/Version 8.0/<locale>
3. Create a text file named “PlugInConfig.txt” in that directory, and enter the following text into it:
CHAPTER 2: Getting Started with the InDesign SDK Development environments 14
=Path
4. Edit the sections as desired. For example, the following tells InDesign to load every plug-in in the SDK folder:
Windows:
=Path "C:\Adobe InDesign CS6 Products SDK\build\win\debug\sdk"
Mac OS:
=Path "/Adobe InDesign CS6 Products SDK/build/mac/debug/sdk"
NOTE: You also can use an “=Exclude” tag to exclude a certain plug-in from being loaded. This is useful if you do not want to load everything in the “=Path” folder.
OTE: This is target specific. You cannot launch the release version of InDesign with debug plug-ins. It is
N
convenient to add both debug and release paths, commenting out the target that is not in use. For single-line comments, start the comment line with a “;” (semicolon).
5. Save the PlugInConfig.txt file.
6. Restart InDesign.
7. Verify that the set of plug-ins loaded by selecting the About Plug-ins menu.
Moving a plug-in to the Plug-ins folder
By default, all SDK samples are built into the following folder:
<SDK>/build/win│mac/debug│release/sdk
You can move the plug-in(s) that you want to load with InDesign from that path into the following folder:
<InDesign Application Folder>/Plug-ins
Having the project build directly into the Plug-ins folder
You can change the project setting so the plug-in binary is built directly into the InDesign application’s Plug-ins folder.
On Windows, the project’s output setting is specified in the Visual Studio project’s Properties > Configuration Properties > Linker > General > Output File.
On Mac OS, the project’s output setting is specified in the Xcode project’s ID_SDK_DIR variable in each Tar ge t.

Starting a debugging session from your plug-in project

Windows
1. From your project window, choose Debug > Start Debugging.
A dialog pops up to prompt you to select the executable file for the debug session.
2. Under the “Executable file name” drop-down list, select Browse and browse to the InDesign.exe in your InDesign CS6 folder.
CHAPTER 2: Getting Started with the InDesign SDK Anatomy of a plug-in’s project files 15
3. Select the InDesign.exe and click OK to begin the debugging session.
Mac OS
To debug an InDesign plug-in from an Xcode project, you need to define an executable environment. Because you are building an InDesign plug-in, you need to tell Xcode where to find the host application, InDesign, when you try to start your plug-in from the Xcode project. To define a new executable:
1. Find the Executable group under the Groups & Files pane of the project window. Right-click on Executables to bring up its contextual menu.
2. Choose Add > New custom executables. An executables set-up assistant is displayed.
3. Give the executable a name.
4. In Executable Paths, specify the path to InDesign CS6.
5. Select the project to add for the executable. This should be the current project you are trying to debug.
6. Click Finish. An Executable Info window pops up to summarize the executable environment you just created.
If you set up only one executable for the project, it becomes the active executable. When you choose Build > Build And Debug, a debug window appears, and InDesign CS6 starts.

Anatomy of a plug-in’s project files

Typically, an InDesign project contains the following C++, ODFRC, and library files.

C++ files

Declaration of abstract base classes for interfaces.
Definition of implementation classes.
Identification of the implementation ID and name of the InDesign object model.

ODFRC resource files

The PluginVersion resource establishes a plug-in’s name/ID, the plug-in version and InDesign version
required, and the plug-in’s data-format number for conversion.
Boss resources establish relationships among boss IDs for the InDesign object model, the IDs of
interfaces, and the IDs of C++ implementations.
Localization mechanism.
User-interface widget declaration.
Data-conversion schema and plug-in dependency.
CHAPTER 2: Getting Started with the InDesign SDK Tutorial: Creating a plug-in from scratch 16

Library files

Public libraries that contains code that you must link against when building your plug-in.

Tutorial: Creating a plug-in from scratch

The rest of this chapter guides you through creating a basic InDesign plug-in and illustrates how to add functionality to that basic plug-in.
The source code for InDesign plug-ins is largely platform independent. The InDesign plug-in development process is unique, because it has its own user-interface and object-oriented API. This section focuses on these two unique aspects, to help you develop plug-ins for both Windows and Mac OS.

Introducing the sample plug-in

The example describes how to build the WriteFishPrice sample plug-in that is available in the InDesign SDK. This sample allows the user to enter fish names and current prices into a text frame at the text-cursor position. It incorporates several common user-interface components: menus, dialog boxes, pull-down menus, text-edit boxes, static-text fields, and buttons.
To see the finished plug-in toward which you are working, start InDesign with WriteFishPrice loaded, and create a document. In the new document, create a text frame and place a text cursor in the frame. From the main menu, choose Plug-In > SDK > WriteFishPrice(US):
The WriteFishPrice(US) dialog opens:
From the drop-down menu, select a fish name. Enter its price in the text box:
When you click OK, the name of the fish selected from the drop-down menu and the price you entered appear in the text frame at the insertion point of the text cursor. As you continue making entries in the text frame, the output appears like that shown here:
CHAPTER 2: Getting Started with the InDesign SDK Step 1: Use DollyXs to generate a dialog-based plug-in project 17
This simple plug-in serves as a good starting point, because it incorporates fundamental and common components. The following sections describe how to create this plug-in. The main steps are as follows:
“Step 1: Use DollyXs to generate a dialog-based plug-in project”
“Step 2: Add a DropDownListWidget to the dialog”
“Step 3: Add a TextEditBoxWidget”
“Step 4: Add a StaticTextWidget”
“Step 5: Obtain a value from DropDownListWidget”
“Step 6: Get the text in the TextEditBoxWidget”
“Step 7: Insert a string into a text frame”
“Step 8: Disable the menu with no text selection”
“Step 9: Initialize dialog widgets”

Step 1: Use DollyXs to generate a dialog-based plug-in project

Before you begin, have a mental picture of the plug-in you want to create—what it should do and what sort of interface it should present to the user. Then you can use DollyXs to create the basic skeleton for your plug-in.
DollyXs is a plug-in development tool included in the InDesign SDK. This tool, written in Java™, uses XSL templates to generate fundamental plug-in projects for Microsoft Visual C++ and Apple® Xcode. See the DollyXs Readme.txt file for details, including how to obtain the Java Runtime Environment for Windows.
To create a working plug-in that provides a solid starting point for your plug-in development, you can run DollyXs and fill in the fields in the DollyXs interface. For this example, you will choose a dialog-box user interface as the foundation for your WriteFishPrice plug-in. In other circumstances, you might choose the panel-based or script-provider-based user interfaces that DollyXs supplies.
DollyXs is located in the <SDK>/devtools/sdktools/dollyxs directory.
OTE: On Mac OS, as an alternative to using DollyXs to generate a dialog-based plug-in project, you can
N
use the template to generate an empty InDesign SDK project file. See
Create an InDesign SDK Xcode
project from the template (Mac OS only)” on page 25.
CHAPTER 2: Getting Started with the InDesign SDK Step 1: Use DollyXs to generate a dialog-based plug-in project 18

Step 1.1. Start DollyXs

To start, execute DollyXs.bat (on Windows) or the DollyXs.sh shell script (on Mac OS). When DollyXs starts, you see this dialog:

Step 1.2: Specify plug-in names

In the Plugin tab, enter the two plug-in names:
Long Name is the name of the plug-in itself. It is used as a string in the Plug-ins menu and in the About
This Plug-in dialog.
Short Name is used as part of the source-code files, class names, and IDs that are generated. We
recommend that Short Name have approximately six characters.
For this exercise, enter WriteFishPrice for Long Name and WFP for Short Name.
For Author, enter your name. This string is used in the About This Plug-in dialog and comments in source code.

Step 1.3: Specify the prefix ID

A prefix ID is a unique value assigned by Adobe for your plug-in development. For plug-ins that you will release outside your organization, make sure to use a prefix ID assigned to you by Adobe. Information about obtaining a plug-in prefix ID is at Adobe’s InDesign Developer Center,
http://www.adobe.com/devnet/indesign/
N
OTE: This is very important, because the prefix ID is used to define the plug-in’s IDs and resources. There
must be no overlap in the prefix IDs used by plug-ins. Plug-ins with the same prefix ID cannot be loaded simultaneously.
.
CHAPTER 2: Getting Started with the InDesign SDK Step 1: Use DollyXs to generate a dialog-based plug-in project 19
For this exercise, specify 0x61000 (the default). This prefix ID was allocated for the purpose of this exercise.

Step 1.4: Specify directory locations

Windows
Click the Win tab, and specify the directory paths that you want to use. For Project Dir, specify the complete path to the directory where you want your Visual C++ project (.vcproj) file to be generated. If you installed the SDK in a different directory, edit the default path.
The other directories are relative to Project Dir. For this exercise, you will work in the WriteFishPrice directory. For Source Dir and Header Dir, specify WriteFishPrice as your subdirectory in sdksamples.
The Shared RSP Files group lets you use existing .rsp file(s). A .rsp file is used in an SDK project to specify common search paths for the C++ and ODFRC compilers.
Mac OS
Click the Mac tab, and specify the directory paths that you want to use. For Project Dir, specify the complete path to the directory where you want your Xcode project (.xcodeproj) file to be generated. If you installed the SDK in a different directory, edit the path.
The other directories are relative to Project Dir. For this exercise, you will work in the WriteFishPrice directory. For Source Dir and Header Dir, specify WriteFishPrice as your subdirectory in sdksamples.
In the Architectures pop-up menu, the choice corresponds to the Architectures variable in the Xcode’s project/target setting. Choose the platform that you want to target.
The Shared XCConfig Files group lets you use existing xcconfig files on your computer. The xcconfig file is used in the Xcode project to provide base settings for project/targets. The file specified in the Main xcconfig field is used as the xcconfig file for the project-level build setting in the generated project; the file specified in the Debug xcconfig field is used for the Debug-target build setting; and the file specified in the Release xcconfig field is used for the Release-target build setting. The SDK comes with a set of xcconfig files in the projects folder, which you can reuse if you use settings like those in the SDK project.

Step 1.5: Specify template

Click the Features tab, and select Generate Dialog.

Step 1.6: Verify entered information and generate plug-in project

Verify your settings, then click OK.
Verify that DollyXs has generated files in the project and code directories you specified. In the project directory, you should see WriteFishPrice.vcproj or WriteFishPrice.xcodeproj. In the source directory, you should see a group of C++ source files that begin with WFP. For details about each file, see
in the project generated by DollyXs” on page 21.
Files included
CHAPTER 2: Getting Started with the InDesign SDK Step 1: Use DollyXs to generate a dialog-based plug-in project 20

Step 1.7: Build the plug-in

Windows
Before building your plug-in, set up your InDesign development environment (IDE) to use the InDesign ODFRC. To do this, choose Tools > Options, and add the <SDK>\devtools\bin directory under the Executable Files directory path.
To build your plug- in:
1. Open WFP.vcproj using Microsoft Visual C++.
2. When the project is open, make sure Debug is the active configuration: Choose Project > WriteFishPrice Properties. The configuration in the Property Pages dialog box should be Active (Debug).
3. To build the plug-in, choose Build > Build WriteFishPrice.
4. When you are asked to save a Solutions file (.sln), save it to the same directory as the project (.vcproj) file.
Mac OS
The Xcode project generated by DollyXs is already set up to find the ODFRC compiler from its default SDK location. Unless you moved the ODFRC.cmd to somewhere other than its default location, you do not need to do anything to specify the location of the ODFRC compiler.
To build your plug- in:
1. Open the WriteFishPrice.xcodeproj file using Xcode.
2. Choose Debug from the Active Target pop-up menu, on the top left corner of the project window.
3. Choose Build > Build, or click the Build button on the Project Window.

Step 1.8: Load the plug-in

The plug-in you just built has the filename WriteFishPrice.pln (Windows) or WriteFishPrice.InDesignPlugin (Mac OS) and is in the following directory in your <SDK> directory:
Windows:
Debug: <SDK>\build\win\debug\SDK
Release: <SDK>\build\win\release\SDK
Mac OS:
Debug: <SDK>/build/mac/debug/SDK
Release: <SDK>/build/mac/release/SDK
Copy the WriteFishPrice plug-in file to the Plug-Ins directory in the InDesign CS6 directory; then the WriteFishPrice plug-in will be loaded when InDesign is launched.
CHAPTER 2: Getting Started with the InDesign SDK Files included in the project generated by DollyXs 21
NOTE: Do not install debug plug-ins to the Plug-Ins directory for the release build of InDesign, or vice versa;
if you do, your plug-in will fail to load.
When the plug-in is loaded, InDesign displays a Plug-Ins menu containing a WriteFishPrice menu item.

Step 1.9: Start InDesign through your IDE

If you successfully built and loaded your plug-in, you can start InDesign through your IDE by following the steps in this section.
On Windows:
1. Using Microsoft Visual C++ and with the project file open, choose Project > WriteFishPrice Properties.
2. In the Debugging panel of Configuration Properties, set the Command field to InDesign.exe. If you know the path, type it; otherwise, click the Command field, then click the Down button to open a Browse window that you can use to navigate to where InDesign.exe is located on your computer.
3. Click OK to complete the process.
On Mac OS:
For information on starting an Xcode debugging session, see “Starting a debugging session from your
plug-in project” on page 14.
You are now ready to start the application from your IDE. In Visual C++, choose Debug from the IDE main menu, and click Start. The process is similar for Xcode.
After you start InDesign, open the dialog from the Plug-Ins menu:
No widgets are placed on your dialog yet, nor is the menu name correct, so you still have some work to do.

Files included in the project generated by DollyXs

This section describes the files that DollyXs generates. Go back to the project in your IDE, and follow along with this section to examine each file.

Source files

WFPID.h — This header file is a central repository for plug-in IDs. Some IDs are numeric, and some are
string values; some IDs are unique across the application, and some are unique only within the plug-in. This file is critical for plug-ins and is included by all plug-in project files.
WFPFactoryList.h — This header file contains macros that allow the core InDesign object model to
create and destroy instances of the implementations through factory classes.
CHAPTER 2: Getting Started with the InDesign SDK Files included in the project generated by DollyXs 22
WFPNoStrip.cpp — This file prevents the C++ compiler optimizations from dead stripping (eliminating code that appears to the compiler to be unused). Because most of the code in a plug-in is not used directly from within the plug-in itself, much of this code can appear to the compiler to be dead. WFPNoStrip.cpp contains a function, DontDeadStrip, which includes WFPFactoryList.h.
WFPID.cpp — This file allows the IDs defined in WFPID.h to be included as strings in the debug build
symbols.
SDKPlugInEntrypoint.cpp — This file, in the <SDK>/source/sdksamples/common directory, specifies
the plug-in’s entry point. This file is not modified by any DollyXs settings but is simply included in the project.
TriggerResourceDeps.cpp — This file ensures that the ODFRC resource is relinked when the .fr file is
compiled on Windows.
WFPDialogController.cpp — This source file contains a class used for initializing, validating, and
responding to dialog widgets. The WFPDialogController class specifies what happens when the dialog is initialized and when OK is clicked.
WFPDialogObserver.cpp — The WFPDialogObserver class in this file dynamically processes changes to
the widgets on the dialog. To observe events pertaining to any other widgets you may place on the dialog, this is where you add your code.
WFPActionComponent.cpp — The WFPActionComponent class in this source file defines what happens
when the plug-in’s menu item is selected. In this case, the Plug-Ins menu item and About This Plug-In menu items are handled. The About This Plug-In menu item is displayed in the Help > About Plug-Ins > SDK menu item (Windows) or the Apple Menu menu item (Mac OS). This class also opens the About This Plug-In dialog box in the DoAbout method.

Resource files

WFP.fr — This file defines resources unique to InDesign. These cross-platform resource definitions are
compatible with Windows and Mac OS. This file contains resources other than strings.
WFP_enUS.fr — This file contains string resources in a string-table resource used for the US English
locale. These resources are used when the plug-in is used with InDesign in the US English locale. Also, this file can contain user-interface specifications, especially when they differ by locale.
WFP_jaJP.fr — This file contains string resources in a string-table resource used for the Japanese
locale. These resources are used when the plug-in is used with InDesign in the Japanese locale. Also, this file can contain user-interface specifications, especially when they differ by locale.
WFP.rc — This file defines resources specific to Windows; in particular, the plug-in file version.

Project files

WFP.vcproj — This is a Visual C++ project file for Windows. By default, it is in <sdk>\build\win\prj.
WFP.xcodeproj — This is an Xcode project file for Mac OS. By default, it is in <sdk>/build/mac/prj.

Detailed descriptions of code generated by DollyXs

This section provides more detail about the source files that you will modify throughout this exercise. Follow along with this section by using your IDE to open and examine the code of each file.
CHAPTER 2: Getting Started with the InDesign SDK Files included in the project generated by DollyXs 23
WFPActionComponent.cpp
WFPActionComponent — This class inherits the CActionComponent class, which implements the
IActionComponent interface. The WFPActionComponent class responds to menu selections in the DoAction method and distinguishes the selected menu item by means of the corresponding ActionID.
WFPActionComponent::DoAction — This method overrides the DoAction method in its parent class,
(CActionComponent), receives the selected ActionID as a parameter, and compares it with kWFPAboutActionID and kWFPDialogActionID (defined in WFPID.h). If there is a match, the DoAction method calls the appropriate DoAbout or DoDialog method.
WFPActionComponent::DoAbout — This method is called from WFPActionComponent::DoAction. It
displays a CAlert::ModalAlert dialog.
WFPActionComponent::DoDialog — This method first obtains the IApplication interface by means of
GetExecutionContextSession()->QueryApplication(). GetExecutionContextSession() returns a pointer to the ISession interface aggregated in the kSessionBoss, which is a boss-class object that describes the current InDesign application session. IApplication is an interface aggregated on kAppBoss, which is a boss-class object that describes the InDesign application itself. See the following figure. From the IApplication interface, DoDialog obtains the IDialogMgr interface, which enables you to get to the InDesign dialog manager’s boss class. Next, DoDialog loads the dialog resources that correspond to the current user-interface locale during the first instantiation, and DoDialog saves it to the InDesign database, so it can be loaded efficiently during subsequent instantiations. The current user-interface locale is obtained by instantiating a RsrcSpec object, dialogSpec, by calling LocaleSetting::GetLocale. There are several kinds of constructors for the RsrcSpec object, but this method uses the constructor shown in the code. As shown, once you instantiate a RsrcSpec object, DoDialog calls the CreateNewDialog method on the IDialogMgr interface. The parameter list contains the dialogSpec that was just instantiated and a constant that specifies the modality of the dialog (kMovableModal constant defined in the IDialog interface). CreateNewDialog then creates a movable dialog based on the dialogSpec and returns a pointer to a dialog (IDialog on kDialogWindowBoss, or a derived boss class). Finally, the Open method on the IDialog interface is called, and the dialog is opened.
WFPDialogObserver.cpp
WFPDialogObserver — This class inherits the CDialogObserver class, which implements the IObserver
interface. Through this class, you can register to observe dynamic changes to the widgets on the dialog. The example simply provides some stub code so your code can observe changes to widget states, such as a custom button. The observer provides a mechanism to listen to changes to specific objects, known as subjects. By attaching to a subject, observers can be notified when a change occurs, rather than having to poll for changes.
CHAPTER 2: Getting Started with the InDesign SDK Files included in the project generated by DollyXs 24
WFPDialogObserver::AutoAttach — This method is called by the application and enables observers to attach themselves to a subject. By attaching, an observer can be notified when there is a change to the subject. In the example, there are no widgets handled. If you need to observe other widgets on this dialog, you can add them here. Alternately, you can observe each widget in separate observers. To keep the code simple, however, the example collectively observes all widgets on this dialog. By default, the OK and Cancel buttons (with widget IDs of kOKButtonWidgetID and kCancelButton_WidgetID, respectively) are observed by the parent class, CDialogObserver. Consider how this works. First, the WFPDialogObserver::AutoAttach method calls the CDialogObserver::AutoAttach method in the parent class. This is so the OK and Cancel buttons can be handled. Afterward, the IPanelControlData interface (from the same boss object that hosts the current implementation, WFPDialogObserver) is obtained and, by using the parent class’s CDialogObserver::AttachToWidget method, it can attach to any other widget on the dialog.
WFPDialogObserver::AutoDetach — This method, which is called by the InDesign application, allows
observers to detach from a subject. Detaching an observer is the reverse of attaching, which means the detached observer is no longer notified of changes. Again, the OK and Cancel buttons are handled by default in the parent class, CDialogObserver. Like the AutoAttach method, the CDialogObserver::AutoDetach method is called to handle the OK and Cancel buttons. Afterward, the IPanelControlData interface (from the same boss class in which the current class resides) is obtained and, by using the parent class's CDialogObserver::DetachFromWidget method, an observer can detach from any other widget on the dialog.
WFPDialogObserver::Update — This method is called by the host when a change occurs to the
observed object. (In the example, there are no widgets other than the OK and Cancel buttons, so there is not much extra code.) When a widget is changed, the CDialogObserver::Update method is called to handle the OK and Cancel buttons up front, then the IControlView interface of the widget that caused the change is obtained from the theSubject parameter. To determine which widget ID caused the change, the GetWidgetID method is called on the IControlView interface. Suppose you want to add another button with a specific widget ID, like kWFPIconSuiteWidgetID, to this dialog. For a button press to be responded to, the widget ID must correspond to the ID for your button, and the message ID from the theSubject parameter must be something like kTrueStateMessage (indicating the button is pressed).
WFPDialogController.cpp
WFPDialogController — This class inherits the CDialogController class, which implements the
IDialogController interface. This class handles the dialog initialization, as well as data validation and the OK button click.
WFPDialogController::InitializeDialogFields — This method initializes the widgets on the dialog. This
method is called by the parent class when the dialog is opened and when the dialog’s Reset button is clicked, if you did not override the CDialogController::ResetDialogFields method. This method first needs to call the CDialogController::InitializeDialogFields method in the parent class. (Note: Cancel becomes Reset when you hold the Alt or Option key.)
WFPDialogController::ValidateDialogFields — This method validates the fields on the dialog. When the
OK button is clicked, this method is called before the ApplyDialogFields method. Again, the CDialogController::ValidateDialogFields method in the parent class is called first. If there is even one field with an invalid value, you can return the WidgetID to be selected. If all fields have valid values, you can return kDefaultWidgetId, which allows the parent class to call the ApplyDialogFields method.
CHAPTER 2: Getting Started with the InDesign SDK Create an InDesign SDK Xcode project from the template (Mac OS only) 25
WFPDialogController::ApplyDialogFields — This method retrieves the values from the dialog fields and acts on them. The widgetId from the parameter list contains the widget ID that caused this method to be called. By default, this parameter contains kOKButtonWidgetID.

Create an InDesign SDK Xcode project from the template (Mac OS only)

On Mac OS, as an alternative to using DollyXs to generate a plug-in project, you can use the template to generate an empty InDesign SDK project file. The development environment for the InDesign SDK is XCode 3.2.5 for Mac OS 10.6.x (also known as Snow Leopard). To create an InDesign template project for XCode 3.2.5, see the following section.

Add the SDK project template for Xcode

Add the SDK template project folder InDesign Project from <SDK>/devtools/sdktools/xcodetemplates to <your-start-up-disk-volume>/Developer/Library/Xcode/Project Templates. The template is one of the
methods that you can use to convert or create a new Xcode project for an InDesign plug-in.
Follow these steps:
1. Start Xcode.
2. From the Xcode menu, choose File > New project to bring up the New Project window:
CHAPTER 2: Getting Started with the InDesign SDK Create an InDesign SDK Xcode project from the template (Mac OS only) 26
3. Select the “InDesign Project” group, select “SDK Project”, and click Choose... The Save As dialog appears:
4. Name the project and give it a proper path. The path should be in the same directory as the SDK’s prj folder. By default, Xcode appends a project folder after you specify the SDK project path. Click Save, and a windows appears to “Select the directory to use as the project root”:
CHAPTER 2: Getting Started with the InDesign SDK Step 2: Add a DropDownListWidget to the dialog 27
5. Select the directory to use as the project root and click Open.
6. Copy the project file from the project folder to the SDK project folder. (If you prefer to create a project outside the prj folder, consider using DollyXs, as it supports the feature.)
7. If a “Files to be Overwritten” dialog pops up with an invisible .DS.store file shown as the existing file, click “Overwrite Select Files.” Now a new project with the name you specified above is created in the prj location. Go to the prj location; you will find the xcodeproj file is created and a folder named <your-project-name>-#.moved-aside also is created. This folder contains the files that are being overwritten. If .DS.store file is the only file being overwritten, you can safely discard this <your-project name>-#moved-aside.
OTE: The template works only when you create the project file in the same directory as the prj folder.
N
N
OTE: The template uses InDesignModel.framework by default. If your plug-in needs UI elements, you
need to replace InDesignModel.framework with InDesignModelAndUI.framework. Otherwise, you will get many link errors.
OTE: You need to add any necessary header file paths to the project’s Header Search Paths.
N

Step 2: Add a DropDownListWidget to the dialog

You have created the rough foundation for your plug-in. Now it is time to start building your plug-in by improving its dialog widget.

Step 2.1: Add a widget ID

Open WFPID.h in your IDE and find the widget definitions for the dialog, as shown here:
CHAPTER 2: Getting Started with the InDesign SDK Step 2: Add a DropDownListWidget to the dialog 28
// WidgetIDs: DECLARE_PMID(kWidgetIDSpace, kWFPDialogWidgetID, kWFPPrefix + 1)
On the next line, add the following:
// DropDownList widget ID DECLARE_PMID(kWidgetIDSpace, kWFPDropDownListWidgetID, kWFPPrefix + 2)

Step 2.2: Define string keys for list items

Next, define string keys for the items in the DropDownList. InDesign has a base type object, PMString, that is used extensively for user-interface strings; for this type, InDesign has a locale-based, string look-up mechanism for automatic string translation. The translated strings are defined in a string-table resource; if a string is specified by its key, InDesign automatically replaces it with the corresponding localized string. If you look at WFPID.h in the “Other StringKeys” section, you can see several string keys defined there.
To define a string key for the DropDownListWidget items, first find the following in WFPID.h:
// Other StringKeys: #define kWFPAboutBoxStringKey kWFPStringPrefix "kWFPAboutBoxStringKey" #define kWFPTargetMenuPath kWFPPluginsMenuPath
Immediately after this, add the following lines:
#define kWFPDropDownItem_1Key kWFPStringPrefix "kWFPDropDownItem_1Key" #define kWFPDropDownItem_2Key kWFPStringPrefix "kWFPDropDownItem_2Key" #define kWFPDropDownItem_3Key kWFPStringPrefix "kWFPDropDownItem_3Key" #define kWFPDropDownItem_4Key kWFPStringPrefix "kWFPDropDownItem_4Key"
If you know what your string key will be—for instance, kWFP_TunaKey—you can define the key using the string, so you can find it more easily later.

Step 2.3: Define locale-specific strings for list items on DropDownListWidget

Next, define the string-table resource entries that correspond to the string keys you just defined. These string tables are defined in WFP_enUS.fr and WFP_jaJP.fr, for use in the US English and Japanese locales, respectively. These two resource files are included by WFP.fr.
Start by defining the US English string-table entries. Open WFP_enUS.fr to see that the string keys and the English strings are paired up. Add strings for the four string keys you just defined. Look for the following in WFP_enUS.fr:
resource StringTable (kSDKDefStringsResourceID + index_enUS) { // Locale Id k_enUS, // Character encoding converter kEuropeanMacToWinEncodingConverter, { // ...omitted // ----- Panel/dialog strings kWFPDialogTitleKey, kWFPPluginName "[US]",
Immediately after this, add the following lines:
CHAPTER 2: Getting Started with the InDesign SDK Step 2: Add a DropDownListWidget to the dialog 29
// Drop-down list item strings kWFPDropDownItem_1Key, "Tuna", kWFPDropDownItem_2Key, "Salmon", kWFPDropDownItem_3Key, "Bonito", kWFPDropDownItem_4Key, "Yellowtail",
Similarly, you can add strings to the Japanese string table. Open WFP_jaJP.fr and look for the following:
resource StringTable (kSDKDefStringsResourceID + index_jaJP) { k_jaJP,// Locale Id 0, // Character encoding converter { //...omitted // ----- Panel/dialog strings kWFPDialogTitleKey, kWFPPluginName "[JP]",
Immediately after this, add the following lines:
// Drop-down list item strings kWFPDropDownItem_1Key, "Tuna [JP]", kWFPDropDownItem_2Key, "Salmon [JP]", kWFPDropDownItem_3Key, "Bonito [JP]", kWFPDropDownItem_4Key, "Yellowtail [JP]",
For this exercise, it is not necessary to enter Japanese characters into the resource string tables. The SDK sample plug-ins often put a locale-specific suffix on these strings, such as “[JP],” so you know the appropriate string table is being used. You can choose to do the same.
If you will release your plug-ins commercially, however, there is a chance an InDesign Japanese version will use your plug-in. In that case, it is advisable to define strings for the Japanese string table. Better yet, obtain help in translating the strings into Japanese or other locales supported by InDesign.

Step 2.4: Add a DropDownListWidget to your dialog resource

The dialog resource is defined in WFP.fr, toward the end of the file. This resource already contains two widgets: the default OK button and Cancel button. Look for the following:
resource WFPDialogWidget (kSDKDefDialogResourceID + index_enUS) {
FILE__, __LINE__, kWFPDialogWidgetID, // WidgetID kPMRsrcID_None, // RsrcID
kBindNone, // Binding 0, 0, 388,112, // Frame (l,t,r,b) kTrue, kTrue, // Visible, Enabled kWFPDialogTitleKey, // Dialog name { ...omitted CancelButtonWidget ( ...omitted ),
Immediately after this, add the following lines:
CHAPTER 2: Getting Started with the InDesign SDK Step 2: Add a DropDownListWidget to the dialog 30
// Drop-down list widget resource DropDownListWidget ( kWFPDropDownListWidgetID, // WidgetId kSysDropDownPMRsrcId, // RsrcId kBindNone, // Frame binding Frame(10,16,140,36), // Frame (l,t,r,b) kTrue, kTrue, // Visible, Enabled {{ // List Items kWFPDropDownItem_1Key, kWFPDropDownItem_2Key, kWFPDropDownItem_3Key, kWFPDropDownItem_4Key, }} ),
This drop-down list widget is now added to your dialog.

Step 2.5: Correct the localized menu strings

Earlier, when you first looked at your dialog (“Step 1.9: Start InDesign through your IDE” on page 21), the menu string in the Plug-Ins > SDK menu was Show Dialog. You want it to be WriteFishPrice[US] or WriteFishPrice[JP], so you need to change it.
1. Open WFP_enUS.fr, and look for the following:
kWFPDialogMenuItemKey, "Show dialog[US]",
2. Change this line to the following:
kWFPDialogMenuItemKey, kWFPPluginName "[US]",
3. Also do this in your Japanese string table. Open WFP_jaJP.fr, and look for the following:
kWFPDialogMenuItemKey, "Show dialog[JP]",
4. Change this line to the following:
kWFPDialogMenuItemKey, kWFPPluginName "[JP]",
NOTE: kWFPPluginName is defined in WFPID.h.

Step 2.6: Save, build, and test

Save the source files you edited, build the plug-in, move the plug-in to the Plug-Ins directory, start InDesign, and try using your new drop-down list.
When you first open the dialog, notice there is no default value in the drop-down list. You will set up a default value for this drop-down list in a later step.
Click the drop-down list widget. The drop-down list widget should show the four strings you just added:
Loading...
+ 99 hidden pages