summaryrefslogtreecommitdiff
path: root/pdf-over-gui/src/main/java
diff options
context:
space:
mode:
Diffstat (limited to 'pdf-over-gui/src/main/java')
-rw-r--r--pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/SignaturePanel.java1098
1 files changed, 549 insertions, 549 deletions
diff --git a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/SignaturePanel.java b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/SignaturePanel.java
index 193f5974..575c8f86 100644
--- a/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/SignaturePanel.java
+++ b/pdf-over-gui/src/main/java/at/asit/pdfover/gui/composites/SignaturePanel.java
@@ -1,549 +1,549 @@
-/*
- * Copyright 2012 by A-SIT, Secure Information Technology Center Austria
- *
- * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
- * the European Commission - subsequent versions of the EUPL (the "Licence");
- * You may not use this work except in compliance with the Licence.
- * You may obtain a copy of the Licence at:
- * http://joinup.ec.europa.eu/software/page/eupl
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the Licence is distributed on an "AS IS" basis,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the Licence for the specific language governing permissions and
- * limitations under the Licence.
- */
-package at.asit.pdfover.gui.composites;
-
-// Imports
-import java.awt.BorderLayout;
-import java.awt.Color;
-import java.awt.Cursor;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.Image;
-import java.awt.event.MouseAdapter;
-import java.awt.event.MouseEvent;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.NoninvertibleTransformException;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-
-import javax.swing.JPanel;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import at.asit.pdfover.gui.Constants;
-import at.asit.pdfover.gui.utils.Messages;
-
-import com.sun.pdfview.PDFFile;
-import com.sun.pdfview.PDFPage;
-
-/**
- *
- */
-public class SignaturePanel extends JPanel {
- /**
- * SLF4J Logger instance
- **/
- private static final Logger log = LoggerFactory
- .getLogger(SignaturePanel.class);
-
- /** Default serial version ID */
- private static final long serialVersionUID = 1L;
-
- /** The PDF file being displayed */
- private PDFFile pdf = null;
- /** The image of the rendered PDF page being displayed */
- Image currentImage = null;
- /** The current PDFPage that was rendered into currentImage */
- private PDFPage currentPage = null;
- /** The current transform from screen to page space */
- AffineTransform currentXform = null;
- /** The horizontal offset of the image from the left edge of the panel */
- int offX = 0;
- /** The vertical offset of the image from the top of the panel */
- int offY = 0;
- /** The size of the image */
- private Dimension prevSize = null;
- /** The position of the signature, in page space */
- Point2D sigPagePos = null;
- /** The position of the signature, in screen space */
- Point2D sigScreenPos = null;
- /** The signature placeholder image */
- private Image sigPlaceholder = null;
- /** Current scaled signature placeholder image */
- BufferedImage sigPlaceholderScaled = null;
- /** Transparency of the signature placeholder (0-255) */
- private int sigPlaceholderTransparency = Constants.DEFAULT_SIGNATURE_PLACEHOLDER_TRANSPARENCY;
- /** Previous Transparency of the signature placeholder */
- private int prevSigPlaceholderTransparency = 0;
- /** Width of the signature placeholder in page space */
- private int sigPageWidth = 0;
- /** Height of the signature placeholder in page space */
- private int sigPageHeight = 0;
- /** Width of the signature placeholder in screen space */
- int sigScreenWidth = 0;
- /** Height of the signature placeholder in screen space */
- int sigScreenHeight = 0;
- /** Previous Width of the signature placeholder in screen space */
- int prevSigScreenWidth = 0;
- /** Previous Height of the signature placeholder in screen space */
- int prevSigScreenHeight = 0;
- /** Color of the signature placeholder border */
- private Color sigPlaceholderBorderColor = Color.BLUE;
- /** Current page */
- int page = 0;
- /** Number of pages in the document */
- int numPages = 0;
- /** Cursor types */
- static enum Cursors {DEFAULT, HAND, MOVE};
- /** Default arrow cursor */
- final Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
- /** Hand cursor */
- final Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
- /** Move cursor */
- final Cursor moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
- /** Current cursor */
- Cursors currentCursor = Cursors.DEFAULT;
-
- /**
- * Create a new PagePanel.
- * @param pdf the PDFFile to display
- */
- public SignaturePanel(PDFFile pdf) {
- super(new BorderLayout());
- setDocument(pdf);
- setPreferredSize(new Dimension(Constants.DEFAULT_MAINWINDOW_WIDTH, Constants.DEFAULT_MAINWINDOW_HEIGHT - Constants.MAINBAR_HEIGHT));
- setFocusable(true);
- addMouseListener(this.mouseListener);
- addMouseMotionListener(this.mouseListener);
- }
-
- /**
- * Set a new document to be displayed
- * @param pdf the PDFFile to be displayed
- */
- public void setDocument(PDFFile pdf) {
- this.pdf = pdf;
- this.sigPagePos = null;
- this.numPages = pdf.getNumPages();
- showPage(this.numPages);
- }
-
- /**
- * Set the signature placeholder image
- * @param placeholder signature placeholder
- * @param width width of the placeholder in page space
- * @param height height of the placeholder in page space
- * @param transparency transparency of the signature placeholder (0 - 255)
- */
- public void setSignaturePlaceholder(Image placeholder, int width, int height, int transparency) {
- this.sigPlaceholder = placeholder;
- this.sigPageWidth = width;
- this.sigPageHeight = height;
- this.sigPlaceholderTransparency = transparency;
- }
-
- /**
- * Set the color of the signature placeholder border
- * @param color new signature placeholder border color
- */
- public void setSignaturePlaceholderBorderColor(Color color) {
- this.sigPlaceholderBorderColor = color;
- }
-
- /**
- * Change the currently displayed page
- * @param page the number of the page to display
- */
- public void showPage(int page) {
- this.page = page;
- showPage(this.pdf.getPage(page));
- }
-
- /**
- * Add and display a new page at the end of the document
- *
- * This page has the same dimensions as the old last page
- */
- public void addNewLastPage() {
- showPage(this.numPages + 1);
- }
-
- /**
- * Translate the signature placeholder position
- * @param sigXOffset signature placeholder horizontal position offset
- * @param sigYOffset signature placeholder vertical position offset
- */
- public void translateSignaturePosition(int sigXOffset, int sigYOffset) {
- updateSigPos((int) this.sigScreenPos.getX() + sigXOffset, (int) this.sigScreenPos.getY() + sigYOffset);
- }
-
- /**
- * Set the signature placeholder position
- * Call showPage afterwards to update actual position
- * @param x the horizontal signature position
- * @param y the vertical signature position
- */
- public void setSignaturePosition(float x, float y)
- {
- this.sigPagePos = new Point2D.Double(x, y);
- }
-
- /**
- * Get the current horizontal position of the signature
- * @return signature x coordinate
- */
- public float getSignaturePositionX() {
- if (this.sigPagePos == null)
- return 0;
- return Math.max((float) this.sigPagePos.getX(), 0);
- }
-
- /**
- * Get the current vertical position of the signature
- * @return signature y coordinate
- */
- public float getSignaturePositionY() {
- if (this.sigPagePos == null)
- return 0;
- return Math.max((float) this.sigPagePos.getY(), 0);
- }
-
- /**
- * Stop the generation of any previous page, and draw the new one.
- *
- * @param page the PDFPage to draw.
- */
- private synchronized void showPage(PDFPage page) {
- // stop drawing the previous page
- if (this.currentPage != null && this.prevSize != null) {
- this.currentPage.stop(this.prevSize.width, this.prevSize.height, null);
- }
-
- boolean newPage = false;
- // set up the new page
- if (this.page > this.numPages)
- {
- // New last page - use old last page as template
- this.currentPage = this.pdf.getPage(this.numPages);
- newPage = true;
- }
- else
- this.currentPage = page;
-
-
- if (this.currentPage == null) {
- // no page
- this.currentImage = null;
- this.currentXform = null;
- repaint();
- } else {
- // start drawing
- Dimension sz = getSize();
- if (sz.width + sz.height == 0) {
- // no image to draw.
- return;
- }
-
- Dimension pageSize = this.currentPage.getUnstretchedSize(sz.width, sz.height,
- null);
-
- // get the new image
- if (newPage)
- {
- this.currentImage = new BufferedImage(pageSize.width, pageSize.height, BufferedImage.TYPE_INT_RGB);
- Graphics g = this.currentImage.getGraphics();
- g.setColor(Color.WHITE);
- g.fillRect(0, 0, pageSize.width, pageSize.height);
- }
- else
- this.currentImage = this.currentPage.getImage(pageSize.width, pageSize.height,
- null, this);
-
- // calculate the transform from page to screen space
- this.currentXform = new AffineTransform(1, 0, 0, -1, 0, pageSize.height);
- Rectangle2D clip = this.currentPage.getBBox();
- double scaleX = pageSize.width / clip.getWidth();
- double scaleY = pageSize.height / clip.getHeight();
- this.currentXform.scale(scaleX, scaleY);
- this.currentXform.translate(-clip.getMinX(), -clip.getMinY());
-
- if (this.sigPagePos != null)
- this.sigScreenPos = this.currentXform.transform(this.sigPagePos, this.sigScreenPos);
- this.sigScreenWidth = (int) Math.round(this.sigPageWidth * this.currentXform.getScaleX());
- this.sigScreenHeight = (int) Math.round(this.sigPageHeight * this.currentXform.getScaleX());
-
- // invert the transform (screen to page space)
- try {
- this.currentXform = this.currentXform.createInverse();
- } catch (NoninvertibleTransformException nte) {
- log.error("Error inverting page transform!", nte); //$NON-NLS-1$
- }
-
- if (this.sigPagePos == null)
- {
- this.sigScreenPos = new Point2D.Double(
- clamp((int) (pageSize.getWidth() / 2), 0, this.currentImage.getWidth(null) - this.sigScreenWidth),
- clamp((int) ((pageSize.getHeight() / 4) * 3), 0, this.currentImage.getHeight(null) - this.sigScreenHeight));
- this.sigPagePos = this.currentXform.transform(this.sigScreenPos, this.sigPagePos);
- }
- else
- updateSigPos((int) this.sigScreenPos.getX(), (int) this.sigScreenPos.getY());
-
- this.prevSize = pageSize;
-
- repaint();
- }
- }
-
- /**
- * Draw the image.
- */
- @Override
- public void paint(Graphics g) {
- Dimension sz = getSize();
- g.setColor(getBackground());
- g.fillRect(0, 0, getWidth(), getHeight());
- if (this.currentImage == null) {
- g.setColor(Color.black);
- g.drawString(Messages.getString("error.SignaturePanel.NoPage"), getWidth() / 2 - 30, //$NON-NLS-1$
- getHeight() / 2);
- if (this.currentPage != null) {
- showPage(this.currentPage);
- }
- } else {
- // draw the image
- int imwid = this.currentImage.getWidth(null);
- int imhgt = this.currentImage.getHeight(null);
-
- // draw it centered within the panel
- this.offX = (sz.width - imwid) / 2;
- this.offY = (sz.height - imhgt) / 2;
-
- if ((imwid == sz.width && imhgt <= sz.height)
- || (imhgt == sz.height && imwid <= sz.width)) {
-
- // draw document
- g.drawImage(this.currentImage, this.offX, this.offY, this);
-
- // draw signature
- int sigX = (int) (this.offX + this.sigScreenPos.getX());
- int sigY = (int) (this.offY + this.sigScreenPos.getY());
- if (this.sigPlaceholder == null) {
- g.setColor(Color.red);
- g.drawRect(sigX, sigY, 100, 40);
- }
- else {
- if (
- ((this.sigScreenWidth != this.prevSigScreenWidth) ||
- (this.sigScreenHeight != this.prevSigScreenHeight) ||
- (this.sigPlaceholderTransparency != this.prevSigPlaceholderTransparency)) &&
- ((this.sigScreenWidth != 0) && (this.sigScreenHeight != 0)))
- {
- // redraw scaled transparent placeholder
- this.prevSigScreenWidth = this.sigScreenWidth;
- this.prevSigScreenHeight = this.sigScreenHeight;
- this.prevSigPlaceholderTransparency = this.sigPlaceholderTransparency;
- Image placeholder = this.sigPlaceholder.getScaledInstance(
- this.sigScreenWidth, this.sigScreenHeight, Image.SCALE_SMOOTH);
-
- //Make placeholder transparent
- this.sigPlaceholderScaled = new BufferedImage(this.sigScreenWidth, this.sigScreenHeight, BufferedImage.TYPE_INT_ARGB);
- Graphics g_phs = this.sigPlaceholderScaled.getGraphics();
- g_phs.drawImage(placeholder, 0, 0, null);
-
- // Draw grey "Signature" overlay
- String overlay = Messages.getString("positioning.signature"); //$NON-NLS-1$
- // Voodoo to get overlay font scale
- float scale = (((float) this.sigScreenWidth) / this.sigPlaceholder.getWidth(null)) * 150;
- g_phs.setFont(getFont().deriveFont(scale));
- g_phs.setColor(this.sigPlaceholderBorderColor);
- Rectangle2D overlay_size = g_phs.getFontMetrics().getStringBounds(overlay, g_phs);
- int width = (int) overlay_size.getWidth();
- int height = (int) overlay_size.getHeight();
- int x = this.sigScreenWidth / 2 - width / 2;
- int y = this.sigScreenHeight / 2 - height / 2 + g_phs.getFontMetrics().getAscent();
- g_phs.drawString(overlay, x, y);
-
- g_phs.dispose();
- int[] phpixels = new int[this.sigScreenWidth * this.sigScreenHeight];
- phpixels = this.sigPlaceholderScaled.getRGB(0, 0, this.sigScreenWidth, this.sigScreenHeight, phpixels, 0, this.sigScreenWidth);
- for (int i = 0; i < phpixels.length; ++i) {
- Color c = new Color(phpixels[i]);
- c = new Color(c.getRed(), c.getGreen(), c.getBlue(), this.sigPlaceholderTransparency);
- phpixels[i] = c.getRGB();
- }
- this.sigPlaceholderScaled.setRGB(0, 0, this.sigScreenWidth, this.sigScreenHeight, phpixels, 0, this.sigScreenWidth);
- }
- g.drawImage(this.sigPlaceholderScaled, sigX, sigY, null);
- g.setColor(this.sigPlaceholderBorderColor);
- g.drawRect(sigX, sigY, this.sigScreenWidth-1, this.sigScreenHeight-1);
- }
-
- } else {
- // the image is bogus. try again, or give up.
- if (this.currentPage != null) {
- showPage(this.currentPage);
- }
- g.setColor(Color.black);
- g.drawString(Messages.getString("error.SignaturePanel.NoRender"), getWidth() / 2 - 30, //$NON-NLS-1$
- getHeight() / 2);
- }
- }
- }
-
- /**
- * Handles notification of the fact that some part of the image changed.
- * Repaints that portion.
- *
- * @return true if more updates are desired.
- */
- @Override
- public boolean imageUpdate(Image img, int infoflags, int x, int y,
- int width, int height) {
- if ((infoflags & (SOMEBITS | ALLBITS)) != 0) {
- repaint(x + this.offX, y + this.offY, width, height);
- }
- return ((infoflags & (ALLBITS | ERROR | ABORT)) == 0);
- }
-
- private MouseAdapter mouseListener = new MouseAdapter() {
-
- private boolean doDrag = false;
- private int dragXOffset = 0;
- private int dragYOffset = 0;
-
- private void updateSigPos(int sigx, int sigy) {
- SignaturePanel.this.updateSigPos(
- sigx - SignaturePanel.this.offX,
- sigy - SignaturePanel.this.offY);
- }
-
- /** Handles a mouseMoved event */
- @Override
- public void mouseMoved(MouseEvent evt) {
-// try {
- boolean onSig = isOnSignature(evt.getX(), evt.getY());
- setCursor(onSig ? Cursors.HAND : Cursors.DEFAULT);
-// }catch (NullPointerException e) {
-// log.debug("Error " +e.getMessage()); //$NON-NLS-1$
-// }
- }
-
- /** Handles a mousePressed event */
- @Override
- public void mousePressed(MouseEvent evt) {
- if (evt.getButton() == MouseEvent.BUTTON1)
- {
- this.doDrag = true;
- if (isOnSignature(evt.getX(), evt.getY())) {
- this.dragXOffset = (int)
- (SignaturePanel.this.sigScreenPos.getX() -
- (evt.getX() - SignaturePanel.this.offX));
- this.dragYOffset = (int)
- (SignaturePanel.this.sigScreenPos.getY() -
- (evt.getY() - SignaturePanel.this.offY));
- }
- else {
- this.dragXOffset = 0;
- this.dragYOffset = 0;
- }
- updateSigPos(evt.getX() + this.dragXOffset, evt.getY() + this.dragYOffset);
- setCursor(Cursors.MOVE);
- }
- }
-
- /** Handles a mouseReleased event */
- @Override
- public void mouseReleased(MouseEvent evt) {
- this.doDrag = false;
- boolean onSig = isOnSignature(evt.getX(), evt.getY());
- setCursor(onSig ? Cursors.HAND : Cursors.DEFAULT);
- }
-
- /**
- * Handles a mouseDragged event.
- */
- @Override
- public void mouseDragged(MouseEvent evt) {
- if (this.doDrag)
- updateSigPos(evt.getX() + this.dragXOffset, evt.getY() + this.dragYOffset);
- }
- };
-
- /**
- * Sets the mouse cursor
- * @param cursor cursor to set
- */
- void setCursor(Cursors cursor)
- {
- if (this.currentCursor == cursor)
- return;
- this.currentCursor = cursor;
- Cursor cur = null;
- switch (cursor) {
- case DEFAULT:
- cur = this.defaultCursor;
- break;
- case HAND:
- cur = this.handCursor;
- break;
- case MOVE:
- cur = this.moveCursor;
- break;
- }
- this.getParent().setCursor(cur);
- }
-
- /**
- * Check whether given point is on signature placeholder
- * @param x x coordinate
- * @param y y coordinate
- * @return true if given point is on signature placeholder
- */
- boolean isOnSignature(int x, int y)
- {
- Rectangle2D sig = new Rectangle2D.Double(
- this.sigScreenPos.getX() + this.offX,
- this.sigScreenPos.getY() + this.offY,
- this.sigScreenWidth,
- this.sigScreenHeight);
- Point2D pos = new Point2D.Double(x, y);
- return (sig.contains(pos));
- }
-
- /**
- * Update the signature placeholder position
- * @param sigx X position on the document (screen coordinates)
- * @param sigy Y position on the document (screen coordinates)
- */
- void updateSigPos(int sigx, int sigy) {
- if (this.currentImage == null)
- return;
- sigx = clamp(sigx, 0, this.currentImage.getWidth(null) - this.sigScreenWidth);
- sigy = clamp(sigy, 0, this.currentImage.getHeight(null) - this.sigScreenHeight);
- this.sigScreenPos = new Point2D.Double(sigx, sigy);
- this.sigPagePos = this.currentXform.transform(this.sigScreenPos, this.sigPagePos);
- repaint();
- }
-
- /**
- * Clamp x to be within [min-max]
- * @param x int to clamp
- * @param min minimum value
- * @param max maximum value
- * @return clamped x
- */
- static int clamp(int x, int min, int max)
- {
- if (x < min)
- x = min;
- else if (x > max)
- x = max;
- return x;
- }
-}
+/*
+ * Copyright 2012 by A-SIT, Secure Information Technology Center Austria
+ *
+ * Licensed under the EUPL, Version 1.1 or - as soon they will be approved by
+ * the European Commission - subsequent versions of the EUPL (the "Licence");
+ * You may not use this work except in compliance with the Licence.
+ * You may obtain a copy of the Licence at:
+ * http://joinup.ec.europa.eu/software/page/eupl
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the Licence is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the Licence for the specific language governing permissions and
+ * limitations under the Licence.
+ */
+package at.asit.pdfover.gui.composites;
+
+// Imports
+import java.awt.BorderLayout;
+import java.awt.Color;
+import java.awt.Cursor;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Image;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.NoninvertibleTransformException;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+
+import javax.swing.JPanel;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import at.asit.pdfover.gui.Constants;
+import at.asit.pdfover.gui.utils.Messages;
+
+import com.sun.pdfview.PDFFile;
+import com.sun.pdfview.PDFPage;
+
+/**
+ *
+ */
+public class SignaturePanel extends JPanel {
+ /**
+ * SLF4J Logger instance
+ **/
+ private static final Logger log = LoggerFactory
+ .getLogger(SignaturePanel.class);
+
+ /** Default serial version ID */
+ private static final long serialVersionUID = 1L;
+
+ /** The PDF file being displayed */
+ private PDFFile pdf = null;
+ /** The image of the rendered PDF page being displayed */
+ Image currentImage = null;
+ /** The current PDFPage that was rendered into currentImage */
+ private PDFPage currentPage = null;
+ /** The current transform from screen to page space */
+ AffineTransform currentXform = null;
+ /** The horizontal offset of the image from the left edge of the panel */
+ int offX = 0;
+ /** The vertical offset of the image from the top of the panel */
+ int offY = 0;
+ /** The size of the image */
+ private Dimension prevSize = null;
+ /** The position of the signature, in page space */
+ Point2D sigPagePos = null;
+ /** The position of the signature, in screen space */
+ Point2D sigScreenPos = null;
+ /** The signature placeholder image */
+ private Image sigPlaceholder = null;
+ /** Current scaled signature placeholder image */
+ BufferedImage sigPlaceholderScaled = null;
+ /** Transparency of the signature placeholder (0-255) */
+ private int sigPlaceholderTransparency = Constants.DEFAULT_SIGNATURE_PLACEHOLDER_TRANSPARENCY;
+ /** Previous Transparency of the signature placeholder */
+ private int prevSigPlaceholderTransparency = 0;
+ /** Width of the signature placeholder in page space */
+ private int sigPageWidth = 0;
+ /** Height of the signature placeholder in page space */
+ private int sigPageHeight = 0;
+ /** Width of the signature placeholder in screen space */
+ int sigScreenWidth = 0;
+ /** Height of the signature placeholder in screen space */
+ int sigScreenHeight = 0;
+ /** Previous Width of the signature placeholder in screen space */
+ int prevSigScreenWidth = 0;
+ /** Previous Height of the signature placeholder in screen space */
+ int prevSigScreenHeight = 0;
+ /** Color of the signature placeholder border */
+ private Color sigPlaceholderBorderColor = Color.BLUE;
+ /** Current page */
+ int page = 0;
+ /** Number of pages in the document */
+ int numPages = 0;
+ /** Cursor types */
+ static enum Cursors {DEFAULT, HAND, MOVE};
+ /** Default arrow cursor */
+ final Cursor defaultCursor = Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR);
+ /** Hand cursor */
+ final Cursor handCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);
+ /** Move cursor */
+ final Cursor moveCursor = Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR);
+ /** Current cursor */
+ Cursors currentCursor = Cursors.DEFAULT;
+
+ /**
+ * Create a new PagePanel.
+ * @param pdf the PDFFile to display
+ */
+ public SignaturePanel(PDFFile pdf) {
+ super(new BorderLayout());
+ setDocument(pdf);
+ setPreferredSize(new Dimension(Constants.DEFAULT_MAINWINDOW_WIDTH, Constants.DEFAULT_MAINWINDOW_HEIGHT - Constants.MAINBAR_HEIGHT));
+ setFocusable(true);
+ addMouseListener(this.mouseListener);
+ addMouseMotionListener(this.mouseListener);
+ }
+
+ /**
+ * Set a new document to be displayed
+ * @param pdf the PDFFile to be displayed
+ */
+ public void setDocument(PDFFile pdf) {
+ this.pdf = pdf;
+ this.sigPagePos = null;
+ this.numPages = pdf.getNumPages();
+ showPage(this.numPages);
+ }
+
+ /**
+ * Set the signature placeholder image
+ * @param placeholder signature placeholder
+ * @param width width of the placeholder in page space
+ * @param height height of the placeholder in page space
+ * @param transparency transparency of the signature placeholder (0 - 255)
+ */
+ public void setSignaturePlaceholder(Image placeholder, int width, int height, int transparency) {
+ this.sigPlaceholder = placeholder;
+ this.sigPageWidth = width;
+ this.sigPageHeight = height;
+ this.sigPlaceholderTransparency = transparency;
+ }
+
+ /**
+ * Set the color of the signature placeholder border
+ * @param color new signature placeholder border color
+ */
+ public void setSignaturePlaceholderBorderColor(Color color) {
+ this.sigPlaceholderBorderColor = color;
+ }
+
+ /**
+ * Change the currently displayed page
+ * @param page the number of the page to display
+ */
+ public void showPage(int page) {
+ this.page = page;
+ showPage(this.pdf.getPage(page));
+ }
+
+ /**
+ * Add and display a new page at the end of the document
+ *
+ * This page has the same dimensions as the old last page
+ */
+ public void addNewLastPage() {
+ showPage(this.numPages + 1);
+ }
+
+ /**
+ * Translate the signature placeholder position
+ * @param sigXOffset signature placeholder horizontal position offset
+ * @param sigYOffset signature placeholder vertical position offset
+ */
+ public void translateSignaturePosition(int sigXOffset, int sigYOffset) {
+ updateSigPos((int) this.sigScreenPos.getX() + sigXOffset, (int) this.sigScreenPos.getY() + sigYOffset);
+ }
+
+ /**
+ * Set the signature placeholder position
+ * Call showPage afterwards to update actual position
+ * @param x the horizontal signature position
+ * @param y the vertical signature position
+ */
+ public void setSignaturePosition(float x, float y)
+ {
+ this.sigPagePos = new Point2D.Double(x, y);
+ }
+
+ /**
+ * Get the current horizontal position of the signature
+ * @return signature x coordinate
+ */
+ public float getSignaturePositionX() {
+ if (this.sigPagePos == null)
+ return 0;
+ return Math.max((float) this.sigPagePos.getX(), 0);
+ }
+
+ /**
+ * Get the current vertical position of the signature
+ * @return signature y coordinate
+ */
+ public float getSignaturePositionY() {
+ if (this.sigPagePos == null)
+ return 0;
+ return Math.max((float) this.sigPagePos.getY(), 0);
+ }
+
+ /**
+ * Stop the generation of any previous page, and draw the new one.
+ *
+ * @param page the PDFPage to draw.
+ */
+ private synchronized void showPage(PDFPage page) {
+ // stop drawing the previous page
+ if (this.currentPage != null && this.prevSize != null) {
+ this.currentPage.stop(this.prevSize.width, this.prevSize.height, null);
+ }
+
+ boolean newPage = false;
+ // set up the new page
+ if (this.page > this.numPages)
+ {
+ // New last page - use old last page as template
+ this.currentPage = this.pdf.getPage(this.numPages);
+ newPage = true;
+ }
+ else
+ this.currentPage = page;
+
+
+ if (this.currentPage == null) {
+ // no page
+ this.currentImage = null;
+ this.currentXform = null;
+ repaint();
+ } else {
+ // start drawing
+ Dimension sz = getSize();
+ if (sz.width + sz.height == 0) {
+ // no image to draw.
+ return;
+ }
+
+ Dimension pageSize = this.currentPage.getUnstretchedSize(sz.width, sz.height,
+ null);
+
+ // get the new image
+ if (newPage)
+ {
+ this.currentImage = new BufferedImage(pageSize.width, pageSize.height, BufferedImage.TYPE_INT_RGB);
+ Graphics g = this.currentImage.getGraphics();
+ g.setColor(Color.WHITE);
+ g.fillRect(0, 0, pageSize.width, pageSize.height);
+ }
+ else
+ this.currentImage = this.currentPage.getImage(pageSize.width, pageSize.height,
+ null, this);
+
+ // calculate the transform from page to screen space
+ this.currentXform = new AffineTransform(1, 0, 0, -1, 0, pageSize.height);
+ Rectangle2D clip = this.currentPage.getBBox();
+ double scaleX = pageSize.width / clip.getWidth();
+ double scaleY = pageSize.height / clip.getHeight();
+ this.currentXform.scale(scaleX, scaleY);
+ this.currentXform.translate(-clip.getMinX(), -clip.getMinY());
+
+ if (this.sigPagePos != null)
+ this.sigScreenPos = this.currentXform.transform(this.sigPagePos, this.sigScreenPos);
+ this.sigScreenWidth = (int) Math.round(this.sigPageWidth * this.currentXform.getScaleX());
+ this.sigScreenHeight = (int) Math.round(this.sigPageHeight * this.currentXform.getScaleX());
+
+ // invert the transform (screen to page space)
+ try {
+ this.currentXform = this.currentXform.createInverse();
+ } catch (NoninvertibleTransformException nte) {
+ log.error("Error inverting page transform!", nte); //$NON-NLS-1$
+ }
+
+ if (this.sigPagePos == null)
+ {
+ this.sigScreenPos = new Point2D.Double(
+ clamp((int) (pageSize.getWidth() / 2), 0, this.currentImage.getWidth(null) - this.sigScreenWidth),
+ clamp((int) ((pageSize.getHeight() / 4) * 3), 0, this.currentImage.getHeight(null) - this.sigScreenHeight));
+ this.sigPagePos = this.currentXform.transform(this.sigScreenPos, this.sigPagePos);
+ }
+ else
+ updateSigPos((int) this.sigScreenPos.getX(), (int) this.sigScreenPos.getY());
+
+ this.prevSize = pageSize;
+
+ repaint();
+ }
+ }
+
+ /**
+ * Draw the image.
+ */
+ @Override
+ public void paint(Graphics g) {
+ Dimension sz = getSize();
+ g.setColor(getBackground());
+ g.fillRect(0, 0, getWidth(), getHeight());
+ if (this.currentImage == null) {
+ g.setColor(Color.black);
+ g.drawString(Messages.getString("error.SignaturePanel.NoPage"), getWidth() / 2 - 30, //$NON-NLS-1$
+ getHeight() / 2);
+ if (this.currentPage != null) {
+ showPage(this.currentPage);
+ }
+ } else {
+ // draw the image
+ int imwid = this.currentImage.getWidth(null);
+ int imhgt = this.currentImage.getHeight(null);
+
+ // draw it centered within the panel
+ this.offX = (sz.width - imwid) / 2;
+ this.offY = (sz.height - imhgt) / 2;
+
+ if ((imwid == sz.width && imhgt <= sz.height)
+ || (imhgt == sz.height && imwid <= sz.width)) {
+
+ // draw document
+ g.drawImage(this.currentImage, this.offX, this.offY, this);
+
+ // draw signature
+ int sigX = (int) (this.offX + this.sigScreenPos.getX());
+ int sigY = (int) (this.offY + this.sigScreenPos.getY());
+ if (this.sigPlaceholder == null) {
+ g.setColor(Color.red);
+ g.drawRect(sigX, sigY, 100, 40);
+ }
+ else {
+ if (
+ ((this.sigScreenWidth != this.prevSigScreenWidth) ||
+ (this.sigScreenHeight != this.prevSigScreenHeight) ||
+ (this.sigPlaceholderTransparency != this.prevSigPlaceholderTransparency)) &&
+ ((this.sigScreenWidth != 0) && (this.sigScreenHeight != 0)))
+ {
+ // redraw scaled transparent placeholder
+ this.prevSigScreenWidth = this.sigScreenWidth;
+ this.prevSigScreenHeight = this.sigScreenHeight;
+ this.prevSigPlaceholderTransparency = this.sigPlaceholderTransparency;
+ Image placeholder = this.sigPlaceholder.getScaledInstance(
+ this.sigScreenWidth, this.sigScreenHeight, Image.SCALE_SMOOTH);
+
+ //Make placeholder transparent
+ this.sigPlaceholderScaled = new BufferedImage(this.sigScreenWidth, this.sigScreenHeight, BufferedImage.TYPE_INT_ARGB);
+ Graphics g_phs = this.sigPlaceholderScaled.getGraphics();
+ g_phs.drawImage(placeholder, 0, 0, null);
+
+ // Draw grey "Signature" overlay
+ String overlay = Messages.getString("positioning.signature"); //$NON-NLS-1$
+ // Voodoo to get overlay font scale
+ float scale = (((float) this.sigScreenWidth) / this.sigPlaceholder.getWidth(null)) * 150;
+ g_phs.setFont(getFont().deriveFont(scale));
+ g_phs.setColor(this.sigPlaceholderBorderColor);
+ Rectangle2D overlay_size = g_phs.getFontMetrics().getStringBounds(overlay, g_phs);
+ int width = (int) overlay_size.getWidth();
+ int height = (int) overlay_size.getHeight();
+ int x = this.sigScreenWidth / 2 - width / 2;
+ int y = this.sigScreenHeight / 2 - height / 2 + g_phs.getFontMetrics().getAscent();
+ g_phs.drawString(overlay, x, y);
+
+ g_phs.dispose();
+ int[] phpixels = new int[this.sigScreenWidth * this.sigScreenHeight];
+ phpixels = this.sigPlaceholderScaled.getRGB(0, 0, this.sigScreenWidth, this.sigScreenHeight, phpixels, 0, this.sigScreenWidth);
+ for (int i = 0; i < phpixels.length; ++i) {
+ Color c = new Color(phpixels[i]);
+ c = new Color(c.getRed(), c.getGreen(), c.getBlue(), this.sigPlaceholderTransparency);
+ phpixels[i] = c.getRGB();
+ }
+ this.sigPlaceholderScaled.setRGB(0, 0, this.sigScreenWidth, this.sigScreenHeight, phpixels, 0, this.sigScreenWidth);
+ }
+ g.drawImage(this.sigPlaceholderScaled, sigX, sigY, null);
+ g.setColor(this.sigPlaceholderBorderColor);
+ g.drawRect(sigX, sigY, this.sigScreenWidth-1, this.sigScreenHeight-1);
+ }
+
+ } else {
+ // the image is bogus. try again, or give up.
+ if (this.currentPage != null) {
+ showPage(this.currentPage);
+ }
+ g.setColor(Color.black);
+ g.drawString(Messages.getString("error.SignaturePanel.NoRender"), getWidth() / 2 - 30, //$NON-NLS-1$
+ getHeight() / 2);
+ }
+ }
+ }
+
+ /**
+ * Handles notification of the fact that some part of the image changed.
+ * Repaints that portion.
+ *
+ * @return true if more updates are desired.
+ */
+ @Override
+ public boolean imageUpdate(Image img, int infoflags, int x, int y,
+ int width, int height) {
+ if ((infoflags & (SOMEBITS | ALLBITS)) != 0) {
+ repaint(x + this.offX, y + this.offY, width, height);
+ }
+ return ((infoflags & (ALLBITS | ERROR | ABORT)) == 0);
+ }
+
+ private MouseAdapter mouseListener = new MouseAdapter() {
+
+ private boolean doDrag = false;
+ private int dragXOffset = 0;
+ private int dragYOffset = 0;
+
+ private void updateSigPos(int sigx, int sigy) {
+ SignaturePanel.this.updateSigPos(
+ sigx - SignaturePanel.this.offX,
+ sigy - SignaturePanel.this.offY);
+ }
+
+ /** Handles a mouseMoved event */
+ @Override
+ public void mouseMoved(MouseEvent evt) {
+ try {
+ boolean onSig = isOnSignature(evt.getX(), evt.getY());
+ setCursor(onSig ? Cursors.HAND : Cursors.DEFAULT);
+ } catch (NullPointerException e) {
+ // do nothing
+ }
+ }
+
+ /** Handles a mousePressed event */
+ @Override
+ public void mousePressed(MouseEvent evt) {
+ if (evt.getButton() == MouseEvent.BUTTON1)
+ {
+ this.doDrag = true;
+ if (isOnSignature(evt.getX(), evt.getY())) {
+ this.dragXOffset = (int)
+ (SignaturePanel.this.sigScreenPos.getX() -
+ (evt.getX() - SignaturePanel.this.offX));
+ this.dragYOffset = (int)
+ (SignaturePanel.this.sigScreenPos.getY() -
+ (evt.getY() - SignaturePanel.this.offY));
+ }
+ else {
+ this.dragXOffset = 0;
+ this.dragYOffset = 0;
+ }
+ updateSigPos(evt.getX() + this.dragXOffset, evt.getY() + this.dragYOffset);
+ setCursor(Cursors.MOVE);
+ }
+ }
+
+ /** Handles a mouseReleased event */
+ @Override
+ public void mouseReleased(MouseEvent evt) {
+ this.doDrag = false;
+ boolean onSig = isOnSignature(evt.getX(), evt.getY());
+ setCursor(onSig ? Cursors.HAND : Cursors.DEFAULT);
+ }
+
+ /**
+ * Handles a mouseDragged event.
+ */
+ @Override
+ public void mouseDragged(MouseEvent evt) {
+ if (this.doDrag)
+ updateSigPos(evt.getX() + this.dragXOffset, evt.getY() + this.dragYOffset);
+ }
+ };
+
+ /**
+ * Sets the mouse cursor
+ * @param cursor cursor to set
+ */
+ void setCursor(Cursors cursor)
+ {
+ if (this.currentCursor == cursor)
+ return;
+ this.currentCursor = cursor;
+ Cursor cur = null;
+ switch (cursor) {
+ case DEFAULT:
+ cur = this.defaultCursor;
+ break;
+ case HAND:
+ cur = this.handCursor;
+ break;
+ case MOVE:
+ cur = this.moveCursor;
+ break;
+ }
+ this.getParent().setCursor(cur);
+ }
+
+ /**
+ * Check whether given point is on signature placeholder
+ * @param x x coordinate
+ * @param y y coordinate
+ * @return true if given point is on signature placeholder
+ */
+ boolean isOnSignature(int x, int y)
+ {
+ Rectangle2D sig = new Rectangle2D.Double(
+ this.sigScreenPos.getX() + this.offX,
+ this.sigScreenPos.getY() + this.offY,
+ this.sigScreenWidth,
+ this.sigScreenHeight);
+ Point2D pos = new Point2D.Double(x, y);
+ return (sig.contains(pos));
+ }
+
+ /**
+ * Update the signature placeholder position
+ * @param sigx X position on the document (screen coordinates)
+ * @param sigy Y position on the document (screen coordinates)
+ */
+ void updateSigPos(int sigx, int sigy) {
+ if (this.currentImage == null)
+ return;
+ sigx = clamp(sigx, 0, this.currentImage.getWidth(null) - this.sigScreenWidth);
+ sigy = clamp(sigy, 0, this.currentImage.getHeight(null) - this.sigScreenHeight);
+ this.sigScreenPos = new Point2D.Double(sigx, sigy);
+ this.sigPagePos = this.currentXform.transform(this.sigScreenPos, this.sigPagePos);
+ repaint();
+ }
+
+ /**
+ * Clamp x to be within [min-max]
+ * @param x int to clamp
+ * @param min minimum value
+ * @param max maximum value
+ * @return clamped x
+ */
+ static int clamp(int x, int min, int max)
+ {
+ if (x < min)
+ x = min;
+ else if (x > max)
+ x = max;
+ return x;
+ }
+}