/* * Copyright (c) 2010-2016, Sikuli.org, sikulix.com * Released under the MIT License. * */ package org.sikuli.ide; import java.awt.Color; import java.awt.Container; import java.awt.Point; import java.awt.Rectangle; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.io.File; import java.util.Locale; import javax.swing.BorderFactory; import javax.swing.Box; import javax.swing.BoxLayout; import javax.swing.ImageIcon; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.border.Border; import javax.swing.text.Element; import org.sikuli.basics.Debug; import org.sikuli.basics.FileManager; import org.sikuli.script.Image; import org.sikuli.script.Location; public class EditorPatternLabel extends EditorRegionLabel { public static String CAPTURE = "__CLICK-TO-CAPTURE__"; public static String NOTFOUND = "!? "; private String lblText; private EditorPane pane; private float sim; private Location off; private String imgName = null; private String imgNameShort = null; private String imgFile; private Image image; private JFrame imgpop = null; private boolean onImagePath = true; private boolean isFromCapture; private Border pbrd = BorderFactory.createEmptyBorder(5, 5, 5, 5); private Border ibrd = BorderFactory.createLineBorder(Color.BLACK); private Border brd = BorderFactory.createCompoundBorder(pbrd, ibrd); //TODO clickToShow: make a user pref private boolean clickToShow = false; private SikuliIDEPopUpMenu popMenu = null; private boolean wasPopup = false; public EditorPatternLabel(EditorPane parentPane, String str) { super(parentPane, str); initLabel(parentPane); } public EditorPatternLabel(EditorPane parentPane, String str, boolean fromCapture) { super(parentPane, str); isFromCapture = fromCapture; initLabel(parentPane); } public EditorPatternLabel(EditorPane parentPane, String str, String oldString) { super(parentPane, str, oldString); isFromCapture = true; initLabel(parentPane); } public EditorPatternLabel(EditorPane parentPane, EditorPatternButton btn) { super(parentPane, btn.toString()); initLabel(parentPane); } private void initLabel(EditorPane parentPane) { pane = parentPane; sim = 0.7F; off = new Location(0, 0); if ("".equals(pyText)) { lblText = CAPTURE; pyText = "\"" + lblText + "\""; } else if (pyText.startsWith("Pattern")) { String[] tokens = pyText.split("\\)\\s*\\.?"); for (String tok : tokens) { //System.out.println("token: " + tok); if (tok.startsWith("exact")) { sim = 0.99F; } else if (tok.startsWith("Pattern")) { setFileNames(tok.substring(tok.indexOf("\"") + 1, tok.lastIndexOf("\""))); if (lblText == null) { break; } } else if (tok.startsWith("similar")) { String strArg = tok.substring(tok.lastIndexOf("(") + 1); try { sim = Float.valueOf(strArg); } catch (NumberFormatException e) { sim = 0.7F; } } else if (tok.startsWith("targetOffset")) { String strArg = tok.substring(tok.lastIndexOf("(") + 1); String[] args = strArg.split(","); try { off = new Location(0, 0); off.x = Integer.valueOf(args[0]); off.y = Integer.valueOf(args[1]); } catch (NumberFormatException e) { } } } if (lblText != null) { setLabelText(); } } else { setFileNames(pyText.replaceAll("\"", "")); } if (lblText == null) { onImagePath = false; } else { setText(lblText); setLabelPyText(); } } @Override public boolean isRegionLabel() { return false; } private void setFileNames(String givenName) { lblText = null; if (!new File(givenName).isAbsolute() && FileManager.isFilenameDotted(givenName)) { return; } Image img = pane.getImageInBundle(givenName); if (img.isValid()) { if (isFromCapture || !img.isAbsolute() || img.isBundled()) { image = img; imgFile = img.getFilename(); imgName = img.getName(); imgNameShort = imgName.replaceFirst(".png", "").replaceFirst(".jpg", ""); lblText = imgNameShort; } } } public boolean isOnImagePath() { return onImagePath; } public void showPopup(boolean show) { if (show) { if (imgpop == null) { BufferedImage img = image.get(); if (img == null) { Debug.log(4, "EditorPatternLabel: mouseEntered: not found " + this.imgName); return; } imgpop = new JFrame(); imgpop.setAlwaysOnTop(true); imgpop.setUndecorated(true); imgpop.setResizable(false); imgpop.setFocusableWindowState(false); imgpop.setBackground(Color.WHITE); Container p = imgpop.getContentPane(); p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS)); JLabel lbl = new JLabel(); lbl.setIcon(new ImageIcon(img)); lbl.setBorder(brd); p.add(Box.createHorizontalGlue()); p.add(lbl); p.add(Box.createHorizontalGlue()); imgpop.pack(); } Point p = getLocationOnScreen(); Rectangle r = (new Location(p)).getScreen().getRect(); Point p1 = new Point(); if (p.y < (r.y + r.height) / 2) { p1.y = p.y + getHeight() + 3; } else { p1.y = p.y - 3 - imgpop.getHeight(); } if (p.x < (r.x + r.width) / 2) { p1.x = p.x; } else { p1.x = p.x - imgpop.getWidth() + getWidth(); } imgpop.setLocation(p1); imgpop.setVisible(true); } else { if (imgpop != null) { imgpop.setVisible(false); } } } public boolean isCaptureButton() { return (CAPTURE.equals(lblText) || lblText.startsWith(NOTFOUND)); } public void resetLabel(String givenFileName, float sim, Location off) { imgName = (new File(givenFileName)).getName(); image = Image.createThumbNail(imgName); imgFile = image.getFilename(); imgNameShort = imgName.replaceFirst(".png", "").replaceFirst(".jpg", ""); this.sim = sim; this.off = off; setLabelText(); setLabelPyText(); } public void setLabelText() { String buttonSimilar = ""; if (sim != 0.7F) { buttonSimilar = String.format(Locale.ENGLISH, " .%d", (int) (sim * 100F)); } String buttonOffset = ""; if (off != null && (off.x != 0 || off.y != 0)) { buttonOffset = String.format(" (%d,%d)", off.x, off.y); } lblText = imgNameShort + buttonSimilar + buttonOffset; setText(lblText); } public void setLabelPyText() { if (!lblText.startsWith(NOTFOUND)) { pyText = pane.getPatternString(imgName, sim, off, image); } } public void setFile(String imgFile) { imgName = (new File(imgFile)).getName(); pyText = "\"" + imgName + "\""; imgNameShort = pyText.replaceAll("\"", "").replaceFirst(".png", "").replaceFirst(".jpg", ""); lblText = imgNameShort; setText(lblText); } public String getFile() { return imgFile; } public void setFileName(String img) { this.imgName = img; } public void setTargetOffset(Location off) { this.off = off; } public Location getTargetOffset() { return off; } public void setSimilarity(float sim) { this.sim = sim; } public float getSimilarity() { return sim; } public EditorPane getPane() { return pane; } public static EditorPatternLabel labelFromString(EditorPane parentPane, String str) { EditorPatternLabel reg = new EditorPatternLabel(parentPane, str, false); if (reg.isOnImagePath()) { return reg; } else { reg = null; return null; } } @Override public void mousePressed(MouseEvent me) { checkPopup(me); } @Override public void mouseReleased(MouseEvent me) { checkPopup(me); } private void checkPopup(MouseEvent me) { if (me.isPopupTrigger()) { wasPopup = true; popMenu = pane.getPopMenuImage(); if (popMenu != null) { if (imgpop != null && imgpop.isShowing()) { showPopup(false); } popMenu.show(this, me.getX(), me.getY()); } return; } } @Override public void mouseClicked(MouseEvent me) { if (wasPopup) { wasPopup = false; return; } if (clickToShow) { if (imgpop != null) { if (!imgpop.isShowing()) { showPopup(true); return; } else { showPopup(false); } } else { showPopup(true); return; } } else { if (imgpop != null && imgpop.isShowing()) { showPopup(false); } } if (!CAPTURE.equals(lblText) && !lblText.startsWith(NOTFOUND)) { (new EditorPatternButton(this)).actionPerformed(null); } else { Element x = pane.getLineAtPoint(me); //TODO recapture not found image if (x == null || lblText.startsWith(NOTFOUND)) { return; } (new ButtonCapture(pane, x)).actionPerformed(null); } } @Override public void mouseEntered(MouseEvent me) { super.mouseEntered(me); if (CAPTURE.equals(lblText) || lblText.startsWith(NOTFOUND)) { return; } if (!clickToShow) { showPopup(true); } } @Override public void mouseExited(MouseEvent me) { super.mouseExited(me); if (CAPTURE.equals(lblText)) { return; } showPopup(false); } @Override public String toString() { return super.toString(); } }