November 15, 2008

Tabbing in PDF Annotation Editor

Filed under: Uncategorized — frameworker @ 8:09 pm

Written by John Calhoun, the PDF Annotation Editor is a sample application that uses PDF Kit to examine, edit, and create PDF annotations. 

It lets you tab in Test mode but not in Edit mode.

I needed to tab in Edit mode, but was headed in the wrong direction when John Calhoun graciously provided this recipé:

“Grab keyDown’s in your PDFView subclass and keep track of the current annotation with “focus”.  Manually advance the focus by going round-robin through the annotations on the page.”

Here is its implementation:

// Add a case to [PDFViewEdit keyDown] to detect the Tab key
// and call "advanceFocus" when it is hit.
- (void) keyDown: (NSEvent *) theEvent
    unichar oneChar;

    // Skip out if not in 'edit mode'.
    if (_editMode == NO)
        [super keyDown: theEvent];

    // Get the character from the keyDown event.
    oneChar = [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];

    // Delete or Tab ?
    if ((oneChar == NSDeleteCharacter) || (oneChar == NSDeleteFunctionKey))
        [self delete: self];
    else if (oneChar == NSTabCharacter)
        [self advanceFocus];
        [super keyDown: theEvent];

Add two methods to PDFViewEdit.m
and their method declarations to PDFViewEdit.h.

// Tab key was hit; move focus to the next widget.
- (void) advanceFocus
    if (_activeAnnotation != NULL)
        PDFPage * currentPage = [_activeAnnotation page];

        // Walk array of annotations.
        NSArray *annotations = [currentPage annotations];
        int annotCount = [annotations count];

        int activeIndex = [annotations indexOfObject: _activeAnnotation];

        int newActiveIndex = [self nextAnnotIndex: activeIndex withinCount: annotCount];

        PDFAnnotation * newActiveAnnotation = [annotations objectAtIndex: newActiveIndex];

        [self selectAnnotation: newActiveAnnotation];

// return the index of the next annot, wrapping around on the current page.
– (int) nextAnnotIndex: (int) activeIndex withinCount: (int) annotCountForPage
    int nextIndex = -1;

if (activeIndex +1 < annotCountForPage)     {         nextIndex = activeIndex + 1;     }     else     {         nextIndex = 0; // Wrap around on page.     }     return nextIndex; } [/sourcecode] Voilà, that's all there is to it!  Thanks John!


Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

Blog at

%d bloggers like this: