Tools framework overview

In this document
chevron_rightAbout Tools
chevron_rightOverview
chevron_rightEvent walkthrough

About Tools

PDFTron for iOS includes Tools.framework, an open-source framework that implements virtually all of the SDK's UI functionality. Because the tools framework is open source, the PDFTron UI is customizable without restriction or limitation.

The tools framework itself is optional. Without it, the PTPDFViewCtrl will display a PDF with scrolling and zooming, but will not support text selection, interactive annotation handling, etc.

The Tools framework covers of two major aspects:

  1. PDF Interaction tools:

    PDF interaction tools are those that handle the user's direct interaction with the PDF, that is touching the PDF directly. This functionality includes:

    • Text selection
    • Annotation creation/modification/deletion
    • Form filling
    • Signatures
    • Link following
    • Multimedia handling
  2. UI Controls:

    The UI controls are views that are separate from the PDF:

    • PDF outline (table of contents)
    • User-created bookmarks
    • Annotation toolbar
    • Annotation listing
    • Page manipulation via a grid of thumbnails

The Tools framework does not rely on any special or private access to PDFTron APIs. The PDF interaction tools are implemented entirely by implementing the PTPDFViewCtrl's PTTool protocol and using PDFNet.framework's public and cross-platform APIs. The UI controls rely solely on PDFNet.framework.

The tools source code is provided as part of the SDK and so it can be customized as required for your app, or simply referenced as sample code.

PDF Interaction Tools

Overview

The PDF interaction tools implement the functionality that occurs when the user touches the PDF itself.

The interaction tools use a "manager" class, the aptly named ToolManager, that serves as the PTPDFViewCtrl toolDelegate. It receives events, and passes the information to a set of tools that it mediates. Each of these tools is a class that implements the functionality for some particular purpose, such as text selection, form filling, ink drawing, and so on.

Tool manager event handling

The ToolManger is responsible for passing the event to its current tool. If the current tool has fully handled the event, it returns true, and no further event processing takes place. If the current tool cannot fully handle the event, it returns false, and the tool manager replaces its current tool with a new one (provided by the old tool's getNewTool method), and forwards the event to it for further processing.

The control flow is illustrated below:

How events are handled by Tools.framework.

Example: Tapping on an annotation

As a concrete example, the steps outlined below illustrate how a tap on an annotation would be handled. We will assume that the user is not actively "doing something" on the PDF, so that ToolManager's tool at the time of the tap is the general purpose PanTool.

  1. The user taps the PDF displayed by the PTPDFViewCtrl.
  2. The tap event is forwarded to the PTPDFViewCtrl's toolDelegate object, which is the Tool.framework's ToolManager.
  3. The ToolManager receives the event, and sends it to its current tool, which as discussed is the PanTool.
  4. The PanTool checks what, if anything (link, form field, etc.), was tapped. In this example, it was a markup annotation. The PanTool "knows" this needs to be handled by the AnnotEditTool, and internally notes this for future use in its method getNewTool.
  5. The PanTool returns false, indicating to the ToolManager that event processing has not been completed.
  6. The ToolManager calls PanTool's method getNewTool, which returns a new tool, in this case an AnnotEditTool, which should continue handling the event.
  7. The ToolManager sets its current tool to the instance of the new AnnotEditTool, which causes the PanTool to be destroyed.
  8. The ToolManager sends the tap event to the AnnotEditTool, which handles the event by selecting the annotation.
  9. The AnnotEditTool returns true from the tap event, indicating to the ToolManager that it has been fully handled the event and it does not to be further processed by another tool.

While the above may initially seem long, it is following a fairly simple pattern: a tool implements specific responses to touch events, and tell the tool manager if they have fully handled the event or not. If so, that is the end of the event processing; if not, a new tool is created and the event is sent to it.

Event walkthrough

To understand the above flow in code terms, it is most useful to look at the "tool loop" (method runToolLoop:) in the ToolManager. Here is the essence of the loop for a tap event:

BOOL handled = YES;
do {
    // The tool manager calls the event method, handleTap:, on the current tool, self.tool.
    // If the tool was able to finish processing the event, it returns true; otherwise, false.
    // For example, when using the PanTool (in charge of general scrolling), a tap on empty page space or an image would return true, but a tap on an annotation or form field would return false.
    handled = [self.tool handleTap:gestureRecognizer];
    
    // did the tool finish processing this event?
    if( !handled )
    {
        // If the current tool did not finish handling the event, it needs to be handled by a different tool. The current tool is responsible for indicating which tool type should be used next, via its getNewTool method.
        // For example, if a tap were detected to occur on annotation, it is likely that that the tool that should handle this event is the AnnotEditTool, and so an instance of AnnotEditTool would be returned by getNewTool.
        self.tool = [self.tool getNewTool];
    }
 
// continue to loop until the event has been handled.  
} while (!handled);

For a further look on how interaction tools work, see the article about how to create a new tool.