package org.icepdf.os.examples.annotation.callback; /* * Copyright 2006-2017 ICEsoft Technologies Canada Corp. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the * License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an "AS * IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either * express or implied. See the License for the specific language * governing permissions and limitations under the License. */ import org.icepdf.core.pobjects.Name; import org.icepdf.core.pobjects.Page; import org.icepdf.core.pobjects.actions.*; import org.icepdf.core.pobjects.annotations.Annotation; import org.icepdf.core.pobjects.annotations.BorderStyle; import org.icepdf.core.pobjects.annotations.LinkAnnotation; import org.icepdf.ri.common.SwingController; import org.icepdf.ri.common.views.AnnotationCallback; import org.icepdf.ri.common.views.AnnotationComponent; import org.icepdf.ri.common.views.DocumentViewController; import org.icepdf.ri.common.views.PageViewComponent; import org.icepdf.ri.util.BareBonesBrowserLaunch; import java.awt.*; import java.io.File; import java.util.List; import java.util.WeakHashMap; import java.util.logging.Level; import java.util.logging.Logger; /** * This class represents a basic implementation of the AnnotationCallback. This * class also modifies the border of annotation for initial display, showing a * border around all annotation. When an annotation is clicked on we then change * the colour of the annotation to an alternate colour to indicate that the link * has already been clicked. * * @author ICEsoft Technologies, Inc. * @since 2.7.1 */ public class MyAnnotationCallback implements AnnotationCallback { private static final Logger logger = Logger.getLogger(MyAnnotationCallback.class.toString()); private DocumentViewController documentViewController; // annotation History map similar to browser link history. This is weak // hash map to avoid any potential memory issue for a large document. As // this class lives for as long as the document is open. private WeakHashMap<String, AnnotationState> annotationHistory; private static final Color ANNOTATION = Color.red; private static final Color ANNOTATION_VISITED = Color.blue; public MyAnnotationCallback(DocumentViewController documentViewController) { this.documentViewController = documentViewController; // annotations click on history annotationHistory = new WeakHashMap<String, AnnotationState>(); } /** * <p>Implemented Annotation Callback method. When an annotation is * activated in a PageViewComponent it passes the annotation to this method * for processing. The PageViewComponent take care of drawing the * annotation states but it up to this method to process the * annotation.</p> * * @param annotation annotation that was activated by a user via the * PageViewComponent. */ public void processAnnotationAction(Annotation annotation, Action action, int x, int y) { if (logger.isLoggable(Level.INFO)) { logger.info("Annotation " + annotation.toString()); if (annotation.getAction() != null) { logger.info(" Action: " + annotation.getAction().toString()); } } if (annotation instanceof LinkAnnotation) { LinkAnnotation linkAnnotation = (LinkAnnotation) annotation; // look for an A entry, if (action != null) { // do instance of check to process actions correctly. if (action instanceof GoToAction && documentViewController != null) { documentViewController.setDestinationTarget( ((GoToAction) action).getDestination()); } else if (action instanceof URIAction) { BareBonesBrowserLaunch.openURL( ((URIAction) action).getURI()); } else if (action instanceof GoToRAction) { // process resource request } else if (action instanceof LaunchAction) { LaunchAction launchAction = (LaunchAction) action; String file = launchAction.getExternalFile(); String location = documentViewController.getDocument().getDocumentLocation(); location = location.substring(0, location.lastIndexOf(File.separator) + 1); BareBonesBrowserLaunch.openFile(location + file); } } // look for a Dest entry, only present if an action is not found // or vise versa. else if (linkAnnotation.getDestination() != null && documentViewController != null) { // use this controller to navigate to the correct page documentViewController.setDestinationTarget( linkAnnotation.getDestination()); } } // catch any other annotation types and try and process their action. else { // look for the dest entry and navigate to it. if (action != null) { if (action instanceof GoToAction) { documentViewController.setDestinationTarget( ((GoToAction) action).getDestination()); } else if (action instanceof URIAction) { BareBonesBrowserLaunch.openURL( ((URIAction) action).getURI()); } else if (action instanceof SubmitFormAction) { // submits form data following the submit actions. int responseCode = ((SubmitFormAction) action).executeFormAction(x, y); } else if (action instanceof ResetFormAction) { // resets the form data following reset action. int responseCode = ((ResetFormAction) action).executeFormAction(x, y); } else if (action instanceof JavaScriptAction) { // resets the form dat following reset actions properties JavaScriptAction javaScriptAction = (JavaScriptAction) action; if (logger.isLoggable(Level.FINE)) { logger.fine("Annotation JS: " + javaScriptAction.getJavaScript()); } } else if (action instanceof NamedAction) { // Named actions are key words that we should act on. NamedAction namedAction = (NamedAction) action; Name actionName = namedAction.getNamedAction(); // go to the first page of the document. if (NamedAction.FIRST_PAGE_KEY.equals(actionName)) { documentViewController.setCurrentPageIndex(0); } // go to the last page of the document. else if (NamedAction.LAST_PAGE_KEY.equals(actionName)) { int numberOfPages = documentViewController.getDocument().getNumberOfPages(); documentViewController.setCurrentPageIndex(numberOfPages - 1); } // next page. else if (NamedAction.NEXT_PAGE_KEY.equals(actionName)) { int currentPageNumber = documentViewController.getCurrentPageIndex(); documentViewController.setCurrentPageIndex(currentPageNumber + 1); } // previous page. else if (NamedAction.PREV_PAGE_KEY.equals(actionName)) { int currentPageNumber = documentViewController.getCurrentPageIndex(); documentViewController.setCurrentPageIndex(currentPageNumber - 1); } // print the current document. else if (NamedAction.PRINT_KEY.equals(actionName)) { SwingController controller = (SwingController) documentViewController.getParentController(); controller.print(true); } // show save as dialog. else if (NamedAction.SAVE_AS_KEY.equals(actionName)) { SwingController controller = (SwingController) documentViewController.getParentController(); controller.saveFile(); } } } } /** * Mark the annotation as visited. */ // get our history cache reference if any AnnotationState annotationState = annotationHistory.get(annotation.toString()); // if the weak reference is gone we need to put back a default state. if (annotationState != null) { annotationState.setColor(ANNOTATION_VISITED); // line width can also be set. // annotation.getBorderStyle().setStrokeWidth(1.0f); annotation.setColor(annotationState.getColor()); } // if the annotation is in the cache then we change its appearance to // a visited state. else { annotation.setColor(ANNOTATION_VISITED); annotationHistory.put(annotation.toString(), new AnnotationState(annotation.getColor(), annotation.getBorderStyle())); } } /** * New annotation created with view tool. * * @param page page that annotation was added to. */ public void newAnnotation(PageViewComponent page, AnnotationComponent annotation) { } public void updateAnnotation(AnnotationComponent annotationComponent) { } public void removeAnnotation(PageViewComponent pageComponent, AnnotationComponent annotationComponent) { } /** * <p>Implemented Annotation Callback method. This method is called when a * pages annotations been initialized but before the page has been painted. * This method blocks the </p> * * @param page page that has been initialized. The pages annotations are * available via an accessor method. */ public void pageAnnotationsInitialized(Page page) { List<Annotation> annotations = page.getAnnotations(); // no annotation, no problem just return. if (annotations == null || annotations.size() == 0) { return; } // otherwise we loop though the annotation and add our default border Annotation annotation; for (int i = 0, max = annotations.size(); i < max; i++) { processNullAnnotationDecoration(annotations.get(i)); } } /** * Utility method for changing the default state of a annotation border. * There is no guarantee that an annotation will actually have a border. For * this example we add a default border and colour to annotations that * have a null border style. If the annotation has a border we just store * the current state in the annotation history map. * * @param annotation annotation to decorate. */ private void processNullAnnotationDecoration(Annotation annotation) { AnnotationState annotationState = annotationHistory.get(annotation.toString()); BorderStyle borderStyle; // apply default style, freshly initialized page. if (annotationState == null) { // if there is a border already we paint it as it. if (annotation.getBorderStyle() != null) { annotationHistory.put(annotation.toString(), new AnnotationState(annotation.getColor(), annotation.getBorderStyle())); } // if no border we add our own custom border. else { borderStyle = new BorderStyle(); // set default paint styles borderStyle.setBorderStyle(BorderStyle.BORDER_STYLE_DASHED); annotation.setBorderStyle(borderStyle); if (annotation.getColor() == null) { annotation.setColor(ANNOTATION); } // add the state to the hash. annotationHistory.put(annotation.toString(), new AnnotationState( annotation.getColor(), borderStyle)); } } // If the annotationState is not null then we are dealing with a page // that has been disposed of due to memory constraints. In this case // we apply the previous border style and color. else { annotation.setBorderStyle(annotationState.getBorderStyle()); annotation.setColor(annotationState.getColor()); } } /** * Helper class for storing visited state information for annotations. */ protected class AnnotationState { private Color color; private BorderStyle borderStyle; public AnnotationState(Color color, BorderStyle borderStyle) { this.color = color; this.borderStyle = borderStyle; } public Color getColor() { return color; } public void setColor(Color color) { this.color = color; } public BorderStyle getBorderStyle() { return borderStyle; } public void setBorderStyle(BorderStyle borderStyle) { this.borderStyle = borderStyle; } } }