commit e2e5c283d348396efb2e8d0f92d531025d207ba8 Author: Victor Date: Thu Nov 15 17:09:39 2018 +0200 Initial diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..b0771dc --- /dev/null +++ b/build.xml @@ -0,0 +1,73 @@ + + + + + + + + + + + Builds, tests, and runs the project Colorillo Painter. + + + diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml new file mode 100644 index 0000000..20e9809 --- /dev/null +++ b/nbproject/build-impl.xml @@ -0,0 +1,1419 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set src.dir + Must set test.src.dir + Must set build.dir + Must set dist.dir + Must set build.classes.dir + Must set dist.javadoc.dir + Must set build.test.classes.dir + Must set build.test.results.dir + Must set build.classes.excludes + Must set dist.jar + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + No tests executed. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must set JVM to use for profiling in profiler.info.jvm + Must set profiler agent JVM arguments in profiler.info.jvmargs.agent + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + To run this application from the command line without Ant, try: + + java -jar "${dist.jar.resolved}" + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + Must select one file in the IDE or set run.class + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set debug.class + + + + + Must select one file in the IDE or set debug.class + + + + + Must set fix.includes + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + Must select one file in the IDE or set profile.class + This target only works when run from inside the NetBeans IDE. + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + This target only works when run from inside the NetBeans IDE. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select one file in the IDE or set run.class + + + + + + Must select some files in the IDE or set test.includes + + + + + Must select one file in the IDE or set run.class + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Must select some files in the IDE or set javac.includes + + + + + + + + + + + + + + + + + + + + Some tests failed; see details above. + + + + + + + + + Must select some files in the IDE or set test.includes + + + + Some tests failed; see details above. + + + + Must select some files in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + Some tests failed; see details above. + + + + + Must select one file in the IDE or set test.class + + + + Must select one file in the IDE or set test.class + Must select some method in the IDE or set test.method + + + + + + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + Must select one file in the IDE or set applet.url + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties new file mode 100644 index 0000000..d864bc8 --- /dev/null +++ b/nbproject/genfiles.properties @@ -0,0 +1,8 @@ +build.xml.data.CRC32=a70e3604 +build.xml.script.CRC32=342e1232 +build.xml.stylesheet.CRC32=8064a381@1.79.0.48 +# This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. +# Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. +nbproject/build-impl.xml.data.CRC32=a70e3604 +nbproject/build-impl.xml.script.CRC32=c795d3c0 +nbproject/build-impl.xml.stylesheet.CRC32=05530350@1.79.0.48 diff --git a/nbproject/private/private.properties b/nbproject/private/private.properties new file mode 100644 index 0000000..844cd7e --- /dev/null +++ b/nbproject/private/private.properties @@ -0,0 +1,2 @@ +compile.on.save=true +user.properties.file=C:\\Users\\aNNiMON\\AppData\\Roaming\\NetBeans\\dev\\build.properties diff --git a/nbproject/private/private.xml b/nbproject/private/private.xml new file mode 100644 index 0000000..df6dc78 --- /dev/null +++ b/nbproject/private/private.xml @@ -0,0 +1,12 @@ + + + + + + file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_SAMPLES/Colorillo%20Painter/src/com/annimon/colorillopainter/DebugPanel.java + file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_SAMPLES/Colorillo%20Painter/src/com/annimon/colorillopainter/Main.java + file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_SAMPLES/Colorillo%20Painter/src/com/annimon/colorillopainter/CanvasBoard.java + file:/C:/Users/aNNiMON/Documents/NetBeansProjects/_SAMPLES/Colorillo%20Painter/src/com/annimon/colorillopainter/ImagePainter.java + + + diff --git a/nbproject/project.properties b/nbproject/project.properties new file mode 100644 index 0000000..ab5dad6 --- /dev/null +++ b/nbproject/project.properties @@ -0,0 +1,74 @@ +annotation.processing.enabled=true +annotation.processing.enabled.in.editor=false +annotation.processing.processor.options= +annotation.processing.processors.list= +annotation.processing.run.all.processors=true +annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output +build.classes.dir=${build.dir}/classes +build.classes.excludes=**/*.java,**/*.form +# This directory is removed when the project is cleaned: +build.dir=build +build.generated.dir=${build.dir}/generated +build.generated.sources.dir=${build.dir}/generated-sources +# Only compile against the classpath explicitly listed here: +build.sysclasspath=ignore +build.test.classes.dir=${build.dir}/test/classes +build.test.results.dir=${build.dir}/test/results +# Uncomment to specify the preferred debugger connection transport: +#debug.transport=dt_socket +debug.classpath=\ + ${run.classpath} +debug.test.classpath=\ + ${run.test.classpath} +# Files in build.classes.dir which should be excluded from distribution jar +dist.archive.excludes= +# This directory is removed when the project is cleaned: +dist.dir=dist +dist.jar=${dist.dir}/Colorillo_Painter.jar +dist.javadoc.dir=${dist.dir}/javadoc +excludes= +includes=** +jar.compress=false +javac.classpath= +# Space-separated list of extra javac options +javac.compilerargs= +javac.deprecation=false +javac.external.vm=true +javac.processorpath=\ + ${javac.classpath} +javac.source=1.8 +javac.target=1.8 +javac.test.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +javac.test.processorpath=\ + ${javac.test.classpath} +javadoc.additionalparam= +javadoc.author=false +javadoc.encoding=${source.encoding} +javadoc.noindex=false +javadoc.nonavbar=false +javadoc.notree=false +javadoc.private=false +javadoc.splitindex=true +javadoc.use=true +javadoc.version=false +javadoc.windowtitle= +main.class=com.annimon.colorillopainter.Main +manifest.file=manifest.mf +meta.inf.dir=${src.dir}/META-INF +mkdist.disabled=false +platform.active=default_platform +run.classpath=\ + ${javac.classpath}:\ + ${build.classes.dir} +# Space-separated list of JVM arguments used when running the project. +# You may also define separate properties like run-sys-prop.name=value instead of -Dname=value. +# To set system properties for unit tests define test-sys-prop.name=value: +run.jvmargs= +run.test.classpath=\ + ${javac.test.classpath}:\ + ${build.test.classes.dir} +source.encoding=UTF-8 +src.dir=src +test.src.dir=test diff --git a/nbproject/project.xml b/nbproject/project.xml new file mode 100644 index 0000000..5fa6419 --- /dev/null +++ b/nbproject/project.xml @@ -0,0 +1,15 @@ + + + org.netbeans.modules.java.j2seproject + + + Colorillo Painter + + + + + + + + + diff --git a/src/com/annimon/colorillopainter/CanvasBoard.java b/src/com/annimon/colorillopainter/CanvasBoard.java new file mode 100644 index 0000000..52e1b97 --- /dev/null +++ b/src/com/annimon/colorillopainter/CanvasBoard.java @@ -0,0 +1,80 @@ +package com.annimon.colorillopainter; + +import java.awt.event.MouseEvent; + +/** + * + * @author aNNiMON + */ +public final class CanvasBoard { + + // (485, 170) -- (1283, 668) + private static final int BOARD_X1 = 485, BOARD_Y1 = 170; + private static final int BOARD_X2 = 1283, BOARD_Y2 = 668; + +// ColorBox (375, 430) -- (430, 430) + private static final int COLORBOX_X1 = 375, COLORBOX_Y1 = 430; + private static final int COLORBOX_X2 = 430, COLORBOX_Y2 = 430; + + private static final int DELAY = 105; + private static final int BRUSH_SIZE = 1; + private static final int OFFSET_X = 0; + + private int lastColor; + + public CanvasBoard() { + lastColor = -1; + } + + public void drawPixel(int color, int x, int y) { + if (color != lastColor) changeColor(color); + + final int nx = convertX(x), ny = convertY(y); + RobotUtils.getInstance().mouseMove(nx, ny); + RobotUtils.getInstance().mousePressLong(MouseEvent.BUTTON1_MASK); + RobotUtils.getInstance().delay(DELAY); + RobotUtils.getInstance().mouseMove(nx, ny + 1); + RobotUtils.getInstance().delay(DELAY); + RobotUtils.getInstance().mousePressLongReset(); + } + + public void changeColor(int color) { + final int red = (color >> 16) & 0xFF; + final int green = (color >> 8) & 0xFF; + final int blue = color & 0xFF; + + final StringBuilder sb = new StringBuilder(7); + sb.append('#'); + if (red <= 0x0F) sb.append(0); + sb.append(Integer.toHexString(red)); + if (green <= 0x0F) sb.append(0); + sb.append(Integer.toHexString(green)); + if (blue <= 0x0F) sb.append(0); + sb.append(Integer.toHexString(blue)); + + // Clear colorbox + RobotUtils.getInstance().mouseMove(COLORBOX_X1, COLORBOX_Y1); + RobotUtils.getInstance().mousePressLong(MouseEvent.BUTTON1_MASK); + RobotUtils.getInstance().delay(DELAY); + RobotUtils.getInstance().mouseMove(COLORBOX_X2, COLORBOX_Y2); + RobotUtils.getInstance().delay(DELAY); + RobotUtils.getInstance().mousePressLongReset(); + + // Type color + RobotUtils.getInstance().writeMessage(sb.toString()); + + lastColor = color; + } + + private int convertX(int x) { + final int result = BOARD_X1 + OFFSET_X + (x * BRUSH_SIZE); + if (result > BOARD_X2) return BOARD_X2; + return result; + } + + private int convertY(int y) { + final int result = BOARD_Y1 + (y * BRUSH_SIZE); + if (result > BOARD_Y2) return BOARD_Y2; + return result; + } +} diff --git a/src/com/annimon/colorillopainter/DebugPanel.form b/src/com/annimon/colorillopainter/DebugPanel.form new file mode 100644 index 0000000..2fcc951 --- /dev/null +++ b/src/com/annimon/colorillopainter/DebugPanel.form @@ -0,0 +1,84 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/src/com/annimon/colorillopainter/DebugPanel.java b/src/com/annimon/colorillopainter/DebugPanel.java new file mode 100644 index 0000000..1c58528 --- /dev/null +++ b/src/com/annimon/colorillopainter/DebugPanel.java @@ -0,0 +1,105 @@ +/* + */ +package com.annimon.colorillopainter; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.GroupLayout; +import javax.swing.JButton; +import javax.swing.JLabel; +import javax.swing.JSlider; +import javax.swing.LayoutStyle; + +/** + * + * @author aNNiMON + */ +public class DebugPanel extends javax.swing.JPanel { + + /** + * Creates new form DebugPanel + */ + public DebugPanel() { + initComponents(); + xSlider.addChangeListener(e -> updateInfo()); + ySlider.addChangeListener(e -> updateInfo()); + } + + /** + * This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + @SuppressWarnings("unchecked") + private void initComponents() {//GEN-BEGIN:initComponents + + xSlider = new JSlider(); + ySlider = new JSlider(); + checkButton = new JButton(); + infoLabel = new JLabel(); + + xSlider.setMaximum(2800); + + ySlider.setMaximum(1678); + ySlider.setOrientation(JSlider.VERTICAL); + + checkButton.setText("Check"); + checkButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + checkButtonActionPerformed(evt); + } + }); + + infoLabel.setText("info"); + + GroupLayout layout = new GroupLayout(this); + this.setLayout(layout); + layout.setHorizontalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(ySlider, GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.TRAILING) + .addGroup(layout.createSequentialGroup() + .addGap(11, 11, 11) + .addComponent(xSlider, GroupLayout.DEFAULT_SIZE, 344, Short.MAX_VALUE)) + .addGroup(layout.createSequentialGroup() + .addGap(89, 89, 89) + .addComponent(infoLabel) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(checkButton))) + .addContainerGap()) + ); + layout.setVerticalGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addComponent(xSlider, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE) + .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE) + .addComponent(checkButton) + .addComponent(infoLabel))) + .addComponent(ySlider, GroupLayout.DEFAULT_SIZE, 278, Short.MAX_VALUE)) + .addContainerGap()) + ); + }//GEN-END:initComponents + + private void checkButtonActionPerformed(ActionEvent evt) {//GEN-FIRST:event_checkButtonActionPerformed + final int x = xSlider.getValue(); + final int y = ySlider.getValue(); + RobotUtils.getInstance().mouseMove(x, y); + }//GEN-LAST:event_checkButtonActionPerformed + + private void updateInfo() { + infoLabel.setText(String.format("x: %d, y: %d", xSlider.getValue(), ySlider.getValue())); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private JButton checkButton; + private JLabel infoLabel; + private JSlider xSlider; + private JSlider ySlider; + // End of variables declaration//GEN-END:variables + +} diff --git a/src/com/annimon/colorillopainter/ImagePainter.java b/src/com/annimon/colorillopainter/ImagePainter.java new file mode 100644 index 0000000..ccebe18 --- /dev/null +++ b/src/com/annimon/colorillopainter/ImagePainter.java @@ -0,0 +1,80 @@ +package com.annimon.colorillopainter; + +import java.awt.Point; +import java.awt.image.BufferedImage; +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import javax.imageio.ImageIO; + +/** + * + * @author aNNiMON + */ +public final class ImagePainter { + + + public static ImagePainter fromFile(String path) { + try { + return new ImagePainter( ImageIO.read(new File(path)) ); + } catch (IOException ex) { + throw new RuntimeException("Successfully failed to open image"); + } + } + + private final int width, height; + private final int[] pixels; + private final HashMap> colors; + + private CanvasBoard canvas; + + public ImagePainter(BufferedImage image) { + width = image.getWidth(); + height = image.getHeight(); + pixels = new int[width * height]; + image.getRGB(0, 0, width, height, pixels, 0, width); + + colors = new HashMap<>(); + scanPixels(); + } + + private void scanPixels() { + int index = 0; + for (int y = 0; y < height; y++) { + for (int x = 0; x < width; x++) { + final int color = pixels[index++]; + final List points; + if (colors.containsKey(color)) { + points = colors.get(color); + } else { + points = new ArrayList<>(); + colors.put(color, points); + } + points.add(new Point(x, y)); + } + } + } + + public void setCanvas(CanvasBoard canvas) { + this.canvas = canvas; + } + + public void draw() { + colors.entrySet() + .stream() + .filter(entry -> { + // Filter white and transparent color + final int color = entry.getKey(); + if ( (color & 0xFFFFFF) == 0xFFFFFF) return false; + if ( (color & 0xFFFFFF) == 0x000000) return false; + final int alpha = (color >> 24) & 0xFF; + return alpha == 0xFF; + }) + .forEach(entry -> { + final int color = entry.getKey(); + entry.getValue().forEach(point -> canvas.drawPixel(color, point.x, point.y)); + }); + } +} diff --git a/src/com/annimon/colorillopainter/Main.java b/src/com/annimon/colorillopainter/Main.java new file mode 100644 index 0000000..41c203c --- /dev/null +++ b/src/com/annimon/colorillopainter/Main.java @@ -0,0 +1,78 @@ +package com.annimon.colorillopainter; + +import java.awt.Dimension; +import java.awt.event.MouseEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import javax.swing.JButton; +import javax.swing.JFrame; + +/** + * @author aNNiMON + */ +public final class Main extends JFrame { + + public static void main(String[] args) { + new Main().setVisible(true); + } + + private final CanvasBoard canvas; + private final ImagePainter painter; + + public Main() { + super("Colorillo Painter"); + + setLocation(50, 130); + setPreferredSize(new Dimension(300, 200)); + setAlwaysOnTop(true); + setDefaultCloseOperation(EXIT_ON_CLOSE); + addWindowFocusListener(new WindowAdapter() { + + private int counter = 0; + + @Override + public void windowGainedFocus(WindowEvent e) { + super.windowGainedFocus(e); + counter++; + System.out.println("focus " + counter); + if (counter == 6) { + RobotUtils.getInstance().mousePressLongReset(); + System.exit(0); + } + } + }); + + JButton start = new JButton("Start"); + start.addActionListener(e -> new Thread(this::onStart).start()); + + add(start); +// add(new DebugPanel()); + pack(); + + canvas = new CanvasBoard(); + painter = ImagePainter.fromFile("E:/ext_road_day.png"); + painter.setCanvas(canvas); + } + + private void onStart() { + colorillo(); + } + + private void colorillo() { + // Canvas (485, 170) -- (1283, 668) + // ColorBox (375, 430) -- (430, 430) +// for(int x = 0; x < 50; x++) +// canvas.drawPixel(0xFF0000, x, 0); +// for(int x = 0; x < 50; x++) +// canvas.drawPixel(0x00FF00, x, 10); + painter.draw(); + } + + private void postToTwitchChat() { + RobotUtils.getInstance().mouseMove(2668, 800); + RobotUtils.getInstance().mousePress(MouseEvent.BUTTON1_MASK); + RobotUtils.getInstance().writeMessage("IT WORKS"); + RobotUtils.getInstance().mouseMove(2768, 860); + RobotUtils.getInstance().mousePress(MouseEvent.BUTTON1_MASK); + } +} diff --git a/src/com/annimon/colorillopainter/RobotUtils.java b/src/com/annimon/colorillopainter/RobotUtils.java new file mode 100644 index 0000000..7bce1e1 --- /dev/null +++ b/src/com/annimon/colorillopainter/RobotUtils.java @@ -0,0 +1,122 @@ +package com.annimon.colorillopainter; + +import java.awt.*; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + +/** + * Work with Robot class. + * @author aNNiMON + */ +public class RobotUtils { + + private static RobotUtils instance; + + public static synchronized RobotUtils getInstance() { + if (instance == null) { + instance = new RobotUtils(); + } + return instance; + } + + + private static final int CLICK_DELAY = 100; + private static final int PRESS_DELAY = 112; + private Robot robot; + + private int code1, code2, code3, button1; + + public RobotUtils() { + try { + robot = new Robot(); + } catch (AWTException e) { + e.printStackTrace(); + } + } + + public void delay(int time) { + robot.delay(time); + } + + public void keyPress(int code) { + robot.keyPress(code); + robot.delay(PRESS_DELAY); + robot.keyRelease(code); + } + + public void keyPressLong(int code1, int code2, int code3) { + this.code1 = code1; + this.code2 = code2; + this.code3 = code3; + + if (code1 != 0) robot.keyPress(code1); + if (code2 != 0) robot.keyPress(code2); + if (code3 != 0) robot.keyPress(code3); + } + + public void keyPressLongReset() { + if (code1 != 0) robot.keyRelease(code1); + if (code2 != 0) robot.keyRelease(code2); + if (code3 != 0) robot.keyRelease(code3); + + this.code1 = 0; + this.code2 = 0; + this.code3 = 0; + } + + public void mouseMove(int x, int y) { + robot.mouseMove(x, y); + } + + public void mousePress(int button) { + int mask = convertMouseButtonToMask(button); + robot.mousePress(mask); + robot.delay(CLICK_DELAY); + robot.mouseRelease(mask); + } + + public void mousePressLong(int button) { + this.button1 = button; + + robot.mousePress(convertMouseButtonToMask(button)); + } + + public void mousePressLongReset() { + robot.mouseRelease(convertMouseButtonToMask(button1)); + this.button1 = 0; + } + + public void writeMessage(String text) { + for (char symbol : text.toCharArray()) { + boolean needShiftPress = Character.isUpperCase(symbol) && Character.isLetter(symbol); + int symbolIndex = "+!@#$%^&*()_".indexOf(symbol); + if (needShiftPress || (symbolIndex != -1)) { + robot.keyPress(KeyEvent.VK_SHIFT); + robot.delay(PRESS_DELAY); + } + if (symbolIndex != -1) { + symbol = (char) ('0' + symbolIndex); + } + int event = KeyEvent.getExtendedKeyCodeForChar(symbol); + try { + robot.keyPress(event); + } catch (Exception e) {} + robot.delay(PRESS_DELAY); + try { + robot.keyRelease(event); + } catch (Exception e) {} + if (needShiftPress || (symbolIndex != -1)) { + robot.delay(PRESS_DELAY); + robot.keyRelease(KeyEvent.VK_SHIFT); + } + } + } + + private int convertMouseButtonToMask(int button) { + if (button == 1) return MouseEvent.BUTTON1_MASK; // left + if (button == 3) return MouseEvent.BUTTON2_MASK; // center + if (button == 2) return MouseEvent.BUTTON3_MASK; // right + return button; + } + +}