Creating a new tool

Creating a custom tool to use with the PDFViewCtrl is fairly straight forward. There are several tools implemented in the PDFViewCtrlTools project already. These tools can be used as a base for many other tools or as a reference for a new tool. In order to create your own tool, we suggest looking at the PDFViewCtrlTools project.

When creating a new tool, there are a few important elements that needs to be handled.

Events raised on the PDFViewCtrl

First, we need to handle the events of the PDFViewCtrl. This is easily done by subscribing to the events using standard syntax. The standard events to subscribe to are PointerPressed, PointerMoved, and PointerReleased. However, additional events, such as PointerCancelled and PointerCaptureLost are also important.

Preventing the PDFViewCtrl from handling the input

Preventing the PDFViewCtrl from handling the input is best done when the pointer is pressed. You will receive the PointerPressed event, at which point you can call PDFViewCtrl.SetZoomEnabled(false) and PDFViewCtrl.SetScrollEnabled(false). Remember to call the same two functions but with True on the PointerReleased event. Once the user starts to manipulate the PDFViewCtrl, especially with touch, such as a scrolling or pinching, the event chain will be taken away from the UI thread to be handled internally by the Control itself. This is standard procedure for controls like the ScrollViewer or FlipView in Windows Store Apps. This allows the events to be processed in a background thread, and it keeps the UI thread responsive. Once the PDFViewCtrl starts to scroll, you will not be able to get any pointer or Manipulation events until it has come to a rest.

Knowing when to lock the document

It is important to lock the document whenever you read any information from it. PDFNet provides two types of locks. A read lock which allows for concurrent reading, as well as a write lock which grants the process exclusive access to the PDFDoc. The write lock is only necessary when modifying information in the document, such as when pushing back annotations or changing their appearance. Please see the PDFViewCtrlTools project to learn how and when to use these locks.

Converting between different cooridinate spaces

When working with the PDFViewCtrl, there are three spaces to be aware of. There is a Screen space, which is a coordinate system relative to the PDFViewCtrl itself. The point 0, 0 is in the PDFViewCtrl's top left corner. There is a page space, which is the coordinate system relative to a particular page. PDF page coordinates start with 0, 0 in the bottom left corner, unless rotated. Note that the page's CropBox, which is the region visible in the PDFViewCtrl, doesn't always start at 0, 0 though. And finally there is the space of the Canvas that you can get from calling PDFViewCtrl.GetAnnotationCanvas(). This canvas is the minimum bounding rectangle (starting with 0, 0 in the top left) around all the pages in the current scrollable region (for example, at very low zoom levels, the x-coordinate 0 might be close to the center of the PDFViewCtrl). You can use PDFViewCtrl.ConvAnnotationCanvasPtToScreenPt and PDFViewCtrl.ConvScreenPtToAnnotationCanvasPt to convert between PDFViewCtrl and AnnotationCanvas coordinates. Note that the PDFViewCtrl has an internal concept of a canvas which is different from this canvas. Therefore, PDFViewCtrl.ConvPagePtToCanvasPt will not actually work on the Canvas from GetAnnotationCanvas. When capturing input, you usually deal with Canvas or Screen coordinates. For example, inside the PointerPressed handler, Windows.Foundation.Point downPoint = e.GetCurrentPoint(mPDFView).Position will give you a point in Screen space. When pushing back an annotation, this has to be converted to Page space of the page you want to add the annotation to. You can convert between these spaces with the help of the PDFViewCtrl. For example, int pgNumber = PDFViewCtrl.GetPageNumberFromScreenPoint(double x, double y) will give you the page that you would be touching if x, y was the point of your finger in screen space. Then, calling PDFViewCtrl.ConvScreenPtToPagePt(DoubleRef px, DoubleRef py, int pgNumber) will give you what point this is in page space. These conversions are used throughout the tools library. Also, the base Tool class contains some convenience functions to perform these conversions on full rectangles (pdftron.PDF.Rect).

We will also take a quick look at the tool loop in the ToolManager class, to better understand how that is used

In the PDFViewCtrlTools project, the ToolManager is the only class that directly subscribes to the PDFViewCtrl's events. This provides a centralized location to managed the different tools. The ToolManager forwards the event to various tools, inside a loop. The reason for this loop is that it allows a tool to process an event, decide if another tool should be handling it, and then let the ToolManager know that another type of tool should be getting the event. This is done by changing the next tool mode to that of the tool that should be processing the event. For example, the Pan tool will, when a Tapped event occurs, examine the contents of the point where the tap occurred. If the tap happened on a link, it will set the mNextToolMode to ToolType.elinkaction. Once the pan tool returns, the ToolManager will notice that the NextToolMode is different from the current ToolMode, it will create a LinkAction tool, and then call the Tapped handler on that tool. The link tool will then read the link and execute the associated action.