From 424eedc3f57676211a79f53cc92288e9c3f65b25 Mon Sep 17 00:00:00 2001 From: NathanSweet Date: Wed, 6 Apr 2016 11:34:40 +0200 Subject: [PATCH] Much fancier region screenshot UI. --- .../esotericsoftware/clippy/Screenshot.java | 166 ++++++++++++++++-- 1 file changed, 149 insertions(+), 17 deletions(-) diff --git a/src/com/esotericsoftware/clippy/Screenshot.java b/src/com/esotericsoftware/clippy/Screenshot.java index 00a0f98..c473414 100644 --- a/src/com/esotericsoftware/clippy/Screenshot.java +++ b/src/com/esotericsoftware/clippy/Screenshot.java @@ -4,6 +4,7 @@ import static com.esotericsoftware.clippy.Win.User32.*; import static com.esotericsoftware.minlog.Log.*; +import java.awt.BasicStroke; import java.awt.Color; import java.awt.Dimension; import java.awt.Frame; @@ -14,13 +15,19 @@ import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; +import java.awt.Stroke; import java.awt.Toolkit; import java.awt.Transparency; +import java.awt.event.InputEvent; 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.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.geom.Ellipse2D; +import java.awt.geom.Ellipse2D.Float; import java.awt.image.BufferedImage; import java.awt.image.VolatileImage; import java.io.File; @@ -40,8 +47,12 @@ import retrofit.client.Response; public class Screenshot { + static final int mag = 8, magOffsetX = 8, magOffsetY = 8, magW = 280, magH = 280; + static final int crosshair = 16; + final Clippy clippy = Clippy.instance; - private Robot robot; + Robot robot; + final Stroke dashed = new BasicStroke(1, BasicStroke.CAP_BUTT, BasicStroke.JOIN_BEVEL, 0, new float[] {4}, 0); public Screenshot () { try { @@ -115,29 +126,78 @@ public void region () { image.getGraphics().drawImage(robotImage, 0, 0, null); JFrame frame = new JFrame() { - int x, y, x1, y1; - boolean drag; + int lastX, lastY, x, y, x1, y1; + int magX = magOffsetX, magY = magOffsetY; + boolean drag, lock, lockX, robotEvent; { addMouseMotionListener(new MouseMotionAdapter() { public void mouseDragged (MouseEvent e) { - x = e.getX(); - y = e.getY(); - if (!drag) { - drag = true; - x1 = x; - y1 = y; - } - repaint(); + mouseMoved(e); } public void mouseMoved (MouseEvent e) { - x = e.getX(); - y = e.getY(); + int ex = e.getX(), ey = e.getY(); + if (robotEvent) { + robotEvent = false; + lastX = ex; + lastY = ey; + return; + } + + int diffX = ex - lastX, diffY = ey - lastY; + + // Shift to move slow. + if ((e.getModifiers() & InputEvent.SHIFT_MASK) != 0) { + diffX /= mag; + diffY /= mag; + } + if (diffX != 0) lastX = ex; + if (diffY != 0) lastY = ey; + + // Ctrl to lock axis. + if ((e.getModifiers() & InputEvent.CTRL_MASK) != 0) { + if (!lock) { + lock = true; + lockX = diffY != 0; + } + if (lockX) + diffX = 0; + else + diffY = 0; + } else { + lock = false; + } + + x += diffX; + y += diffY; + if (x < 0) + x = 0; + else if (x > width) // + x = width; + if (y < 0) + y = 0; + else if (y > height) // + y = height; + repaint(); + + // Prevent mouse from getting stuck against screen edge. + if (ex < 10 || width - ex < 10 || ey < 10 || height - ey < 10) { + robot.mouseMove(width / 2, height / 2); + robotEvent = true; + } } }); addMouseListener(new MouseAdapter() { + public void mousePressed (MouseEvent e) { + lastX = e.getX(); + lastY = e.getY(); + drag = true; + x1 = x; + y1 = y; + } + public void mouseReleased (MouseEvent e) { dispose(); if (x == x1 || y == y1) return; @@ -160,21 +220,93 @@ public void mouseReleased (MouseEvent e) { }); addKeyListener(new KeyAdapter() { public void keyPressed (KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_SHIFT) return; + if (e.getKeyCode() == KeyEvent.VK_CONTROL) return; dispose(); } + + public void keyReleased (KeyEvent e) { + if (e.getKeyCode() == KeyEvent.VK_CONTROL) lock = false; + }; + }); + addWindowListener(new WindowAdapter() { + public void windowClosed (WindowEvent e) { + robot.mouseMove(x, y); + } }); } - public void paint (Graphics g) { + public void paint (Graphics graphics) { + Graphics2D g = (Graphics2D)graphics; + + if (x + magX < 0) + magX = magOffsetX; + else if (x + magX + magW > width) // + magX = -(magW + magOffsetX); + if (y + magY < 0) + magY = magOffsetY; + else if (y + magY + magH > height) // + magY = -(magH + magOffsetY); + + // Draw whole screen image. g.drawImage(image, 0, 0, width, height, null); if (drag) { g.setColor(new Color(0, 0, 0, 0.3f)); g.fillRect(0, 0, width, height); g.drawImage(image, x1, y1, x, y, x1, y1, x, y, null); } - g.setColor(Color.green); - g.drawLine(0, y, width, y); - g.drawLine(x, 0, x, height); + + // Magnified image. + Float circle = new Ellipse2D.Float(x + magX, y + magY, magW, magH); + g.setClip(circle); + g.drawImage(image, // + x + magX + mag, y + magY + mag, x + magX + magW, y + magY + magH, // + x - magW / (mag * 2), y - magH / (mag * 2), x + magW / (mag * 2), y + magW / (mag * 2), null); + g.setClip(null); + + // Magnified crosshair. + int space = mag * 2; + int cx = x + magX + magW / 2 - mag / 2; + int cy = y + magY + space; + int ch = magH / 2 - mag * 3 / 2 - space; + g.setColor(Color.black); + g.fillRect(cx, cy, mag, ch); + g.fillRect(cx, cy + ch + mag * 3, mag, ch); + g.setColor(Color.white); + cx--; + cy--; + g.drawRect(cx, cy, mag + 1, ch + 1); + g.drawRect(cx, cy + ch + mag * 3, mag + 1, ch + 1); + cx = x + magX + space; + cy = y + magY + magH / 2 - mag / 2; + int cw = magW / 2 - mag * 3 / 2 - space; + g.setColor(Color.black); + g.fillRect(cx, cy, cw, mag); + g.fillRect(cx + cw + mag * 3, cy, cw, mag); + g.setColor(Color.white); + cx--; + cy--; + g.drawRect(cx, cy, cw + 1, mag + 1); + g.drawRect(cx + cw + mag * 3, cy, cw + 1, mag + 1); + + // Dotted guide lines. + g.setColor(Color.black); + g.drawLine(x - crosshair - 1, y, 0, y); + g.drawLine(x + crosshair + 1, y, width, y); + g.drawLine(x, y - crosshair - 1, x, 0); + g.drawLine(x, y + crosshair + 1, x, height); + g.setColor(Color.white); + Stroke solid = g.getStroke(); + g.setStroke(dashed); + g.drawLine(x - crosshair, y, 0, y); + g.drawLine(x + crosshair, y, width, y); + g.drawLine(x, y - crosshair, x, 0); + g.drawLine(x, y + crosshair, x, height); + g.setXORMode(Color.white); + g.setColor(Color.black); + g.fillRect(x - 1, y - crosshair, 3, crosshair * 2 + 1); + g.fillRect(x - crosshair, y - 1, crosshair - 1, 3); + g.fillRect(x + 2, y - 1, crosshair - 1, 3); } }; frame.setType(Frame.Type.UTILITY);