/* * Copyright (c) 2010-2016, Sikuli.org, sikulix.com * Released under the MIT License. * */ package org.sikuli.ide; import org.sikuli.basics.PreferencesUser; import java.awt.*; import java.awt.event.*; import java.awt.image.BufferedImage; import java.io.*; import javax.imageio.*; import javax.swing.*; import org.sikuli.script.Location; import org.sikuli.basics.Debug; import org.sikuli.basics.FileManager; import org.sikuli.script.Image; class EditorPatternButton extends JButton implements ActionListener, Serializable, MouseListener { public static final int DEFAULT_NUM_MATCHES = 50; static final float DEFAULT_SIMILARITY = 0.7f; private String _imgFilename, _thumbFname, _imgFilenameSaved; private Image _image; private JLabel patternImageIcon = null; private EditorPane _pane; private float _similarity, _similaritySaved; private int _numMatches = DEFAULT_NUM_MATCHES; private boolean _exact, _exactSaved; private Location _offset = new Location(0, 0), _offsetSaved; private int _imgW, _imgH; private float _scale = 1f; private static PatternWindow pwin = null; private static Font textFont = new Font("arial", Font.BOLD, 12); private Color oldC; private String buttonFname = ""; private String buttonSimilar = ""; private String buttonOffset = ""; private EditorPatternLabel _lbl; protected EditorPatternButton(EditorPane pane) { this._image = null; init(pane, null, null); } public EditorPatternButton(EditorPane pane, String imgFilename) { this._image = null; init(pane, imgFilename, null); } private EditorPatternButton(EditorPane pane, Image img) { this._image = null; init(pane, null, img); } protected EditorPatternButton(EditorPatternLabel lbl) { super(); this._image = null; _lbl = lbl; _imgFilename = _lbl.getFile(); _exact = false; _similarity = _lbl.getSimilarity(); _offset = _lbl.getTargetOffset(); _numMatches = DEFAULT_NUM_MATCHES; _pane = _lbl.getPane(); } private void init(EditorPane pane, String imgFilename, Image img) { //TODO thumbMax = PreferencesUser.getInstance().getDefaultThumbHeight() == 0 ? false : true; _pane = pane; _exact = false; _similarity = DEFAULT_SIMILARITY; _numMatches = DEFAULT_NUM_MATCHES; if (imgFilename != null) { setFilename(imgFilename); } else if (img != null) { setFilename(img); } setMargin(new Insets(0, 0, 0, 0)); setBorderPainted(true); setCursor(new Cursor(Cursor.HAND_CURSOR)); addActionListener(this); setButtonText(); } public BufferedImage createThumbnailImage(int maxHeight) { return createThumbnailImage(_imgFilename, maxHeight); } public static EditorPatternButton createFromFilename(EditorPane parentPane, String str, EditorPatternLabel lbl) { return createFromString(parentPane, "\"" + str + "\"", lbl); } public static EditorPatternButton createFromString(EditorPane parentPane, String str, EditorPatternLabel lbl) { if (!str.startsWith("Pattern")) { str = str.substring(1, str.length() - 1); str = FileManager.slashify(str, false); Image img = Image.createThumbNail(str); if (img.isValid() && img.isBundled()) { return new EditorPatternButton(parentPane, img); } return null; } EditorPatternButton btn = new EditorPatternButton(parentPane); String[] tokens = str.split("\\)\\s*\\.?"); for (String tok : tokens) { //System.out.println("token: " + tok); if (tok.startsWith("exact")) { btn.setExact(true); btn.setSimilarity(0.99f); } else if (tok.startsWith("Pattern")) { String filename = FileManager.slashify(tok.substring( tok.indexOf("\"") + 1, tok.lastIndexOf("\"")), false); Image img = Image.createThumbNail(filename); if (img.isValid() && img.isBundled()) { btn.setFilename(img); } else { return null; } } else if (tok.startsWith("similar")) { String strArg = tok.substring(tok.lastIndexOf("(") + 1); try { btn.setSimilarity(Float.valueOf(strArg)); } catch (NumberFormatException e) { return null; } } else if (tok.startsWith("firstN")) { // FIXME: replace with limit/max String strArg = tok.substring(tok.lastIndexOf("(") + 1); btn._numMatches = Integer.valueOf(strArg); } else if (tok.startsWith("targetOffset")) { String strArg = tok.substring(tok.lastIndexOf("(") + 1); String[] args = strArg.split(","); try { Location offset = new Location(0, 0); offset.x = Integer.valueOf(args[0]); offset.y = Integer.valueOf(args[1]); btn.setTargetOffset(offset); } catch (NumberFormatException e) { return null; } } } btn.setButtonText(); return btn; } @Override public void actionPerformed(ActionEvent e) { Debug.log(3, "ThumbButtonLabel: open Pattern Settings"); _pane.saveCaretPosition(); if (pwin == null) { _offsetSaved = new Location(_offset); _similaritySaved = _similarity; _exactSaved = _similarity >= 0.99f; _imgFilenameSaved = _imgFilename.substring(0); pwin = new PatternWindow(this, _exactSaved, _similarity, _numMatches); pwin.setTargetOffset(_offset); } pwin.requestFocus(); } @Override public Point getLocationOnScreen() { if (_lbl == null) { return super.getLocationOnScreen(); } else { return _lbl.getLocationOnScreen(); } } @Override public void mouseEntered(MouseEvent me) { } @Override public void mouseExited(MouseEvent me) { } public PatternWindow getWindow() { return pwin; } public void resetWindow() { pwin = null; } public String getFilename() { File img = new File(_imgFilename); String oldBundle = img.getParent(); String newBundle = _pane.getSrcBundle(); Debug.log(4, "ImageButton.getFilename: old: " + oldBundle + "\nnew: " + newBundle); if (FileManager.pathEquals(newBundle, oldBundle)) { return _imgFilename; } setFilename(new File(newBundle, img.getName()).getAbsolutePath()); return _imgFilename; } public void setFilename(String fileName) { _image = _pane.getImageInBundle(fileName); _imgFilename = _image.getFilename(); setIcon(new ImageIcon(createThumbnailImage(_imgFilename, PreferencesUser.getInstance().getDefaultThumbHeight()))); setButtonText(); } private void setFilename(Image img) { _image = img; _imgFilename = _image.getFilename(); setIcon(new ImageIcon(createThumbnailImage(_imgFilename, PreferencesUser.getInstance().getDefaultThumbHeight()))); setButtonText(); } private String createThumbnail(String imgFname) { return createThumbnail(imgFname, PreferencesUser.getInstance().getDefaultThumbHeight()); } private String createThumbnail(String imgFname, int maxHeight) { BufferedImage thumb = createThumbnailImage(imgFname, maxHeight); return FileManager.saveTmpImage(thumb); } private BufferedImage createThumbnailImage(String imgFname, int maxHeight) { try { BufferedImage img; if (_image != null) { img = _image.get(); } else { //TODO ???? Debug.error("EditorPatternButton: createThumbnailImage: not using Image for: " + imgFname); img = ImageIO.read(new File(imgFname)); } int w = img.getWidth(null), h = img.getHeight(null); _imgW = w; _imgH = h; if (maxHeight == 0 || maxHeight >= h) { return img; } _scale = (float) maxHeight / h; w *= _scale; h *= _scale; h = (int) h ; BufferedImage thumb = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB); Graphics2D g2d = thumb.createGraphics(); g2d.drawImage(img, 0, 0, w, h, null); g2d.dispose(); return thumb; } catch (IOException e) { Debug.error("Can't read file: " + e.getMessage()); return null; } } public boolean setParameters(boolean exact, float similarity, int numMatches) { boolean dirty = false; Debug.log(3, "ThumbButtonLabel: setParameters: " + exact + "," + similarity + "," + numMatches); dirty |= setExact(exact); dirty |= setSimilarity(similarity); setButtonText(); return dirty; } public void resetParameters() { setFilename(_imgFilenameSaved); setParameters(_exactSaved, _similaritySaved, DEFAULT_NUM_MATCHES); setTargetOffset(_offsetSaved); } public boolean setExact(boolean exact) { if (_exact != exact) { _exact = exact; return true; } return false; } public boolean setSimilarity(float val) { float sim; if (val < 0) { sim = 0; } else if (val >= 1) { sim = 0.99f; } else { sim = val; } if (sim != _similarity) { _similarity = sim; return true; } return false; } public float getSimilarity() { return _similarity; } public boolean setTargetOffset(Location offset) { Debug.log(3, "ThumbButtonLabel: setTargetOffset: " + offset.toStringShort()); if (!_offset.equals(offset)) { _offset = offset; setButtonText(); return true; } return false; } public Location getTargetOffset() { return _offset; } public String getFileName() { return _imgFilename; } //<editor-fold defaultstate="collapsed" desc="paint button"> @Override public void paint(Graphics g) { super.paint(g); Graphics2D g2d = (Graphics2D)g; drawText(g2d); if( useThumbnail() ){ g2d.setColor( new Color(0, 128, 128, 128) ); g2d.drawRoundRect(3, 3, getWidth()-7, getHeight()-7, 5, 5); } } private void drawText(Graphics2D g2d) { String strSim = null, strOffset = null; if (_similarity != DEFAULT_SIMILARITY) { if (_exact) { strSim = "99"; } else { strSim = String.format("%d", (int) (_similarity * 100)); } } if (_offset != null && (_offset.x != 0 || _offset.y != 0)) { strOffset = _offset.toStringShort(); } if (strOffset == null && strSim == null) { return; } final int fontH = g2d.getFontMetrics().getMaxAscent(); final int x = getWidth(), y = 0; drawText(g2d, strSim, x, y); if (_offset != null) { drawCross(g2d); } } private void drawText(Graphics2D g2d, String str, int x, int y) { if (str == null) { return; } final int w = g2d.getFontMetrics().stringWidth(str); final int fontH = g2d.getFontMetrics().getMaxAscent(); final int borderW = 3; g2d.setFont(textFont); g2d.setColor(new Color(0, 128, 0, 128)); g2d.fillRoundRect(x - borderW * 2 - w - 1, y, w + borderW * 2 + 1, fontH + borderW * 2 + 1, 3, 3); g2d.setColor(Color.white); g2d.drawString(str, x - w - 3, y + fontH + 3); } private void drawCross(Graphics2D g2d) { int x, y; final String cross = "+"; final int w = g2d.getFontMetrics().stringWidth(cross); final int h = g2d.getFontMetrics().getMaxAscent(); if (_offset.x > _imgW / 2) { x = getWidth() - w; } else if (_offset.x < -_imgW / 2) { x = 0; } else { x = (int) (getWidth() / 2 + _offset.x * _scale - w / 2); } if (_offset.y > _imgH / 2) { y = getHeight() + h / 2 - 3; } else if (_offset.y < -_imgH / 2) { y = h / 2 + 2; } else { y = (int) (getHeight() / 2 + _offset.y * _scale + h / 2); } g2d.setFont(textFont); g2d.setColor(new Color(0, 0, 0, 180)); g2d.drawString(cross, x + 1, y + 1); g2d.setColor(new Color(255, 0, 0, 180)); g2d.drawString(cross, x, y); } private boolean useThumbnail() { return !_imgFilename.equals(_thumbFname); } //</editor-fold> @Override public String toString() { return _pane.getPatternString(_imgFilename, _similarity, _offset, _image); } private void setButtonText() { if (_lbl == null) { setToolTipText(toString()); } else { _lbl.resetLabel(_imgFilename, _similarity, _offset); } } //<editor-fold defaultstate="collapsed" desc="mouse events not used"> @Override public void mouseClicked(MouseEvent me) {} @Override public void mousePressed(MouseEvent me) {} @Override public void mouseReleased(MouseEvent me) {} //</editor-fold> }