Customize annotation handling

By default, the Tools library will respond to user actions such as a click event on a link or form widget, or a property change event on a selected annotation. It is possible to customize such behavior before it is executed within the Tools library, as well as getting notified of an action after it has happened.

Intercept annotation events

If you would like to customize the behavior executed in response to user actions prior to it being handled by the Tools library, it is possible to do so with the BasicAnnotationListener.onInterceptAnnotationHandling(Annot, Bundle, int) API. If this method returns true, then it will intercept executing the default logic.

In BasicAnnotationListener.onInterceptAnnotationHandling(Annot, Bundle, int), the second parameter, Bundle, contains the name of the action intercepted by this function, as well as some extra information. You can get the name of the intercepted action by calling bundle.getString(Tool.METHOD_FROM):

1public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
2 if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
3 String methodCalling = extra.getString(Tool.METHOD_FROM);
4 }
5}

To get extra information, first obtain the information keys by calling bundle.getStringArray(Tool.KEYS):

1String[] paramKeys = extra.getStringArray(Tool.KEYS)

Then, you can get the information values by looping on each key obtained above:

1public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
2 if (extra != null && extra.containsKey(Tool.KEYS)) {
3 String[] paramKeys = extra.getStringArray(Tool.KEYS);
4 if (paramKeys != null) {
5 for (String key : paramKeys) {
6 // Gets the information value
7 Object param = extra.get(key);
8 }
9 }
10 }
11}

Common use cases

1mToolManager.setBasicAnnotationListener(new ToolManager.BasicAnnotationListener() {
2 @Override
3 public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
4 try {
5 // Intercept clicking link annotation by return true
6 if (annot.getType() == Annot.e_Link) {
7 Log.d("InterceptAnnot", "handling link annotation");
8 return true;
9 }
10 } catch (PDFNetException e) {
11 e.printStackTrace();
12 }
13 // return false so the other events can continue executing
14 return false;
15 }
16});

Form widgets

1mToolManager.setBasicAnnotationListener(new ToolManager.BasicAnnotationListener() {
2 @Override
3 public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
4 try {
5 // Intercept clicking widget annotation by return true
6 if (annot.getType() == Annot.e_Widget) {
7 Log.d("InterceptAnnot", "handling widget annotation");
8 return true;
9 }
10 } catch (PDFNetException e) {
11 e.printStackTrace();
12 }
13 // return false so the other events can continue executing
14 return false;
15 }
16});

Full sample code

For example, the following code demonstrates several scenarios and how you can get notified before each: clicking on a radio button, changing the annotation opacity, and clicking on a link. See the comments in the code for details.

1mToolManager.setBasicAnnotationListener(new ToolManager.BasicAnnotationListener() {
2 @Override
3 public boolean onInterceptAnnotationHandling(Annot annot, Bundle extra, ToolMode toolMode) {
4 /*
5 For example, when a radio button is clicked, this code will print:
6 calling method: handleWidget
7 property: OTHER
8 */
9 if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
10 String methodCalling = extra.getString(Tool.METHOD_FROM);
11 Log.d("InterceptAnnot", "calling method " + methodCalling);
12 AnnotationProperty.Property property = AnnotationProperty.getProperty(methodCalling);
13 Log.d("InterceptAnnot", "property: " + property);
14 }
15 /*
16 For example, when annotation opacity is about to be changed to 50%, this code will print:
17 calling method: editOpacity
18 property: OPACITY
19 key: opacity
20 value: 0.5
21 */
22 if (extra != null && extra.containsKey(Tool.KEYS)) {
23 String[] paramKeys = extra.getStringArray(Tool.KEYS);
24 if (paramKeys != null) {
25 for (String key : paramKeys) {
26 Object param = extra.get(key);
27 Log.d("InterceptAnnot", "key: " + key);
28 Log.d("InterceptAnnot", "value: " + param.toString());
29 }
30 }
31 }
32 try {
33 // Intercept radio button from clicking by return true
34 if(annot.getType() == Annot.e_Widget) {
35 Widget w = new Widget(annot);
36 Field field = w.getField();
37 if (field != null && field.isValid() && field.getType() == Field.e_radio) {
38 return true;
39 }
40 }
41 // Intercept clicking link annotation by return true
42 if (annot.getType() == Annot.e_Link) {
43 Log.d("InterceptAnnot", "handling link annotation");
44 }
45 } catch (PDFNetException e) {
46 e.printStackTrace();
47 }
48 // return false so the other events can continue executing
49 return false;
50 }
51});

Get notified after an action

If you simply want to get notified after the action has happened, you can do so via the AnnotationModificationListener.onAnnotationsModified(Map<Annot, Integer>) API. This event callback is raised when an annotation change has occurred. For example, in order to get notified when the value of a checkbox has been changed and when annotation opacity has been changed, do the following:

1ToolManager.AnnotationModificationListener annotationModificationListener = new ToolManager.AnnotationModificationListener() {
2 @Override
3 public void onAnnotationsModified(Map<Annot, Integer> annots, Bundle extra) {
4 /*
5 For example, when a checkbox's value has been changed, this code will print:
6 calling method: handleWidget
7 property: OTHER
8 */
9 if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
10 String methodCalling = extra.getString(Tool.METHOD_FROM);
11 Log.d("AnnotationsModified", "calling method " + methodCalling);
12 AnnotationProperty.Property property = AnnotationProperty.getProperty(methodCalling);
13 Log.d("AnnotationsModified", "property: " + property);
14 }
15 /*
16 For example, when annotation opacity is changed to 50%, this code will print:
17 calling method: editOpacity
18 property: OPACITY
19 key: opacity
20 value: 0.5
21 */
22 if (extra != null && extra.containsKey(Tool.KEYS)) {
23 String[] paramKeys = extra.getStringArray(Tool.KEYS);
24 if (paramKeys != null) {
25 for (String key : paramKeys) {
26 Object param = extra.get(key);
27 Log.d("AnnotationsModified", "key: " + key);
28 Log.d("AnnotationsModified", "value: " + param.toString());
29 }
30 }
31 }
32 }
33};
34mToolManager.addAnnotationModificationListener(annotationModificationListener);
1ToolManager.AnnotationModificationListener annotationModificationListener = new ToolManager.AnnotationModificationListener() {
2 @Override
3 public void onAnnotationsModified(Map<Annot, Integer> annots, Bundle extra) {
4 /*
5 For example, when a checkbox's value has been changed, this code will print:
6 calling method: handleWidget
7 property: OTHER
8 */
9 if (extra != null && extra.containsKey(Tool.METHOD_FROM)) {
10 String methodCalling = extra.getString(Tool.METHOD_FROM);
11 Log.d("AnnotationsModified", "calling method " + methodCalling);
12 AnnotationProperty.Property property = AnnotationProperty.getProperty(methodCalling);
13 Log.d("AnnotationsModified", "property: " + property);
14 }
15
16 /*
17 For example, when annotation opacity is changed to 50%, this code will print:
18 calling method: editOpacity
19 property: OPACITY
20 key: opacity
21 value: 0.5
22 */
23 if (extra != null && extra.containsKey(Tool.KEYS)) {
24 String[] paramKeys = extra.getStringArray(Tool.KEYS);
25 if (paramKeys != null) {
26 for (String key : paramKeys) {
27 Object param = extra.get(key);
28 Log.d("AnnotationsModified", "key: " + key);
29 Log.d("AnnotationsModified", "value: " + param.toString());
30 }
31 }
32 }
33 }
34};
35mToolManager.addAnnotationModificationListener(annotationModificationListener);

When finished with the callback, do:

1mToolManager.removeAnnotationModificationListener(annotationModificationListener);

We are always interested in expanding the customization options through APIs, and will be adding more options in the future. If you would like to suggest changes, please don't hesitate to get in touch.

Did you find this helpful?

Trial setup questions?

Ask experts on Discord

Need other help?

Contact Support

Pricing or product questions?

Contact Sales