/*
* Copyright 2006-2012 ICEsoft Technologies Inc.
*
* 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.
*/
package org.icepdf.core.views.common;
import org.icepdf.core.pobjects.Page;
import org.icepdf.core.pobjects.annotations.Annotation;
import org.icepdf.core.util.GraphicsRenderingHints;
import org.icepdf.core.views.DocumentViewController;
import org.icepdf.core.views.DocumentViewModel;
import org.icepdf.core.views.AnnotationComponent;
import org.icepdf.core.views.swing.AbstractPageViewComponent;
import org.icepdf.core.views.swing.AnnotationComponentImpl;
import javax.swing.event.MouseInputListener;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.util.ArrayList;
import java.util.logging.Logger;
/**
* <p>This classes purpose is to manage annotation selected state and the
* broadcaset of resized and moved for multiple selected components. The
* other purpose of this class is to handle the drawing of a selection box
* and handle the creation of new link annotation when the link annotation
* tool is selected </p>
*
* @since 4.0
*/
public class AnnotationHandler extends SelectionBoxHandler
implements MouseInputListener {
private static final Logger logger =
Logger.getLogger(AnnotationHandler.class.toString());
// parent page component
private AbstractPageViewComponent pageViewComponent;
private DocumentViewController documentViewController;
private DocumentViewModel documentViewModel;
// flag to indicate a drag had occured.
private boolean isDragged;
// annotations component for pageViewComp.
private ArrayList<AnnotationComponent> annotations;
// selected annotations.
// todo: implement multiple select, should probably go in documentViewModel
// instead.
private ArrayList<AnnotationComponentImpl> selectedAnnotations;
public AnnotationHandler(AbstractPageViewComponent pageViewComponent,
DocumentViewModel documentViewModel) {
this.pageViewComponent = pageViewComponent;
this.documentViewModel = documentViewModel;
selectedAnnotations = new ArrayList<AnnotationComponentImpl>();
selectionBoxColour = Color.GRAY;
}
/**
* DocumentController callback
*
* @param documentViewController document controller.
*/
public void setDocumentViewController(
DocumentViewController documentViewController) {
this.documentViewController = documentViewController;
}
/**
* Initializes the annotation components given the annotations collections.
*
* @param annotations annotations to wrap with annotations components.
*/
public void initializeAnnotationComponents(ArrayList<Annotation> annotations){
if (this.annotations == null && annotations != null){
this.annotations = new ArrayList<AnnotationComponent>(annotations.size());
AnnotationComponentImpl comp;
for (Annotation annotation : annotations) {
if (!(annotation.getFlagInvisible() ||
annotation.getFlagHidden())) {
comp = new AnnotationComponentImpl(annotation,
documentViewController,
pageViewComponent, documentViewModel);
// add them to the container, using absolute positioning.
pageViewComponent.add(comp);
// add the comp reference locally so we have easier access
this.annotations.add(comp);
}
}
}
}
/**
* Wraps the specified annotaiton with a new Annotation component and adds
* it to the PageViewComponent as a child.
* @param annotation new annotation to add to PageView.
*/
public AnnotationComponent addAnnotationComponent(Annotation annotation){
// initialize annotations
if (annotations == null){
annotations = new ArrayList<AnnotationComponent>();
}
// make sure we don't add the following types.
if (!(annotation.getFlagInvisible() ||
annotation.getFlagHidden())) {
AnnotationComponentImpl comp = new AnnotationComponentImpl(annotation,
documentViewController,
pageViewComponent, documentViewModel);
// add them to the container, using absolute positioning.
pageViewComponent.add(comp);
// add the comp reference locally so we have easier access
this.annotations.add(comp);
// set the new annotation as the selected one.
documentViewController.clearSelectedAnnotations();
return comp;
}
return null;
}
/**
* Removes the specified annotation from the page view. The component
* is actually set to invisible. We need to keep the component around
* so that it can be made visible on an undo, as each state var keeps a
* reference to the component it is
* @param annotation annotation component to removed.
*/
public void removeAnnotationComponent(AnnotationComponent annotation){
// initialize annotations
if (annotations == null){
return;
}
((Component)annotation).setVisible(false);
// set the new annotation as the selected one.
documentViewController.assignSelectedAnnotation(null);
}
/**
* Creates a new link annotation when the link annotation creation tool is
* selected. The bounds of the annotation are defined by the current
* selection box that has none zero bounds. If the two previous
* conditions are met then the annotation callback is fired and an
* width a new annotation object which can be updated by the end user
* using either the api or UI tools.
*/
public void createNewLinkAnnotation() {
if (documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_LINK_ANNOTATION) {
if (documentViewController.getAnnotationCallback() != null) {
// convert the drawn rectangle to page space.
documentViewController.getAnnotationCallback()
.newAnnotation(pageViewComponent, rectToDraw);
}
}
}
/**
* Adds an Annotation component to the list of selected. The list
* of selected annotations is used do batch resize and moved commands.
*
* @param annotationComponent component to add to list of selected annotations
*/
public void addSelectedAnnotation(AnnotationComponentImpl annotationComponent) {
selectedAnnotations.add(annotationComponent);
}
/**
* Adds an Annotation component to the list of selected. The list
* of selected annotations is used do batch resize and moved commands.
*
* @param annotationComponent remove the specified annotation from the
* selection list
*/
public void removeSelectedAnnotation(AnnotationComponentImpl annotationComponent) {
selectedAnnotations.remove(annotationComponent);
}
/**
* Clears the slected list of AnnotationComponent, PageViewComponent
* focus should be called after this method is called to insure deselection
* of all AnnotationComponents.
*/
public void clearSelectedList() {
selectedAnnotations.clear();
selectedAnnotations.trimToSize();
}
/**
* Determines if there are more then one selected component. If there is
* more then one component that steps should be made to do batch move and
* resize propigation.
*
* @return true if there are more then one AnnotationComponents in a selected
* state
*/
public boolean isMultipleSelect() {
return selectedAnnotations.size() > 1;
}
/**
* Moves all selected annotation components by the x,y translation.
*
* @param x x-axis offset to be applied to all selected annotation.
* @param y y-axis offset to be applied to all selected annotation.
*/
public void moveSelectedAnnotations(int x, int y) {
// todo implement
// considerations to make sure annotation is not outside of page bounds
}
/**
* Resizes all selected annotation components by the width and height
* values.
*
* @param width width offset to be applied to all selected annotation.
* @param height height offset to be applied to all selected annotation.
*/
public void resizeSelectedAnnotations(int width, int height) {
// todo implement
// considerations to make sure annotation is not outside of page bounds
}
public void mouseClicked(MouseEvent e) {
}
public void mousePressed(MouseEvent e) {
clearSelectedList();
// annotation selection box.
if (documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_SELECTION||
documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_LINK_ANNOTATION) {
int x = e.getX();
int y = e.getY();
currentRect = new Rectangle(x, y, 0, 0);
updateDrawableRect(pageViewComponent.getWidth(),
pageViewComponent.getHeight());
pageViewComponent.repaint();
}
}
public void mouseDragged(MouseEvent e) {
isDragged = true;
if (documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_SELECTION ||
documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_LINK_ANNOTATION) {
// rectangle select tool
updateSelectionSize(e, pageViewComponent);
}
}
public void mouseReleased(MouseEvent e) {
// update selection rectangle
updateSelectionSize(e, pageViewComponent);
if (documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_SELECTION) {
// clear the rectangle
clearRectangle(pageViewComponent);
pageViewComponent.repaint();
}
// link annotations tool.
else if (documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_LINK_ANNOTATION &&
isDragged){
createNewLinkAnnotation();
// clear the rectangle
clearRectangle(pageViewComponent);
pageViewComponent.repaint();
}
isDragged = false;
}
public void mouseMoved(MouseEvent e) {
}
public void mouseEntered(MouseEvent e) {
}
public void mouseExited(MouseEvent e) {
}
/**
* Paints all annotation content for a given page view. If any annotation
* properties are changed then this method must be called to repaint the
* page annotations.
* <p/>
* todo: as a future enhancement it would be great if each Annotation
* component did its own painting, this would take a little more time
* to figure out the correct coordinate space.
*
* @param g parent PageViewComponent graphics context to paint annotations
* to.
*/
public void paintAnnotations(Graphics g) {
Page currentPage = pageViewComponent.getPageLock(this);
if (currentPage != null && currentPage.isInitiated()) {
if (annotations != null) {
Graphics2D gg2 = (Graphics2D) g;
// save draw state.
AffineTransform prePaintTransform = gg2.getTransform();
Color oldColor = gg2.getColor();
Stroke oldStroke = gg2.getStroke();
// apply page transform.
AffineTransform at = currentPage.getPageTransform(
documentViewModel.getPageBoundary(),
documentViewModel.getViewRotation(),
documentViewModel.getViewZoom());
gg2.transform(at);
// get current tool state, we don't want to draw the highlight
// state if the selection tool is selected.
boolean notSelectTool =
documentViewModel.getViewToolMode() !=
DocumentViewModel.DISPLAY_TOOL_SELECTION;
// paint all annotations on top of the content buffer
for (AnnotationComponent annotation : annotations) {
if (((Component)annotation).isVisible()){
annotation.getAnnotation().render(gg2,
GraphicsRenderingHints.SCREEN,
documentViewModel.getViewRotation(),
documentViewModel.getViewZoom(),
annotation.hasFocus() && notSelectTool);
}
}
// post paint clean up.
gg2.setColor(oldColor);
gg2.setStroke(oldStroke);
gg2.setTransform(prePaintTransform);
}
}
pageViewComponent.releasePageLock(currentPage, this);
// paint new link annotation bound box.
if (documentViewModel.getViewToolMode() ==
DocumentViewModel.DISPLAY_TOOL_LINK_ANNOTATION){
paintSelectionBox(g);
}
}
/**
private void annotationMouseMoveHandler(Page currentPage,
Point mouseLocation) {
if (currentPage != null &&
currentPage.isInitiated() &&
isInteractiveAnnotationsEnabled) {
ArrayList<Annotation> annotations = currentPage.getAnnotations();
if (annotations != null) {
Annotation annotation;
Object tmp;
AffineTransform at = currentPage.getPageTransform(
documentViewModel.getPageBoundary(),
documentViewModel.getViewRotation(),
documentViewModel.getViewZoom());
try {
at.inverseTransform(mouseLocation, mouseLocation);
} catch (NoninvertibleTransformException e1) {
e1.printStackTrace();
}
for (Object annotation1 : annotations) {
tmp = annotation1;
if (tmp instanceof Annotation) {
annotation = (Annotation) tmp;
// repaint an annotation.
if (annotation.getUserSpaceRectangle().contains(
mouseLocation.getX(), mouseLocation.getY())) {
currentAnnotation = annotation;
documentViewController.setViewCursor(DocumentViewController.CURSOR_HAND_ANNOTATION);
// repaint(annotation.getUserSpaceRectangle().getBounds());
pageViewComponent.repaint();
break;
} else {
currentAnnotation = null;
}
}
}
if (currentAnnotation == null) {
int toolMode = documentViewModel.getViewToolMode();
if (toolMode == DocumentViewModel.DISPLAY_TOOL_PAN) {
documentViewController.setViewCursor(DocumentViewController.CURSOR_HAND_OPEN);
} else if (toolMode == DocumentViewModel.DISPLAY_TOOL_ZOOM_IN) {
documentViewController.setViewCursor(DocumentViewController.CURSOR_ZOOM_IN);
} else if (toolMode == DocumentViewModel.DISPLAY_TOOL_ZOOM_OUT) {
documentViewController.setViewCursor(DocumentViewController.CURSOR_ZOOM_OUT);
} else if (toolMode == DocumentViewModel.DISPLAY_TOOL_TEXT_SELECTION) {
documentViewController.setViewCursor(DocumentViewController.CURSOR_SELECT);
}
pageViewComponent.repaint();
}
}
}
}
*/
}