package org.lttpp.eemory.ui; import java.awt.AWTException; import java.awt.BasicStroke; import java.awt.Color; import java.awt.Cursor; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.GraphicsDevice; import java.awt.GraphicsEnvironment; import java.awt.HeadlessException; import java.awt.Image; import java.awt.Rectangle; import java.awt.Toolkit; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseMotionAdapter; import java.awt.image.BufferedImage; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; import org.apache.commons.lang3.SystemUtils; import org.lttpp.eemory.Messages; import org.lttpp.eemory.ui.GeomRectangle.Position; import org.lttpp.eemory.util.ColorUtil; import org.lttpp.eemory.util.ImageUtil; import org.lttpp.eemory.util.LogUtil; import org.lttpp.eemory.util.Times; @SuppressWarnings("serial") public class CaptureView extends JFrame { private final BufferedImage fullScreen; private final GeomRectangle rectangle = new GeomRectangle(); private boolean isCapturing = false; private boolean isCaptured = false; private boolean isCaptureFullScreenViaClick = false; private final Times times = new Times(); private GeomPoint datumPoint; private final static Cursor DRAW_CURSOR = Cursor.getPredefinedCursor(Cursor.CROSSHAIR_CURSOR); private static final float PLUGIN_SCREENSHOT_HINT_SCALEFACTOR = 0.3F; private static final float PLUGIN_SCREENSHOT_MASK_FULLSCREEN_SCALEFACTOR = 0.7F; public CaptureView(final ScreenCaptureProcessor processor) throws HeadlessException, AWTException { fullScreen = ImageUtil.captureScreen(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize())); setSize(Toolkit.getDefaultToolkit().getScreenSize()); setUndecorated(true); setResizable(true); // Fix bug: fullscreen doesn't cover tool bars on Ubuntu. setAlwaysOnTop(true); setCursor(DRAW_CURSOR); resetView(); addKeyListener(new KeyAdapter() { @Override public void keyReleased(final KeyEvent e) { if (e.getKeyCode() == KeyEvent.VK_ESCAPE) { rectangle.clear(); escape(); } } }); addMouseListener(new MouseAdapter() { @Override public void mouseClicked(final MouseEvent e) { if (e.getButton() == MouseEvent.BUTTON1) { if (e.getClickCount() == 1) { if (!isCaptured) { isCaptureFullScreenViaClick = true; rectangle.getStartPoint().setLocation(0, 0); rectangle.getEndPoint().setLocation(new Double(Toolkit.getDefaultToolkit().getScreenSize().getWidth()).intValue(), new Double(Toolkit.getDefaultToolkit().getScreenSize().getHeight()).intValue()); maskFullScreen(PLUGIN_SCREENSHOT_MASK_FULLSCREEN_SCALEFACTOR); repaint(); isCaptured = true; } } else if (e.getClickCount() == 2) { escape(); // Perform action against captured image LogUtil.debug(Messages.bind(Messages.Plugin_Debug_CapturedScreenshot, getScreenshot())); if (processor != null) { processor.process(getScreenshot()); } else { LogUtil.debug(Messages.Plugin_Debug_NoScreenCaptureProcessor); } } } else if (e.getButton() == MouseEvent.BUTTON3) { if (e.getClickCount() == 1) { if (isCaptured) { resetView(); isCaptured = false; isCaptureFullScreenViaClick = false; setCursor(DRAW_CURSOR); } else { rectangle.clear(); escape(); } } } } @Override public void mousePressed(final MouseEvent e) { if (!isCaptured && e.getButton() == MouseEvent.BUTTON1) { rectangle.getStartPoint().setLocation(e.getX(), e.getY()); isCapturing = true; times.resetTimes(1); } else if (isResize()) { datumPoint = new GeomPoint(e.getX(), e.getY()); } } @Override public void mouseReleased(final MouseEvent e) { if (isCapturing && e.getButton() == MouseEvent.BUTTON1) { rectangle.getEndPoint().setLocation(e.getX(), e.getY()); isCapturing = false; isCaptured = rectangle.getWidth() > 0 && rectangle.getHeight() > 0; } } }); addMouseMotionListener(new MouseMotionAdapter() { @Override public void mouseDragged(final MouseEvent e) { if (isCapturing) { if (times.hasTimes()) { maskFullScreen(PLUGIN_SCREENSHOT_MASK_FULLSCREEN_SCALEFACTOR); } rectangle.getEndPoint().setLocation(e.getX(), e.getY()); if (rectangle.isRealRectangle()) { repaint(); } } else if (isResize()) { if (getCursor() == Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)) { rectangle.resize(Position.EAST, e.getX() - datumPoint.getX(), 0); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)) { rectangle.resize(Position.SOUTH, 0, e.getY() - datumPoint.getY()); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)) { rectangle.resize(Position.WEST, e.getX() - datumPoint.getX(), 0); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)) { rectangle.resize(Position.NORTH, 0, e.getY() - datumPoint.getY()); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)) { rectangle.resize(Position.NORTHEAST, e.getX() - datumPoint.getX(), e.getY() - datumPoint.getY()); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)) { rectangle.resize(Position.NORTHWEST, e.getX() - datumPoint.getX(), e.getY() - datumPoint.getY()); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)) { rectangle.resize(Position.SOUTHEAST, e.getX() - datumPoint.getX(), e.getY() - datumPoint.getY()); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR)) { rectangle.resize(Position.SOUTHWEST, e.getX() - datumPoint.getX(), e.getY() - datumPoint.getY()); } else if (getCursor() == Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)) { rectangle.move(e.getX() - datumPoint.getX(), e.getY() - datumPoint.getY()); } datumPoint.move(e.getX() - datumPoint.getX(), e.getY() - datumPoint.getY()); repaint(); } } @Override public void mouseMoved(final MouseEvent e) { if (!isCapturing && !isCaptured) { rectangle.getStartPoint().setLocation(e.getX(), e.getY()); } else if (isCaptured) { if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.EAST) { setCursor(Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.SOUTH) { setCursor(Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.WEST) { setCursor(Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.NORTH) { setCursor(Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.NORTHEAST) { setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.NORTHWEST) { setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.SOUTHEAST) { setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.SOUTHWEST) { setCursor(Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR)); } else if (rectangle.positionOf(new GeomPoint(e.getX(), e.getY())) == GeomRectangle.Position.INSIDE) { setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR)); } else { setCursor(DRAW_CURSOR); } } } }); } @Override public void paint(final Graphics graphics) { super.paint(graphics); if (isCapturing || isCaptureFullScreenViaClick || isResize()) { Image cropedScreenshot = fullScreen.getSubimage(rectangle.getTopLeftPoint().getX(), rectangle.getTopLeftPoint().getY(), rectangle.getWidth(), rectangle.getHeight()); Graphics2D g2 = (Graphics2D) graphics; g2.drawImage(cropedScreenshot, rectangle.getTopLeftPoint().getX(), rectangle.getTopLeftPoint().getY(), null); g2.setColor(ColorUtil.AWT_EVERNOTE_GREEN); g2.drawRect(rectangle.getTopLeftPoint().getX(), rectangle.getTopLeftPoint().getY(), rectangle.getWidth(), rectangle.getHeight()); g2.drawRect(rectangle.getTopLeftRectangle().getTopLeftPoint().getX(), rectangle.getTopLeftRectangle().getTopLeftPoint().getY(), rectangle.getTopLeftRectangle().getWidth(), rectangle.getTopLeftRectangle().getHeight()); g2.fillRect(rectangle.getTopLeftRectangle().getTopLeftPoint().getX(), rectangle.getTopLeftRectangle().getTopLeftPoint().getY(), rectangle.getTopLeftRectangle().getWidth(), rectangle.getTopLeftRectangle().getHeight()); g2.drawRect(rectangle.getTopRightRectangle().getTopLeftPoint().getX(), rectangle.getTopRightRectangle().getTopLeftPoint().getY(), rectangle.getTopRightRectangle().getWidth(), rectangle.getTopRightRectangle().getHeight()); g2.fillRect(rectangle.getTopRightRectangle().getTopLeftPoint().getX(), rectangle.getTopRightRectangle().getTopLeftPoint().getY(), rectangle.getTopRightRectangle().getWidth(), rectangle.getTopRightRectangle().getHeight()); g2.drawRect(rectangle.getBottomLeftRectangle().getTopLeftPoint().getX(), rectangle.getBottomLeftRectangle().getTopLeftPoint().getY(), rectangle.getBottomLeftRectangle().getWidth(), rectangle.getBottomLeftRectangle().getHeight()); g2.fillRect(rectangle.getBottomLeftRectangle().getTopLeftPoint().getX(), rectangle.getBottomLeftRectangle().getTopLeftPoint().getY(), rectangle.getBottomLeftRectangle().getWidth(), rectangle.getBottomLeftRectangle().getHeight()); g2.drawRect(rectangle.getBottomRightRectangle().getTopLeftPoint().getX(), rectangle.getBottomRightRectangle().getTopLeftPoint().getY(), rectangle.getBottomRightRectangle().getWidth(), rectangle.getBottomRightRectangle().getHeight()); g2.fillRect(rectangle.getBottomRightRectangle().getTopLeftPoint().getX(), rectangle.getBottomRightRectangle().getTopLeftPoint().getY(), rectangle.getBottomRightRectangle().getWidth(), rectangle.getBottomRightRectangle().getHeight()); g2.drawRect(rectangle.getTopRectangle().getTopLeftPoint().getX(), rectangle.getTopRectangle().getTopLeftPoint().getY(), rectangle.getTopRectangle().getWidth(), rectangle.getTopRectangle().getHeight()); g2.fillRect(rectangle.getTopRectangle().getTopLeftPoint().getX(), rectangle.getTopRectangle().getTopLeftPoint().getY(), rectangle.getTopRectangle().getWidth(), rectangle.getTopLeftRectangle().getHeight()); g2.drawRect(rectangle.getBottomRectangle().getTopLeftPoint().getX(), rectangle.getBottomRectangle().getTopLeftPoint().getY(), rectangle.getBottomRectangle().getWidth(), rectangle.getBottomRectangle().getHeight()); g2.fillRect(rectangle.getBottomRectangle().getTopLeftPoint().getX(), rectangle.getBottomRectangle().getTopLeftPoint().getY(), rectangle.getBottomRectangle().getWidth(), rectangle.getBottomRectangle().getHeight()); g2.drawRect(rectangle.getLeftRectangle().getTopLeftPoint().getX(), rectangle.getLeftRectangle().getTopLeftPoint().getY(), rectangle.getLeftRectangle().getWidth(), rectangle.getLeftRectangle().getHeight()); g2.fillRect(rectangle.getLeftRectangle().getTopLeftPoint().getX(), rectangle.getLeftRectangle().getTopLeftPoint().getY(), rectangle.getLeftRectangle().getWidth(), rectangle.getLeftRectangle().getHeight()); g2.drawRect(rectangle.getRightRectangle().getTopLeftPoint().getX(), rectangle.getRightRectangle().getTopLeftPoint().getY(), rectangle.getRightRectangle().getWidth(), rectangle.getRightRectangle().getHeight()); g2.fillRect(rectangle.getRightRectangle().getTopLeftPoint().getX(), rectangle.getRightRectangle().getTopLeftPoint().getY(), rectangle.getRightRectangle().getWidth(), rectangle.getRightRectangle().getHeight()); // draw hint int stringWidth = graphics.getFontMetrics(getFont()).stringWidth(Messages.Plugin_Runtime_ClipScreenshotToEvernote_Hint); int stringHeight = graphics.getFontMetrics(getFont()).getHeight() + 1; int charWidth = stringWidth / Messages.Plugin_Runtime_ClipScreenshotToEvernote_Hint.length(); int start_x = charWidth * 1; int start_y = -(2 + charWidth); stringWidth += charWidth * 8; if (stringWidth > Toolkit.getDefaultToolkit().getScreenSize().getWidth()) { stringWidth = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth(); } GeomPoint p = rectangle.getTopLeftPoint(); if (p.getY() - (stringHeight + 2) < 0) { p = new GeomPoint(p.getX(), p.getY() + stringHeight + 2); } if (p.getX() + stringWidth > Toolkit.getDefaultToolkit().getScreenSize().getWidth()) { p = new GeomPoint((int) Toolkit.getDefaultToolkit().getScreenSize().getWidth() - stringWidth, p.getY()); } g2.drawImage(ImageUtil.mask(fullScreen.getSubimage(p.getX(), p.getY() - (stringHeight + 2), stringWidth, stringHeight), PLUGIN_SCREENSHOT_HINT_SCALEFACTOR), p.getX(), p.getY() - (stringHeight + 2), null); g2.setColor(Color.WHITE); g2.setFont(getFont().deriveFont(Font.BOLD)); g2.drawString(Messages.Plugin_Runtime_ClipScreenshotToEvernote_Hint, p.getX() + start_x, p.getY() + start_y); } } private boolean isResize() { return getCursor() == Cursor.getPredefinedCursor(Cursor.E_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.S_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.W_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.N_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.SW_RESIZE_CURSOR) || getCursor() == Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR); } private void maskFullScreen(final float scaleFactor) { setContentPane(new JPanel() { @Override public void paintComponent(final Graphics graphics) { super.paintComponent(graphics); ((Graphics2D) graphics).drawImage(ImageUtil.mask(fullScreen, scaleFactor), 0, 0, null); } }); validate(); } private void resetView() { setContentPane(new JPanel() { @Override public void paintComponent(final Graphics graphics) { super.paintComponent(graphics); Graphics2D g2 = (Graphics2D) graphics; g2.drawImage(fullScreen, 0, 0, null); g2.setColor(ColorUtil.AWT_EVERNOTE_GREEN); g2.setStroke(new BasicStroke(6)); g2.drawRect(0, 0, new Double(Toolkit.getDefaultToolkit().getScreenSize().getWidth()).intValue(), new Double(Toolkit.getDefaultToolkit().getScreenSize().getHeight()).intValue()); } }); validate(); } private void escape() { setVisible(false); dispose(); } public BufferedImage getScreenshot() { if (!rectangle.isRealRectangle()) { return null; } return fullScreen.getSubimage(rectangle.getTopLeftPoint().getX(), rectangle.getTopLeftPoint().getY(), rectangle.getWidth(), rectangle.getHeight()); } // Starter method to launch Capture View // public static void showView(final ScreenCaptureProcessor processor) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { try { CaptureView view = new CaptureView(processor); if (SystemUtils.IS_OS_WINDOWS) { view.setVisible(true); } else { GraphicsDevice device = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice(); LogUtil.debug(Messages.bind(Messages.Plugin_Debug_IsFullScreenSupported, device.isFullScreenSupported())); if (device.isFullScreenSupported()) { device.setFullScreenWindow(view); } else { view.setVisible(true); } } } catch (Exception e) { LogUtil.logError(e); } } }); } }