/*
* Copyright 2010-2013, Sikuli.org
* Released under the MIT License.
*
* modified RaiMan 2013
*/
package org.sikuli.ide;
//TODO
// dirty pane handling: on individual tab
import com.explodingpixels.macwidgets.MacUtils;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
import javax.swing.undo.*;
import org.apache.commons.cli.CommandLine;
import org.jdesktop.swingx.JXCollapsiblePane;
import org.jdesktop.swingx.JXSearchField;
import org.jdesktop.swingx.JXTaskPane;
import org.jdesktop.swingx.JXTaskPaneContainer;
import org.sikuli.ide.EditorKit;
import org.sikuli.ide.extmanager.ExtensionManagerFrame;
import org.sikuli.ide.util.Utils;
import org.sikuli.ide.z_notused.sikuli_test.UnitTestRunner;
import org.sikuli.script.CommandArgs;
import org.sikuli.script.Debug;
import org.sikuli.script.EventObserver;
import org.sikuli.script.EventSubject;
import org.sikuli.script.FileManager;
import org.sikuli.script.HotkeyEvent;
import org.sikuli.script.HotkeyListener;
import org.sikuli.script.HotkeyManager;
import org.sikuli.script.Location;
import org.sikuli.script.OverlayCapturePrompt;
import org.sikuli.script.ScreenImage;
import org.sikuli.script.Settings;
import org.sikuli.script.SikuliScript;
import org.sikuli.script.SikuliScriptRunner;
import org.sikuli.utility.AutoUpdater;
public class SikuliIDE extends JFrame {
// RaiMan not used final static boolean ENABLE_RECORDING = false;
final static boolean ENABLE_UNIFIED_TOOLBAR = true;
final static Color COLOR_SEARCH_FAILED = Color.red;
final static Color COLOR_SEARCH_NORMAL = Color.black;
final static int WARNING_CANCEL = 2;
final static int WARNING_ACCEPTED = 1;
final static int WARNING_DO_NOTHING = 0;
static boolean _runningSkl = false;
private static NativeLayer _native;
private Dimension _windowSize = null;
private Point _windowLocation = null;
private boolean smallScreen = false;
private int commandBarHeight = 800;
private CloseableTabbedPane _mainPane;
private EditorLineNumberView lineNumberColumn;
private JSplitPane _mainSplitPane;
private JTabbedPane msgPane;
private boolean msgPaneCollapsed = false;
private EditorConsolePane _console;
private JXCollapsiblePane _cmdList;
private SikuliIDEStatusBar _status = null;
private ButtonCapture _btnCapture;
private ButtonRun _btnRun, _btnRunViz;
private boolean ideIsRunningScript = false;
private JXSearchField _searchField;
private JMenuBar _menuBar = new JMenuBar();
private JMenu _fileMenu = new JMenu(_I("menuFile"));
private JMenu _editMenu = new JMenu(_I("menuEdit"));
private UndoAction _undoAction = new UndoAction();
private RedoAction _redoAction = new RedoAction();
private FindAction _findHelper;
private JMenu _runMenu = new JMenu(_I("menuRun"));
private JMenu _viewMenu = new JMenu(_I("menuView"));
private JMenu _toolMenu = new JMenu(_I("menuTool"));
private JMenu _helpMenu = new JMenu(_I("menuHelp"));
private JXCollapsiblePane _sidePane;
private JPanel _unitPane;
private JCheckBoxMenuItem _chkShowUnitTest;
private JMenuItem chkShowCmdList = null;
private JCheckBoxMenuItem chkShowThumbs;
private UnitTestRunner _testRunner;
private static CommandLine _cmdLine;
private static boolean _useStderr = false;
private static SikuliIDE _instance = null;
private static Icon PY_SRC_ICON = getIconResource("/icons/py-src-16x16.png");
private boolean _inited = false;
private static boolean runMe = false;
private int restoredScripts = 0;
private int alreadyOpenedTab = -1;
private static final String NL = String.format("%n");
private Pattern pFile = Pattern.compile("File..(.*?\\.py).*?"
+ ",.*?line.*?(\\d+),.*?in(.*?)" + NL + "(.*?)" + NL);
private int errorLine;
private int errorColumn;
private String errorType;
private String errorText;
private int errorClass;
private String errorTrace;
private static final int PY_SYNTAX = 0;
private static final int PY_RUNTIME = 1;
private static final int PY_JAVA = 2;
private static final int PY_UNKNOWN = -1;
private PreferencesUser prefs;
public static String _I(String key, Object... args) {
try {
return SikuliIDEI18N._I(key, args);
} catch (Exception e) {
System.out.println("[I18N] " + key);
return key;
}
}
public static void errorMsg(String msg) {
if (_useStderr) {
System.err.println(msg);
} else {
JOptionPane.showMessageDialog(null, msg);
}
}
public static ImageIcon getIconResource(String name) {
URL url = SikuliIDE.class.getResource(name);
if (url == null) {
Debug.error("Warning: could not load \"" + name + "\" icon");
return null;
}
return new ImageIcon(url);
}
//TODO run only one windowed instance of IDE
public static void main(String[] args) {
File file;
String fileName;
Settings.showJavaInfo();
CommandArgs cmdArgs = new CommandArgs("IDE");
_cmdLine = cmdArgs.getCommandLine(args);
boolean _newCommandline = false;
if (_cmdLine.hasOption("h")) {
cmdArgs.printHelp();
return;
}
if (_cmdLine.hasOption("test")) {
Debug.error("Test no longer supported! See docs for alternatives");
return;
}
if (_cmdLine.hasOption("s")) {
_useStderr = true;
}
if (_cmdLine.hasOption("load")) {
//TODO preload .sikuli scripts
_newCommandline = true;
Debug.error("Option -load: not yet working");
return;
}
if (!_newCommandline && args != null && args.length >= 1) {
int exitCode = 0;
fileName = args[0];
if (! fileName.startsWith("-") && fileName.endsWith(".skl")) {
String f = FileManager.unzipSKL(fileName);
if (f != null) {
args[0] = f;
_runningSkl = true;
} else {
System.exit(-2);
}
Debug.error(
"Sikuli IDE is no longer used to run scripts from command line\n"
+ "This is delegated now to sikuli-script.jar\n"
+ "Look into the docs for more information on command line usage");
try {
SikuliScript.main(args);
} catch (Exception e) {
}
if (! _runningSkl) {
//TODO System.exit() und return code
System.exit(exitCode);
} else {
return;
}
}
}
// we should open the IDE
Settings.setArgs(CommandArgs.getPyArgs(_cmdLine));
initNativeLayer();
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception e) {
e.printStackTrace();
}
if (Settings.isMac()) {
_native.initApp();
try {
Thread.sleep(1000);
} catch (InterruptedException ie) {
}
}
SikuliIDE.getInstance(args);
}
//<editor-fold defaultstate="collapsed" desc="IDE setup and general">
//TODO singleton lock
protected SikuliIDE(String[] args) {
super("Sikuli IDE");
initSikuliIDE(args);
}
private void initSikuliIDE(String[] args) {
Debug.log(5, "create SikuliIDE " + args);
// new ScriptRunner(getPyArgs(null));
prefs = PreferencesUser.getInstance();
if (prefs.getUserType() < 0) {
prefs.setUserType(PreferencesUser.NEWBEE);
prefs.setIdeSession("");
prefs.setDefaults(prefs.getUserType());
}
_native.initIDE(this);
_windowSize = prefs.getIdeSize();
_windowLocation = prefs.getIdeLocation();
Rectangle s = (new Location(_windowLocation)).getScreen().getRect();
if (_windowSize.width == 0 || _windowSize.width > s.width ||
_windowSize.height > s.height ||
(new Location(_windowLocation)).getScreenContaining(false) == null) {
if (s.width < 1025) {
_windowSize = new Dimension(1024, 700);
_windowLocation = new Point(0, 0);
} else {
_windowSize = new Dimension(s.width - 150, s.height - 100);
_windowLocation = new Point(75, 0);
}
}
if (_windowSize.getHeight() < commandBarHeight) {
smallScreen = true;
}
setSize(_windowSize);
setLocation(_windowLocation);
initMenuBars(this);
final Container c = getContentPane();
c.setLayout(new BorderLayout());
initTabPane();
initMsgPane(prefs.getPrefMoreMessage() == PreferencesUser.HORIZONTAL);
// RaiMan not used initSidePane(); // IDE UnitTest
JPanel codeAndUnitPane = new JPanel(new BorderLayout(10, 10));
codeAndUnitPane.setBorder(BorderFactory.createEmptyBorder(0, 8, 0, 0));
codeAndUnitPane.add(_mainPane, BorderLayout.CENTER);
// RaiMan not used codeAndUnitPane.add(_sidePane, BorderLayout.EAST);
if (prefs.getPrefMoreMessage() == PreferencesUser.VERTICAL) {
_mainSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, codeAndUnitPane, msgPane);
} else {
_mainSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, codeAndUnitPane, msgPane);
}
_mainSplitPane.setResizeWeight(0.6);
_mainSplitPane.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
JPanel editPane = new JPanel(new BorderLayout(0, 0));
JComponent cp = createCommandPane();
if (PreferencesUser.getInstance().getPrefMoreCommandBar()) {
editPane.add(cp, BorderLayout.WEST);
}
editPane.add(_mainSplitPane, BorderLayout.CENTER);
c.add(editPane, BorderLayout.CENTER);
JToolBar tb = initToolbar();
c.add(tb, BorderLayout.NORTH); // the buttons
c.add(initStatusbar(), BorderLayout.SOUTH);
c.doLayout();
initShortcutKeys();
initHotkeys();
setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
initWindowListener();
initTooltip();
restoreSession();
autoCheckUpdate();
if (_mainPane.getTabCount() == 0) {
(new FileAction()).doNew(null);
}
_inited = true;
getCurrentCodePane().requestFocus();
setVisible(true);
_mainSplitPane.setDividerLocation(0.6);
return; // as breakpoint
}
public static synchronized SikuliIDE getInstance(String args[]) {
if (_instance == null) {
_instance = new SikuliIDE(args);
}
return _instance;
}
public static synchronized SikuliIDE getInstance() {
return getInstance(null);
}
@Override
public void setTitle(String title) {
super.setTitle(SikuliIDESettings.SikuliVersion + " - " + title);
}
static private void initNativeLayer() {
String os = "unknown";
if (Settings.isWindows()) {
os = "Windows";
} else if (Settings.isMac()) {
os = "Mac";
} else if (Settings.isLinux()) {
os = "Linux";
}
String className = "org.sikuli.ide.NativeLayerFor" + os;
try {
Class c = Class.forName(className);
Constructor constr = c.getConstructor();
_native = (NativeLayer) constr.newInstance();
} catch (Exception e) {
e.printStackTrace();
}
}
private boolean saveSession(int action, boolean quitting) {
int nTab = _mainPane.getTabCount();
StringBuilder sbuf = new StringBuilder();
for (int tabIndex = 0; tabIndex < nTab; tabIndex++) {
try {
JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(tabIndex);
EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
if (action == WARNING_DO_NOTHING) {
if (quitting) {
codePane.setDirty(false);
if (codePane.isSourceBundleTemp()) FileManager.deleteTempDir(codePane.getSrcBundle());
}
if (codePane.getCurrentFilename() == null) {
continue;
}
} else if (codePane.isDirty()) {
if (!(new FileAction()).doSaveIntern(tabIndex)) {
if (quitting) {
codePane.setDirty(false);
}
continue;
}
}
File f = codePane.getCurrentFile();
if (f != null) {
String bundlePath = codePane.getSrcBundle();
Debug.log(5, "save session: " + bundlePath);
if (tabIndex != 0) {
sbuf.append(";");
}
sbuf.append(bundlePath);
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
PreferencesUser.getInstance().setIdeSession(sbuf.toString());
return true;
}
private void restoreSession() {
String session_str = PreferencesUser.getInstance().getIdeSession();
if (session_str == null) {
return;
}
String[] filenames = session_str.split(";");
for (int i = 0; i < filenames.length; i++) {
Debug.log(5, "restore session: " + filenames[i]);
File f = new File(filenames[i]);
if (f.exists()) {
if (loadFile(filenames[i])) {
restoredScripts += 1;
}
}
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Support SikuliIDE">
public CloseableTabbedPane getTabPane() {
return _mainPane;
}
public EditorPane getCurrentCodePane() {
if (_mainPane.getSelectedIndex() == -1) {
return null;
}
JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
EditorPane ret = (EditorPane) scrPane.getViewport().getView();
return ret;
}
public void setCurrentFileTabTitle(String fname) {
int tabIndex = _mainPane.getSelectedIndex();
setFileTabTitle(fname, tabIndex);
}
public String getCurrentFileTabTitle() {
String fname = _mainPane.getTitleAt(_mainPane.getSelectedIndex());
if (fname.startsWith("*")) {
return fname.substring(1);
}
else {
return fname;
}
}
public void setFileTabTitle(String fname, int tabIndex) {
if (fname.endsWith("/")) {
fname = fname.substring(0, fname.length() - 1);
}
fname = fname.substring(fname.lastIndexOf("/") + 1);
fname = fname.substring(0, fname.lastIndexOf("."));
_mainPane.setTitleAt(tabIndex, fname);
this.setTitle(fname);
}
public void setCurrentFileTabTitleDirty(boolean isDirty) {
int i = _mainPane.getSelectedIndex();
String title = _mainPane.getTitleAt(i);
if (!isDirty && title.startsWith("*")) {
title = title.substring(1);
_mainPane.setTitleAt(i, title);
}
else if (isDirty && ! title.startsWith("*")) {
title = "*" + title;
_mainPane.setTitleAt(i, title);
}
}
public boolean loadFile(String file) {
(new FileAction()).doNew(null);
try {
setCurrentFileTabTitle(file);
getCurrentCodePane().loadFile(file);
return true;
} catch (IOException e) {
//TODO close tab again on error
Debug.error("Can't load file " + file);
Debug.error(e.getMessage());
return false;
}
}
/**
* filename of current script to run
*
* @return absolute path
* @deprecated (used by IDE Unitest)
*/
@Deprecated
public String getCurrentFilename() {
EditorPane pane = getCurrentCodePane();
String fname = pane.getCurrentFile().getAbsolutePath();
return fname;
}
public ArrayList<String> getOpenedFilenames() {
int nTab = _mainPane.getTabCount();
File file = null;
String filePath;
ArrayList<String> filenames = new ArrayList<String>(0);
if (nTab > 0) {
for (int i = 0; i < nTab; i++) {
JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
file = codePane.getCurrentFile();
if (file != null) {
filePath = Utils.slashify(file.getAbsolutePath(), false);
filePath = filePath.substring(0, filePath.lastIndexOf("/"));
filenames.add(filePath);
} else {
filenames.add("");
}
}
}
return filenames;
}
public int isAlreadyOpen(String filename) {
alreadyOpenedTab = getOpenedFilenames().indexOf(filename);
return alreadyOpenedTab;
}
private void autoCheckUpdate() {
PreferencesUser pref = PreferencesUser.getInstance();
if (!pref.getCheckUpdate()) {
return;
}
long last_check = pref.getCheckUpdateTime();
long now = (new Date()).getTime();
if (now - last_check > 1000 * 604800) {
Debug.log(3, "autocheck update");
(new HelpAction()).checkUpdate(true);
}
pref.setCheckUpdateTime();
}
public boolean isRunningScript() {
return ideIsRunningScript;
}
public void setIsRunningScript(boolean state) {
ideIsRunningScript = state;
}
protected boolean doBeforeRun() {
int action;
if (checkDirtyPanes()) {
if (prefs.getPrefMoreRunSave()) {
action = WARNING_ACCEPTED;
} else {
action = askForSaveAll("Run");
if (action < 0) {
return false;
}
}
saveSession(action, false);
}
Settings.ActionLogs = prefs.getPrefMoreLogActions();
Settings.DebugLogs = prefs.getPrefMoreLogDebug();
Settings.InfoLogs = prefs.getPrefMoreLogInfo();
Settings.Highlight = prefs.getPrefMoreHighlight();
Settings.OcrTextSearch = prefs.getPrefMoreTextSearch();
Settings.OcrTextRead = prefs.getPrefMoreTextOCR();
return true;
}
protected boolean doBeforeQuit() {
if (checkDirtyPanes()) {
int action = askForSaveAll("Quit");
if (action < 0) {
return false;
}
return saveSession(action, true);
}
return saveSession(WARNING_DO_NOTHING, true);
}
private int askForSaveAll(String typ) {
//TODO I18N
String warn = "Some scripts are not saved yet!";
String title = SikuliIDEI18N._I("dlgAskCloseTab");
String[] options = new String[3];
options[WARNING_DO_NOTHING] = typ + " immediately";
options[WARNING_ACCEPTED] = "Save all and " + typ;
options[WARNING_CANCEL] = SikuliIDEI18N._I("cancel");
int ret = JOptionPane.showOptionDialog(this, warn, title, 0, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
if (ret == WARNING_CANCEL || ret == JOptionPane.CLOSED_OPTION) {
return -1;
}
return ret;
}
public void doAbout() {
//TODO full featured About
String info = "You are running Sikuli 1.0.0\n"
+ "Need help? -> start with Help Menu\n\n"
+ "*** Have fun ;-)\n\n"
+ "Tsung-Hsiang Chang aka vgod\n"
+ "Tom Yeh\n"
+ "Raimund Hocke aka RaiMan\n\n"
+ "May 2013";
JOptionPane.showMessageDialog(this, info,
"Sikuli About", JOptionPane.PLAIN_MESSAGE);
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="isInited --- RaiMan not used">
public boolean isInited() {
return _inited;
}
//</editor-fold>
private JMenuItem createMenuItem(JMenuItem item, KeyStroke shortcut, ActionListener listener) {
if (shortcut != null) {
item.setAccelerator(shortcut);
}
item.addActionListener(listener);
return item;
}
private JMenuItem createMenuItem(String name, KeyStroke shortcut, ActionListener listener) {
JMenuItem item = new JMenuItem(name);
return createMenuItem(item, shortcut, listener);
}
class MenuAction implements ActionListener {
protected Method actMethod = null;
protected String action;
public MenuAction() {
}
public MenuAction(String item) throws NoSuchMethodException {
Class[] params = new Class[0];
Class[] paramsWithEvent = new Class[1];
try {
paramsWithEvent[0] = Class.forName("java.awt.event.ActionEvent");
actMethod = this.getClass().getMethod(item, paramsWithEvent);
action = item;
} catch (ClassNotFoundException cnfe) {
Debug.error("Can't find menu action: " + cnfe);
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (actMethod != null) {
try {
Debug.log(3, "MenuAction." + action);
Object[] params = new Object[1];
params[0] = e;
actMethod.invoke(this, params);
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
}
//<editor-fold defaultstate="collapsed" desc="Init FileMenu">
private void initFileMenu() throws NoSuchMethodException {
int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
_fileMenu.setMnemonic(java.awt.event.KeyEvent.VK_F);
if (!Settings.isMac()) {
_fileMenu.add(createMenuItem("About SikuliX",
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, scMask),
new FileAction(FileAction.ABOUT)));
_fileMenu.addSeparator();
}
_fileMenu.add(createMenuItem(_I("menuFileNew"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_N, scMask),
new FileAction(FileAction.NEW)));
_fileMenu.add(createMenuItem(_I("menuFileOpen"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_O, scMask),
new FileAction(FileAction.OPEN)));
_fileMenu.add(createMenuItem(_I("menuFileSave"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S, scMask),
new FileAction(FileAction.SAVE)));
_fileMenu.add(createMenuItem(_I("menuFileSaveAs"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_S,
InputEvent.SHIFT_MASK | scMask),
new FileAction(FileAction.SAVE_AS)));
_fileMenu.add(createMenuItem(_I("menuFileExport"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_E,
InputEvent.SHIFT_MASK | scMask),
new FileAction(FileAction.EXPORT)));
_fileMenu.add(createMenuItem(_I("menuFileCloseTab"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_W, scMask),
new FileAction(FileAction.CLOSE_TAB)));
if (!Settings.isMac()) {
_fileMenu.addSeparator();
_fileMenu.add(createMenuItem(_I("menuFilePreferences"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_P, scMask),
new FileAction(FileAction.PREFERENCES)));
}
if (!Settings.isMac()) {
_fileMenu.addSeparator();
_fileMenu.add(createMenuItem(_I("menuFileQuit"),
null, new FileAction(FileAction.QUIT)));
}
}
class FileAction extends MenuAction {
static final String ABOUT = "doAbout";
static final String NEW = "doNew";
static final String OPEN = "doLoad";
static final String SAVE = "doSave";
static final String SAVE_AS = "doSaveAs";
static final String EXPORT = "doExport";
static final String CLOSE_TAB = "doCloseTab";
static final String PREFERENCES = "doPreferences";
static final String QUIT = "doQuit";
public FileAction() {
super();
}
public FileAction(String item) throws NoSuchMethodException {
super(item);
}
public void doAbout(ActionEvent ae) {
SikuliIDE.getInstance().doAbout();
}
public void doQuit(ActionEvent ae) {
SikuliIDE ide = SikuliIDE.getInstance();
if (!doBeforeQuit()) {
return;
}
while (true) {
EditorPane codePane = ide.getCurrentCodePane();
if (codePane == null) {
break;
}
if (!ide.closeCurrentTab()) {
return;
}
}
System.exit(0);
}
public void doPreferences(ActionEvent ae) {
SikuliIDE.getInstance().showPreferencesWindow();
}
public void doNew(ActionEvent ae) {
EditorPane codePane = new EditorPane();
JScrollPane scrPane = new JScrollPane(codePane);
lineNumberColumn = new EditorLineNumberView(codePane);
scrPane.setRowHeaderView(lineNumberColumn);
_mainPane.addTab(_I("tabUntitled"), scrPane);
_mainPane.setSelectedIndex(_mainPane.getTabCount() - 1);
codePane.requestFocus();
}
public void doLoad(ActionEvent ae) {
alreadyOpenedTab = _mainPane.getSelectedIndex();
try {
doNew(ae);
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
String fname = codePane.loadFile();
if (fname != null) {
SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
} else {
doCloseTab(ae);
_mainPane.setSelectedIndex(alreadyOpenedTab);
}
} catch (IOException eio) {
eio.printStackTrace();
}
}
public void doSave(ActionEvent ae) {
try {
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
String fname = codePane.saveFile();
if (fname != null) {
SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
}
} catch (IOException eio) {
eio.printStackTrace();
}
}
public boolean doSaveIntern(int tabIndex) {
JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(tabIndex);
EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
try {
String fname = codePane.saveFile();
if (fname != null) {
SikuliIDE.getInstance().setFileTabTitle(fname, tabIndex);
} else {
return false;
}
} catch (IOException eio) {
eio.printStackTrace();
return false;
}
return true;
}
public void doSaveAs(ActionEvent ae) {
try {
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
String fname = codePane.saveAsFile();
if (fname != null) {
SikuliIDE.getInstance().setCurrentFileTabTitle(fname);
}
} catch (IOException eio) {
eio.printStackTrace();
}
}
public void doExport(ActionEvent ae) {
try {
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
String fname = codePane.exportAsZip();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void doCloseTab(ActionEvent ae) {
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
try {
if (codePane.close()) {
_mainPane.remove(_mainPane.getSelectedIndex());
}
} catch (IOException e) {
Debug.info("Can't close this tab: " + e.getStackTrace());
}
codePane = SikuliIDE.getInstance().getCurrentCodePane();
if (codePane != null) {
codePane.requestFocus();
} else if (ae != null) {
(new FileAction()).doNew(null);
}
}
}
public void showPreferencesWindow() {
PreferencesWin pwin = new PreferencesWin();
pwin.setAlwaysOnTop(true);
pwin.setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
if (!Settings.isJava7()) {
pwin.setLocation(SikuliIDE.getInstance().getLocation());
}
pwin.setVisible(true);
}
public boolean closeCurrentTab() {
EditorPane pane = getCurrentCodePane();
(new FileAction()).doCloseTab(null);
if (pane == getCurrentCodePane()) {
return false;
}
return true;
}
protected boolean quit() {
SikuliIDE ide = SikuliIDE.getInstance();
(new FileAction()).doQuit(null);
if (ide.getCurrentCodePane() == null) {
return true;
} else {
return false;
}
}
protected boolean checkDirtyPanes() {
for (int i = 0; i < _mainPane.getTabCount(); i++) {
try {
JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
if (codePane.isDirty()) {
//RaiMan not used: getRootPane().putClientProperty("Window.documentModified", true);
return true;
}
} catch (Exception e) {
Debug.error("checkDirtyPanes: " + e.getMessage());
}
}
//RaiMan not used: getRootPane().putClientProperty("Window.documentModified", false);
return false;
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Init EditMenu">
private void initEditMenu() throws NoSuchMethodException {
int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
_editMenu.setMnemonic(java.awt.event.KeyEvent.VK_E);
JMenuItem undoItem = _editMenu.add(_undoAction);
undoItem.setAccelerator(
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, scMask));
JMenuItem redoItem = _editMenu.add(_redoAction);
redoItem.setAccelerator(
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_Z, scMask | InputEvent.SHIFT_MASK));
_editMenu.addSeparator();
_editMenu.add(createMenuItem(_I("menuEditCut"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_X, scMask),
new EditAction(EditAction.CUT)));
_editMenu.add(createMenuItem(_I("menuEditCopy"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_C, scMask),
new EditAction(EditAction.COPY)));
_editMenu.add(createMenuItem(_I("menuEditPaste"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_V, scMask),
new EditAction(EditAction.PASTE)));
_editMenu.add(createMenuItem(_I("menuEditSelectAll"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_A, scMask),
new EditAction(EditAction.SELECT_ALL)));
_editMenu.addSeparator();
JMenu findMenu = new JMenu(_I("menuFind"));
_findHelper = new FindAction();
findMenu.setMnemonic(KeyEvent.VK_F);
findMenu.add(createMenuItem(_I("menuFindFind"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_F, scMask),
new FindAction(FindAction.FIND)));
findMenu.add(createMenuItem(_I("menuFindFindNext"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, scMask),
new FindAction(FindAction.FIND_NEXT)));
findMenu.add(createMenuItem(_I("menuFindFindPrev"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_G, scMask | InputEvent.SHIFT_MASK),
new FindAction(FindAction.FIND_PREV)));
_editMenu.add(findMenu);
_editMenu.addSeparator();
_editMenu.add(createMenuItem(_I("menuEditIndent"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, 0),
new EditAction(EditAction.INDENT)));
_editMenu.add(createMenuItem(_I("menuEditUnIndent"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_TAB, InputEvent.SHIFT_MASK),
new EditAction(EditAction.UNINDENT)));
}
class EditAction extends MenuAction {
static final String CUT = "doCut";
static final String COPY = "doCopy";
static final String PASTE = "doPaste";
static final String SELECT_ALL = "doSelectAll";
static final String INDENT = "doIndent";
static final String UNINDENT = "doUnindent";
public EditAction() {
super();
}
public EditAction(String item) throws NoSuchMethodException {
super(item);
}
private void performEditorAction(String action, ActionEvent ae) {
SikuliIDE ide = SikuliIDE.getInstance();
EditorPane pane = ide.getCurrentCodePane();
pane.getActionMap().get(action).actionPerformed(ae);
}
public void doCut(ActionEvent ae) {
//TODO delete current line if no selection
performEditorAction(DefaultEditorKit.cutAction, ae);
}
public void doCopy(ActionEvent ae) {
//TODO copy current line if no selection
performEditorAction(DefaultEditorKit.copyAction, ae);
}
public void doPaste(ActionEvent ae) {
performEditorAction(DefaultEditorKit.pasteAction, ae);
}
public void doSelectAll(ActionEvent ae) {
performEditorAction(DefaultEditorKit.selectAllAction, ae);
}
public void doIndent(ActionEvent ae) {
SikuliIDE ide = SikuliIDE.getInstance();
EditorPane pane = ide.getCurrentCodePane();
(new EditorKit.InsertTabAction()).actionPerformed(pane);
}
public void doUnindent(ActionEvent ae) {
SikuliIDE ide = SikuliIDE.getInstance();
EditorPane pane = ide.getCurrentCodePane();
(new EditorKit.DeindentAction()).actionPerformed(pane);
}
}
class FindAction extends MenuAction {
static final String FIND = "doFind";
static final String FIND_NEXT = "doFindNext";
static final String FIND_PREV = "doFindPrev";
public FindAction() {
super();
}
public FindAction(String item) throws NoSuchMethodException {
super(item);
}
public void doFind(ActionEvent ae) {
_searchField.selectAll();
_searchField.requestFocus();
}
public void doFindNext(ActionEvent ae) {
findNext(_searchField.getText());
}
public void doFindPrev(ActionEvent ae) {
findPrev(_searchField.getText());
}
private boolean _find(String str, int begin, boolean forward) {
EditorPane codePane = getCurrentCodePane();
int pos = codePane.search(str, begin, forward);
Debug.log(7, "find \"" + str + "\" at " + begin + ", found: " + pos);
if (pos < 0) {
return false;
}
return true;
}
public boolean findStr(String str) {
if (getCurrentCodePane() != null) {
return _find(str, getCurrentCodePane().getCaretPosition(), true);
}
return false;
}
public boolean findPrev(String str) {
if (getCurrentCodePane() != null) {
return _find(str, getCurrentCodePane().getCaretPosition(), false);
}
return false;
}
public boolean findNext(String str) {
if (getCurrentCodePane() != null) {
return _find(str,
getCurrentCodePane().getCaretPosition() + str.length(),
true);
}
return false;
}
public void setFailed(boolean failed) {
Debug.log(7, "search failed: " + failed);
_searchField.setBackground(Color.white);
if (failed) {
_searchField.setForeground(COLOR_SEARCH_FAILED);
} else {
_searchField.setForeground(COLOR_SEARCH_NORMAL);
}
}
}
class UndoAction extends AbstractAction {
public UndoAction() {
super(_I("menuEditUndo"));
setEnabled(false);
}
public void updateUndoState() {
if (getCurrentCodePane() != null
&& getCurrentCodePane().getUndoManager().canUndo()) {
setEnabled(true);
} else {
setEnabled(false);
}
}
@Override
public void actionPerformed(ActionEvent e) {
EditorUndoManager undo = getCurrentCodePane().getUndoManager();
try {
undo.undo();
} catch (CannotUndoException ex) {
}
updateUndoState();
_redoAction.updateRedoState();
}
}
class RedoAction extends AbstractAction {
public RedoAction() {
super(_I("menuEditRedo"));
setEnabled(false);
}
@Override
public void actionPerformed(ActionEvent e) {
EditorUndoManager undo = getCurrentCodePane().getUndoManager();
try {
undo.redo();
} catch (CannotRedoException ex) {
}
updateRedoState();
_undoAction.updateUndoState();
}
protected void updateRedoState() {
if (getCurrentCodePane() != null
&& getCurrentCodePane().getUndoManager().canRedo()) {
setEnabled(true);
} else {
setEnabled(false);
}
}
}
public void updateUndoRedoStates() {
_undoAction.updateUndoState();
_redoAction.updateRedoState();
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Init Run Menu">
private void initRunMenu() throws NoSuchMethodException {
int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
_runMenu.setMnemonic(java.awt.event.KeyEvent.VK_R);
_runMenu.add(createMenuItem(_I("menuRunRun"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R, scMask),
new RunAction(RunAction.RUN)));
_runMenu.add(createMenuItem(_I("menuRunRunAndShowActions"),
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_R,
InputEvent.ALT_MASK | scMask),
new RunAction(RunAction.RUN_SHOW_ACTIONS)));
PreferencesUser pref = PreferencesUser.getInstance();
JMenuItem stopItem = createMenuItem(_I("menuRunStop"),
KeyStroke.getKeyStroke(
pref.getStopHotkey(), pref.getStopHotkeyModifiers()),
new RunAction(RunAction.RUN_SHOW_ACTIONS));
stopItem.setEnabled(false);
_runMenu.add(stopItem);
}
class RunAction extends MenuAction {
static final String RUN = "run";
static final String RUN_SHOW_ACTIONS = "runShowActions";
public RunAction() {
super();
}
public RunAction(String item) throws NoSuchMethodException {
super(item);
}
public void run(ActionEvent ae) {
doRun(_btnRun);
}
public void runShowActions(ActionEvent ae) {
doRun(_btnRunViz);
}
private void doRun(ButtonRun btn) {
btn.runCurrentScript();
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Init View Menu">
private void initViewMenu() throws NoSuchMethodException {
int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
_viewMenu.setMnemonic(java.awt.event.KeyEvent.VK_V);
if (prefs.getPrefMoreCommandBar()) {
chkShowCmdList = new JCheckBoxMenuItem(_I("menuViewCommandList"), true);
_viewMenu.add(createMenuItem(chkShowCmdList,
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_L, scMask),
new ViewAction(ViewAction.CMD_LIST)));
}
chkShowThumbs = new JCheckBoxMenuItem(_I("menuShowThumbs"), false);
_viewMenu.add(createMenuItem(chkShowThumbs,
KeyStroke.getKeyStroke(java.awt.event.KeyEvent.VK_T, scMask),
new ViewAction(ViewAction.SHOW_THUMBS)));
//TODO Message Area clear
//TODO Message Area LineBreak
}
class ViewAction extends MenuAction {
static final String UNIT_TEST = "toggleUnitTest";
static final String CMD_LIST = "toggleCmdList";
static final String SHOW_THUMBS = "toggleShowThumbs";
public ViewAction() {
super();
}
public ViewAction(String item) throws NoSuchMethodException {
super(item);
}
public void toggleCmdList(ActionEvent ae) {
_cmdList.setCollapsed(!_cmdList.isCollapsed());
}
public void toggleShowThumbs(ActionEvent ae) {
getCurrentCodePane().showThumbs = chkShowThumbs.getState();
if (! getCurrentCodePane().reparse()) {
chkShowThumbs.setState(! chkShowThumbs.getState());
getCurrentCodePane().showThumbs = chkShowThumbs.getState();
}
}
public void toggleUnitTest(ActionEvent ae) {
if (_chkShowUnitTest.getState()) {
_sidePane.setCollapsed(false);
} else {
_sidePane.setCollapsed(true);
}
}
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Init ToolMenu">
private void initToolMenu() throws NoSuchMethodException {
int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
_toolMenu.setMnemonic(java.awt.event.KeyEvent.VK_T);
if (Settings.SikuliRepo != null) {
_toolMenu.add(createMenuItem(_I("menuToolExtensions"),
null,
new ToolAction(ToolAction.EXTENSIONS)));
}
}
class ToolAction extends MenuAction {
static final String EXTENSIONS = "extensions";
public ToolAction() {
super();
}
public ToolAction(String item) throws NoSuchMethodException {
super(item);
}
public void extensions(ActionEvent ae) {
showExtensionsFrame();
}
}
public void showExtensionsFrame() {
String warn = "You might proceed, if you\n" +
"- have some programming skills\n" +
"- read the docs about extensions\n" +
"- know what you are doing\n\n" +
"Otherwise you should press Cancel!";
String title = "Need your attention!";
String[] options = new String[3];
options[WARNING_DO_NOTHING] = "OK";
options[WARNING_ACCEPTED] = "Be quiet!";
options[WARNING_CANCEL] = "Cancel";
int ret = JOptionPane.showOptionDialog(this, warn, title, 0, JOptionPane.WARNING_MESSAGE, null, options, options[2]);
if (ret == WARNING_CANCEL || ret == JOptionPane.CLOSED_OPTION) {
return;
}
if (ret == WARNING_ACCEPTED) {
//TODO set prefs to be quiet on extensions warning
};
ExtensionManagerFrame extmg = ExtensionManagerFrame.getInstance();
extmg.setVisible(true);
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Init Help Menu">
private void initHelpMenu() throws NoSuchMethodException {
int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
_helpMenu.setMnemonic(java.awt.event.KeyEvent.VK_H);
_helpMenu.add(createMenuItem(_I("menuHelpQuickStart"),
null, new HelpAction(HelpAction.QUICK_START)));
_helpMenu.addSeparator();
_helpMenu.add(createMenuItem(_I("menuHelpGuide"),
null, new HelpAction(HelpAction.OPEN_DOC)));
_helpMenu.add(createMenuItem(_I("menuHelpDocumentations"),
null, new HelpAction(HelpAction.OPEN_GUIDE)));
_helpMenu.add(createMenuItem(_I("menuHelpFAQ"),
null, new HelpAction(HelpAction.OPEN_FAQ)));
_helpMenu.add(createMenuItem(_I("menuHelpAsk"),
null, new HelpAction(HelpAction.OPEN_ASK)));
_helpMenu.add(createMenuItem(_I("menuHelpBugReport"),
null, new HelpAction(HelpAction.OPEN_BUG_REPORT)));
// _helpMenu.add(createMenuItem(_I("menuHelpTranslation"),
// null, new HelpAction(HelpAction.OPEN_TRANSLATION)));
_helpMenu.addSeparator();
_helpMenu.add(createMenuItem(_I("menuHelpHomepage"),
null, new HelpAction(HelpAction.OPEN_HOMEPAGE)));
_helpMenu.addSeparator();
_helpMenu.add(createMenuItem(_I("menuHelpCheckUpdate"),
null, new HelpAction(HelpAction.CHECK_UPDATE)));
}
class HelpAction extends MenuAction {
static final String CHECK_UPDATE = "doCheckUpdate";
static final String QUICK_START = "openQuickStart";
static final String OPEN_DOC = "openDoc";
static final String OPEN_GUIDE = "openTutor";
static final String OPEN_FAQ = "openFAQ";
static final String OPEN_ASK = "openAsk";
static final String OPEN_BUG_REPORT = "openBugReport";
static final String OPEN_TRANSLATION = "openTranslation";
static final String OPEN_HOMEPAGE = "openHomepage";
public HelpAction() {
super();
}
public HelpAction(String item) throws NoSuchMethodException {
super(item);
}
public void openQuickStart(ActionEvent ae) {
FileManager.openURL("https://github.com/RaiMan/SikuliX-IDE/wiki/Release-Notes-IDE");
}
public void openDoc(ActionEvent ae) {
FileManager.openURL("http://doc.sikuli.org");
}
public void openTutor(ActionEvent ae) {
FileManager.openURL("http://www.sikuli.org/videos.html");
}
public void openFAQ(ActionEvent ae) {
FileManager.openURL("https://answers.launchpad.net/sikuli/+faqs");
}
public void openAsk(ActionEvent ae) {
FileManager.openURL("https://answers.launchpad.net/sikuli");
}
public void openBugReport(ActionEvent ae) {
FileManager.openURL("https://bugs.launchpad.net/sikuli/+filebug");
}
public void openTranslation(ActionEvent ae) {
FileManager.openURL("https://translations.launchpad.net/sikuli/sikuli-x/+translations");
}
public void openHomepage(ActionEvent ae) {
FileManager.openURL("http://sikuli.org");
}
public void doCheckUpdate(ActionEvent ae) {
if (!checkUpdate(false)) {
JOptionPane.showMessageDialog(null,
_I("msgNoUpdate"), SikuliIDESettings.SikuliVersion,
JOptionPane.INFORMATION_MESSAGE);
}
}
public boolean checkUpdate(boolean isAutoCheck) {
JFrame f = null;
String ver = "";
String details;
AutoUpdater au = new AutoUpdater();
if (! isAutoCheck) {
//TODO replace this hack: wait update check
f = au.showUpdateFrame("Checking for new version ... pls. wait!",
"Checking for new version ... pls. wait! Checking for new version ... pls. wait!", -1);
}
PreferencesUser pref = PreferencesUser.getInstance();
Debug.log(2, "being asked to check update");
int whatUpdate = au.checkUpdate();
if (f != null) {
f.dispose();
}
if (whatUpdate >= AutoUpdater.SOMEBETA) {
//TODO add Prefs wantBeta check
whatUpdate -= AutoUpdater.SOMEBETA;
}
if ( whatUpdate > 0 ) {
if (whatUpdate == AutoUpdater.BETA) {
ver = au.getBeta();
details = au.getBetaDetails();
} else {
ver = au.getVersion();
details = au.getDetails();
}
if (isAutoCheck && pref.getLastSeenUpdate().equals(ver)) {
return false;
}
au.showUpdateFrame(_I("dlgUpdateAvailable", ver), details, whatUpdate);
PreferencesUser.getInstance().setLastSeenUpdate(ver);
return true;
}
return false;
}
}
private void initMenuBars(JFrame frame) {
try {
initFileMenu();
initEditMenu();
initRunMenu();
initViewMenu();
initToolMenu();
initHelpMenu();
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
_menuBar.add(_fileMenu);
_menuBar.add(_editMenu);
_menuBar.add(_runMenu);
_menuBar.add(_viewMenu);
_menuBar.add(_toolMenu);
_menuBar.add(_helpMenu);
frame.setJMenuBar(_menuBar);
}
//<editor-fold defaultstate="collapsed" desc="Init LeftBar Commands">
private String[] getCommandCategories() {
String[] CommandCategories = {
_I("cmdListFind"),
_I("cmdListMouse"),
_I("cmdListKeyboard"),
_I("cmdListObserver")
};
return CommandCategories;
}
private String[][] getCommandsOnToolbar() {
String[][] CommandsOnToolbar = {
{"find"}, {"PATTERN"},
{_I("cmdFind")},
{"findAll"}, {"PATTERN"},
{_I("cmdFindAll")},
{"wait"}, {"PATTERN", "[timeout]"},
{_I("cmdWait")},
{"waitVanish"}, {"PATTERN", "[timeout]"},
{_I("cmdWaitVanish")},
{"exists"}, {"PATTERN", "[timeout]"},
{_I("cmdExists")},
{"----"}, {}, {},
{"click"}, {"PATTERN", "[modifiers]"},
{_I("cmdClick")},
{"doubleClick"}, {"PATTERN", "[modifiers]"},
{_I("cmdDoubleClick")},
{"rightClick"}, {"PATTERN", "[modifiers]"},
{_I("cmdRightClick")},
{"hover"}, {"PATTERN"},
{_I("cmdHover")},
{"dragDrop"}, {"PATTERN", "PATTERN", "[modifiers]"},
{_I("cmdDragDrop")},
/* RaiMan not used
* {"drag"}, {"PATTERN"},
* {"dropAt"}, {"PATTERN", "[delay]"},
* RaiMan not used */
{"----"}, {}, {},
{"type"}, {"_text", "[modifiers]"},
{_I("cmdType")},
{"type"}, {"PATTERN", "_text", "[modifiers]"},
{_I("cmdType2")},
{"paste"}, {"_text", "[modifiers]"},
{_I("cmdPaste")},
{"paste"}, {"PATTERN", "_text", "[modifiers]"},
{_I("cmdPaste2")},
{"----"}, {}, {},
{"onAppear"}, {"PATTERN", "_hnd"},
{_I("cmdOnAppear")},
{"onVanish"}, {"PATTERN", "_hnd"},
{_I("cmdOnVanish")},
{"onChange"}, {"_hnd"},
{_I("cmdOnChange")},
{"observe"}, {"[time]", "[background]"},
{_I("cmdObserve")},};
return CommandsOnToolbar;
}
private JComponent createCommandPane() {
JXTaskPaneContainer con = new JXTaskPaneContainer();
PreferencesUser pref = PreferencesUser.getInstance();
JCheckBox chkAutoCapture =
new JCheckBox(_I("cmdListAutoCapture"),
pref.getAutoCaptureForCmdButtons());
chkAutoCapture.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(javax.swing.event.ChangeEvent e) {
boolean flag = ((JCheckBox) e.getSource()).isSelected();
PreferencesUser pref = PreferencesUser.getInstance();
pref.setAutoCaptureForCmdButtons(flag);
}
});
JXTaskPane setPane = new JXTaskPane();
setPane.setTitle(_I("cmdListSettings"));
setPane.add(chkAutoCapture);
setPane.setCollapsed(true);
con.add(setPane);
int cat = 0;
JXTaskPane taskPane = new JXTaskPane();
taskPane.setTitle(getCommandCategories()[cat++]);
con.add(taskPane);
String[][] CommandsOnToolbar = getCommandsOnToolbar();
boolean collapsed;
for (int i = 0; i < CommandsOnToolbar.length; i++) {
String cmd = CommandsOnToolbar[i++][0];
String[] params = CommandsOnToolbar[i++];
String[] desc = CommandsOnToolbar[i];
//TODO: more elegeant way, to handle special cases
if (cmd.equals("----")) {
if (cat == 2) {
collapsed = true;
} else {
collapsed = false;
}
if (cat == 3) {
if (prefs.getUserType() == PreferencesUser.NEWBEE) {
break;
} else {
collapsed = true;
}
}
taskPane = new JXTaskPane();
taskPane.setTitle(getCommandCategories()[cat++]);
con.add(taskPane);
taskPane.setCollapsed(collapsed);
} else {
taskPane.add(new ButtonGenCommand(cmd, desc[0], params));
}
}
Dimension conDim = con.getSize();
con.setPreferredSize(new Dimension(250, 1000));
_cmdList = new JXCollapsiblePane(JXCollapsiblePane.Direction.LEFT);
_cmdList.setMinimumSize(new Dimension(0, 0));
_cmdList.add(new JScrollPane(con));
_cmdList.setCollapsed(false);
return _cmdList;
}
//<editor-fold defaultstate="collapsed" desc="RaiMan obsolete">
private JToolBar initCmdToolbar() {
JToolBar toolbar = new JToolBar(JToolBar.VERTICAL);
toolbar.add(createCommandPane());
return toolbar;
}
//</editor-fold>
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="Init ToolBar Buttons">
private JToolBar initToolbar() {
if (ENABLE_UNIFIED_TOOLBAR) {
MacUtils.makeWindowLeopardStyle(this.getRootPane());
}
JToolBar toolbar = new JToolBar();
JButton btnInsertImage = new ButtonInsertImage();
_btnCapture = new ButtonCapture();
JButton btnSubregion = new ButtonSubregion();
toolbar.add(_btnCapture);
toolbar.add(btnInsertImage);
toolbar.add(btnSubregion);
toolbar.add(Box.createHorizontalGlue());
/* RaiMan not used
* if( ENABLE_RECORDING ){
* JToggleButton btnRecord = new ButtonRecord();
* toolbar.add(btnRecord);
* }
* RaiMan not used */
_btnRun = new ButtonRun();
toolbar.add(_btnRun);
_btnRunViz = new ButtonRunViz();
toolbar.add(_btnRunViz);
toolbar.add(Box.createHorizontalGlue());
toolbar.add(createSearchField());
toolbar.add(Box.createRigidArea(new Dimension(7, 0)));
toolbar.setFloatable(false);
//toolbar.setMargin(new Insets(0, 0, 0, 5));
return toolbar;
}
class ButtonInsertImage extends ButtonOnToolbar implements ActionListener {
public ButtonInsertImage() {
super();
URL imageURL = SikuliIDE.class.getResource("/icons/insert-image-icon.png");
setIcon(new ImageIcon(imageURL));
setText(SikuliIDE._I("btnInsertImageLabel"));
//setMaximumSize(new Dimension(26,26));
setToolTipText(SikuliIDE._I("btnInsertImageHint"));
addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent ae) {
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
File file = new SikuliIDEFileChooser(SikuliIDE.getInstance()).loadImage();
if (file == null) {
return;
}
String path = Utils.slashify(file.getAbsolutePath(), false);
Debug.info("load image: " + path);
EditorPatternButton icon;
String img = codePane.copyFileToBundle(path).getAbsolutePath();
if (prefs.getDefaultThumbHeight() >0) {
icon = new EditorPatternButton(codePane, img);
codePane.insertComponent(icon);
} else {
codePane.insertString("\"" + (new File(img)).getName() + "\"");
}
}
}
class ButtonSubregion extends ButtonOnToolbar implements ActionListener, EventObserver {
public ButtonSubregion() {
super();
URL imageURL = SikuliIDE.class.getResource("/icons/region-icon.png");
setIcon(new ImageIcon(imageURL));
setText(SikuliIDE._I("btnRegionLabel"));
//setMaximumSize(new Dimension(26,26));
setToolTipText(SikuliIDE._I("btnRegionHint"));
addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent ae) {
SikuliIDE ide = SikuliIDE.getInstance();
EditorPane codePane = ide.getCurrentCodePane();
ide.setVisible(false);
OverlayCapturePrompt prompt = new OverlayCapturePrompt(null, this);
prompt.prompt(SikuliIDE._I("msgCapturePrompt"), 500);
}
@Override
public void update(EventSubject s) {
if (s instanceof OverlayCapturePrompt) {
complete((OverlayCapturePrompt) s);
}
}
public void complete(OverlayCapturePrompt cp) {
int x, y, w, h;
SikuliIDE ide = SikuliIDE.getInstance();
EditorPane codePane = ide.getCurrentCodePane();
ScreenImage r = cp.getSelection();
cp.close();
if (r != null) {
Rectangle roi = r.getROI();
x = (int) roi.getX();
y = (int) roi.getY();
w = (int) roi.getWidth();
h = (int) roi.getHeight();
ide.setVisible(false);
JButton icon;
if (prefs.getPrefMoreImageThumbs()) {
icon = new EditorRegionButton(codePane, x, y, w, h);
codePane.insertComponent(icon);
} else {
codePane.insertString(codePane.getRegionString(x, y, w, h));
}
}
ide.setVisible(true);
codePane.requestFocus();
}
}
class ButtonRun extends ButtonOnToolbar implements ActionListener {
private Thread _runningThread = null;
public ButtonRun() {
super();
URL imageURL = SikuliIDE.class.getResource("/icons/run_big_green.png");
setIcon(new ImageIcon(imageURL));
initTooltip();
addActionListener(this);
setText(_I("btnRunLabel"));
//setMaximumSize(new Dimension(45,45));
}
@Override
public void actionPerformed(ActionEvent ae) {
runCurrentScript();
}
public void runCurrentScript() {
SikuliIDE ide = SikuliIDE.getInstance();
if (ideIsRunningScript || !ide.doBeforeRun()) {
return;
}
ide.setIsRunningScript(true);
_runningThread = new Thread() {
@Override
public void run() {
EditorPane codePane = SikuliIDE.getInstance().getCurrentCodePane();
File tmpFile;
tmpFile = FileManager.createTempFile("py");
if (tmpFile == null) {
return;
}
try {
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(
new FileOutputStream(tmpFile),
"UTF8"));
codePane.write(bw);
SikuliIDE.getInstance().setVisible(false);
_console.clear();
resetErrorMark();
runPython(tmpFile);
} catch (Exception e) {
java.util.regex.Pattern p =
java.util.regex.Pattern.compile("SystemExit: ([0-9]+)");
Matcher matcher = p.matcher(e.toString());
//TODO error stop I18N
if (matcher.find()) {
Debug.info(_I("msgExit", matcher.group(1)));
} else {
//Debug.error(_I("msgStopped"));
findErrorSource(e, tmpFile.getAbsolutePath());
}
} finally {
SikuliIDE.getInstance().setIsRunningScript(false);
SikuliIDE.getInstance().setVisible(true);
_runningThread = null;
}
}
};
_runningThread.start();
}
protected void runPython(File f) throws Exception {
String path = SikuliIDE.getInstance().getCurrentBundlePath();
SikuliScriptRunner srunner = new SikuliScriptRunner(Settings.getArgs(), "IDE");
addPythonCode(srunner);
try {
srunner.runPython(path, f);
srunner.close();
} catch (Exception e) {
srunner.close();
throw e;
}
}
protected void addPythonCode(SikuliScriptRunner srunner) {
}
public void stopRunning() {
if (_runningThread != null) {
_runningThread.interrupt();
_runningThread.stop();
}
}
private void initTooltip() {
PreferencesUser pref = PreferencesUser.getInstance();
String strHotkey = Utils.convertKeyToText(
pref.getStopHotkey(), pref.getStopHotkeyModifiers());
String stopHint = _I("btnRunStopHint", strHotkey);
setToolTipText(_I("btnRun", stopHint));
}
private void findErrorSource(Throwable thr, String filename) {
String err = thr.toString();
// Debug.error("------------- Traceback -------------\n" + err +
// "------------- Traceback -------------\n");
errorLine = -1;
errorColumn = -1;
errorClass = PY_UNKNOWN;
errorType = "--UnKnown--";
errorText = "--UnKnown--";
String msg;
Matcher mFile = null;
if (err.startsWith("Traceback")) {
Pattern pError = Pattern.compile(NL + "(.*?):.(.*)$");
mFile = pFile.matcher(err);
if (mFile.find()) {
Debug.log(2, "Runtime error line: " + mFile.group(2)
+ "\n in function: " + mFile.group(3)
+ "\n statement: " + mFile.group(4));
errorLine = Integer.parseInt(mFile.group(2));
errorClass = PY_RUNTIME;
Matcher mError = pError.matcher(err);
if (mError.find()) {
Debug.log(2, "Error:" + mError.group(1));
Debug.log(2, "Error:" + mError.group(2));
errorType = mError.group(1);
errorText = mError.group(2);
} else {
//org.sikuli.core.FindFailed: FindFailed: can not find 1352647716171.png on the screen
Pattern pFF = Pattern.compile(": FindFailed: (.*?)" + NL);
Matcher mFF = pFF.matcher(err);
if (mFF.find()) {
errorType = "FindFailed";
errorText = mFF.group(1);
} else {
errorClass = PY_UNKNOWN;
}
}
}
} else if (err.startsWith("SyntaxError")) {
Pattern pLineS = Pattern.compile(", (\\d+), (\\d+),");
java.util.regex.Matcher mLine = pLineS.matcher(err);
if (mLine.find()) {
Debug.log(4, "SyntaxError error line: " + mLine.group(1));
Pattern pText = Pattern.compile("\\((.*?)\\(");
java.util.regex.Matcher mText = pText.matcher(err);
mText.find();
errorText = mText.group(1) == null ? errorText : mText.group(1);
Debug.log(4, "SyntaxError: " + errorText);
errorLine = Integer.parseInt(mLine.group(1));
errorColumn = Integer.parseInt(mLine.group(2));
errorClass = PY_SYNTAX;
errorType = "SyntaxError";
}
}
msg = "script [ " + _mainPane.getTitleAt(_mainPane.getSelectedIndex());
if (errorLine != -1) {
//Debug.error(_I("msgErrorLine", srcLine));
msg += " ] stopped with error in line " + errorLine;
if (errorColumn != -1) {
msg += " at column " + errorColumn;
}
addErrorMark(errorLine);
} else {
msg += "] stopped with error at line --unknown--";
}
if (errorClass == PY_RUNTIME || errorClass == PY_SYNTAX) {
Debug.error(msg);
Debug.error(errorType + " ( " + errorText + " )");
if (errorClass == PY_RUNTIME) {
errorClass = findErrorSourceWalkTrace(mFile, filename);
if (errorTrace.length() > 0) {
Debug.error("--- Traceback --- error source first\n"
+ "line: module ( function ) statement \n" + errorTrace);
}
}
} else if (errorClass == PY_JAVA) {
} else {
Debug.error(msg);
Debug.error("Could not evaluate error source nor reason. Analyze StackTrace!");
Debug.error(err);
}
}
private int findErrorSourceWalkTrace(Matcher m, String filename) {
//[error] Traceback (most recent call last):
//File "/var/folders/wk/pcty7jkx1r5bzc5dvs6n5x_40000gn/T/sikuli-tmp3464751893408897244.py", line 2, in
//sub.hello()
//File "/Users/rhocke/NetBeansProjects/RaiManSikuli2012-Script/sub.sikuli/sub.py", line 4, in hello
//print "hello from sub", 1/0
//ZeroDivisionError: integer division or modulo by zero
Pattern pModule = Pattern.compile(".*/(.*?).py");
//Matcher mFile = pFile.matcher(etext);
String mod;
String modIgnore = "SikuliImporter,";
StringBuilder trace = new StringBuilder();
String telem;
while (m.find()) {
if (m.group(1).equals(filename)) {
mod = "main";
} else {
Matcher mModule = pModule.matcher(m.group(1));
mModule.find();
mod = mModule.group(1);
if (modIgnore.contains(mod + ",")) {
continue;
}
}
telem = m.group(2) + ": " + mod + " ( "
+ m.group(3) + " ) " + m.group(4) + NL;
//Debug.log(2,telem);
trace.insert(0, telem);
// Debug.log(2,"Rest of Trace ----\n" + etext.substring(mFile.end()));
}
Debug.log(2, "------------- Traceback -------------\n" + trace);
errorTrace = trace.toString();
return errorClass;
}
private void findErrorSourceFromJavaStackTrace(Throwable thr, String filename) {
Debug.error("seems to be an error in the Java API supporting code");
StackTraceElement[] s;
Throwable t = thr;
while (t != null) {
s = t.getStackTrace();
Debug.log(2, "stack trace:");
for (int i = s.length - 1; i >= 0; i--) {
StackTraceElement si = s[i];
Debug.log(2, si.getLineNumber() + " " + si.getFileName());
if (si.getLineNumber() >= 0 && filename.equals(si.getFileName())) {
errorLine = si.getLineNumber();
}
}
t = t.getCause();
Debug.log(2, "cause: " + t);
}
}
public void addErrorMark(int line) {
JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
EditorLineNumberView lnview = (EditorLineNumberView) (scrPane.getRowHeader().getView());
lnview.addErrorMark(line);
EditorPane codePane = SikuliIDE.this.getCurrentCodePane();
codePane.jumpTo(line);
codePane.requestFocus();
}
public void resetErrorMark() {
JScrollPane scrPane = (JScrollPane) _mainPane.getSelectedComponent();
EditorLineNumberView lnview = (EditorLineNumberView) (scrPane.getRowHeader().getView());
lnview.resetErrorMark();
}
}
class ButtonRunViz extends ButtonRun {
public ButtonRunViz() {
super();
URL imageURL = SikuliIDE.class.getResource("/icons/run_big_yl.png");
setIcon(new ImageIcon(imageURL));
setToolTipText(_I("menuRunRunAndShowActions"));
setText(_I("btnRunSlowMotionLabel"));
}
@Override
protected void addPythonCode(SikuliScriptRunner srunner) {
srunner.runSlowMotion();
}
}
public String getCurrentBundlePath() {
EditorPane pane = getCurrentCodePane();
return pane.getSrcBundle();
}
//<editor-fold defaultstate="collapsed" desc="ButtonRecord --- RaiMan not used">
class ButtonRecord extends JToggleButton implements ActionListener {
public ButtonRecord() {
super();
URL imageURL = SikuliIDE.class.getResource("/icons/record.png");
setIcon(new ImageIcon(imageURL));
setMaximumSize(new Dimension(26, 26));
setBorderPainted(false);
setToolTipText("Record");
addActionListener(this);
}
private void initSikuliGenerator() {
}
public void startSikuliGenerator() {
try {
String args[] = {"/tmp/sikuli-video.mov", "/tmp/sikuli-event.log"};
//FIXME: test if this works..
Class c = Class.forName("SikuliGenerator");
Class[] t_params = {
String[].class, EditorPane.class
};
Constructor constr = c.getConstructor(t_params);
constr.newInstance(new Object[]{
args, getCurrentCodePane()
});
// SikuliGenerator sg = new SikuliGenerator(args,
// getCurrentCodePane());
} catch (Exception e) {
Debug.error("Error in starting up SikuliGenerator...");
e.printStackTrace();
}
}
@Override
public void actionPerformed(ActionEvent ae) {
if (getModel().isSelected()) {
Debug.info("start recording");
Thread recordThread = new Thread() {
@Override
public void run() {
Utils.runRecorder();
Debug.info("recording completed");
getModel().setSelected(false);
startSikuliGenerator();
}
};
recordThread.start();
} else {
Debug.info("stop recording...");
Utils.stopRecorder();
}
}
}
//</editor-fold>
private JComponent createSearchField() {
/*
* if(Utils.isMacOSX()){
* _searchField = new JTextField();
* _searchField.putClientProperty("JTextField.variant", "search");
* }
* else{
* _searchField = new JXSearchField();
* }
*/
_searchField = new JXSearchField("Find");
_searchField.setUseNativeSearchFieldIfPossible(true);
//_searchField.setLayoutStyle(JXSearchField.LayoutStyle.MAC);
_searchField.setMinimumSize(new Dimension(220, 30));
_searchField.setPreferredSize(new Dimension(220, 30));
_searchField.setMaximumSize(new Dimension(380, 30));
_searchField.setMargin(new Insets(0, 3, 0, 3));
_searchField.setCancelAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
getCurrentCodePane().requestFocus();
_findHelper.setFailed(false);
}
});
_searchField.setFindAction(new ActionListener() {
@Override
public void actionPerformed(ActionEvent evt) {
//FIXME: On Linux the found selection disappears somehow
if (!Settings.isLinux()) //HACK
{
_searchField.selectAll();
}
boolean ret = _findHelper.findNext(_searchField.getText());
_findHelper.setFailed(!ret);
}
});
_searchField.addKeyListener(new KeyAdapter() {
@Override
public void keyReleased(java.awt.event.KeyEvent ke) {
boolean ret;
if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_ENTER) {
//FIXME: On Linux the found selection disappears somehow
if (!Settings.isLinux()) //HACK
{
_searchField.selectAll();
}
ret = _findHelper.findNext(_searchField.getText());
} else {
ret = _findHelper.findStr(_searchField.getText());
}
_findHelper.setFailed(!ret);
}
});
return _searchField;
}
//</editor-fold>
private void initTabPane() {
_mainPane = new CloseableTabbedPane();
_mainPane.setUI(new AquaCloseableTabbedPaneUI());
_mainPane.addCloseableTabbedPaneListener(
new CloseableTabbedPaneListener() {
@Override
public boolean closeTab(int i) {
try {
JScrollPane scrPane = (JScrollPane) _mainPane.getComponentAt(i);
EditorPane codePane = (EditorPane) scrPane.getViewport().getView();
int count = _mainPane.getComponentCount();
Debug.log(8, "close tab " + i + " n:" + _mainPane.getComponentCount());
boolean ret = codePane.close();
Debug.log(8, "after close tab n:" + _mainPane.getComponentCount());
if (ret && _mainPane.getTabCount() < 2) {
(new FileAction()).doNew(null);
}
return ret;
} catch (Exception e) {
Debug.info("Can't close this tab: " + e.getStackTrace());
e.printStackTrace();
return false;
}
}
});
_mainPane.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(javax.swing.event.ChangeEvent e) {
JTabbedPane tab = (JTabbedPane) e.getSource();
int i = tab.getSelectedIndex();
if (i >= 0) {
SikuliIDE.this.setTitle(tab.getTitleAt(i));
SikuliIDE.this.chkShowThumbs.setState(SikuliIDE.this.getCurrentCodePane().showThumbs);
}
updateUndoRedoStates();
}
});
}
private void initMsgPane(boolean atBottom) {
msgPane = new JTabbedPane();
_console = new EditorConsolePane();
msgPane.addTab(_I("paneMessage"), _console);
if (Settings.isWindows() || Settings.isLinux()) {
msgPane.setBorder(BorderFactory.createEmptyBorder(5, 8, 5, 8));
}
msgPane.addMouseListener(new MouseListener() {
@Override
public void mouseClicked(MouseEvent me) {
if (me.getClickCount() < 2) {
return;
}
if (msgPaneCollapsed) {
_mainSplitPane.setDividerLocation(_mainSplitPane.getLastDividerLocation());
msgPaneCollapsed = false;
} else {
int pos = _mainSplitPane.getWidth()-35;
if (prefs.getPrefMoreMessage() == PreferencesUser.HORIZONTAL) {
pos = _mainSplitPane.getHeight()-35;
}
_mainSplitPane.setDividerLocation(pos);
msgPaneCollapsed = true;
}
}
//<editor-fold defaultstate="collapsed" desc="mouse events not used">
@Override
public void mousePressed(MouseEvent me) {
}
@Override
public void mouseReleased(MouseEvent me) {
}
@Override
public void mouseEntered(MouseEvent me) {
}
@Override
public void mouseExited(MouseEvent me) {
}
//</editor-fold>
});
}
public Container getMsgPane() {
return msgPane;
}
private SikuliIDEStatusBar initStatusbar() {
_status = new SikuliIDEStatusBar();
return _status;
}
public static SikuliIDEStatusBar getStatusbar() {
if (_instance == null) {
return null;
}
else {
return _instance._status;
}
}
private void initWindowListener() {
setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {
SikuliIDE.this.quit();
}
});
addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
PreferencesUser.getInstance().setIdeSize(SikuliIDE.this.getSize());
}
@Override
public void componentMoved(ComponentEvent e) {
PreferencesUser.getInstance().setIdeLocation(SikuliIDE.this.getLocation());
}
});
}
private void initTooltip() {
ToolTipManager tm = ToolTipManager.sharedInstance();
tm.setDismissDelay(30000);
}
//<editor-fold defaultstate="collapsed" desc="Init ShortCuts HotKeys">
private void nextTab() {
int i = _mainPane.getSelectedIndex();
int next = (i + 1) % _mainPane.getTabCount();
_mainPane.setSelectedIndex(next);
}
private void prevTab() {
int i = _mainPane.getSelectedIndex();
int prev = (i - 1 + _mainPane.getTabCount()) % _mainPane.getTabCount();
_mainPane.setSelectedIndex(prev);
}
private void initShortcutKeys() {
final int scMask = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
private boolean isKeyNextTab(java.awt.event.KeyEvent ke) {
if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_TAB
&& ke.getModifiers() == InputEvent.CTRL_MASK) {
return true;
}
if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_CLOSE_BRACKET
&& ke.getModifiers() == (InputEvent.META_MASK | InputEvent.SHIFT_MASK)) {
return true;
}
return false;
}
private boolean isKeyPrevTab(java.awt.event.KeyEvent ke) {
if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_TAB
&& ke.getModifiers() == (InputEvent.CTRL_MASK | InputEvent.SHIFT_MASK)) {
return true;
}
if (ke.getKeyCode() == java.awt.event.KeyEvent.VK_OPEN_BRACKET
&& ke.getModifiers() == (InputEvent.META_MASK | InputEvent.SHIFT_MASK)) {
return true;
}
return false;
}
public void eventDispatched(AWTEvent e) {
java.awt.event.KeyEvent ke = (java.awt.event.KeyEvent) e;
//Debug.log(ke.toString());
if (ke.getID() == java.awt.event.KeyEvent.KEY_PRESSED) {
if (isKeyNextTab(ke)) {
nextTab();
} else if (isKeyPrevTab(ke)) {
prevTab();
}
}
}
}, AWTEvent.KEY_EVENT_MASK);
}
public void removeCaptureHotkey(int key, int mod) {
HotkeyManager.getInstance()._removeHotkey(key, mod);
}
public void installCaptureHotkey(int key, int mod) {
HotkeyManager.getInstance()._addHotkey(key, mod, new HotkeyListener() {
@Override
public void hotkeyPressed(HotkeyEvent e) {
if (!SikuliIDE.getInstance().isRunningScript()) {
onQuickCapture();
}
}
});
}
public void onQuickCapture() {
onQuickCapture(null);
}
public void onQuickCapture(String arg) {
Debug.log(2, "QuickCapture");
_btnCapture.capture(0);
}
public void removeStopHotkey(int key, int mod) {
HotkeyManager.getInstance()._removeHotkey(key, mod);
}
public void installStopHotkey(int key, int mod) {
HotkeyManager.getInstance()._addHotkey(key, mod, new HotkeyListener() {
@Override
public void hotkeyPressed(HotkeyEvent e) {
onStopRunning();
}
});
}
public void onStopRunning() {
Debug.log(2, "StopRunning");
this.setVisible(true);
_btnRun.stopRunning();
_btnRunViz.stopRunning();
}
private void initHotkeys() {
PreferencesUser pref = PreferencesUser.getInstance();
int key = pref.getCaptureHotkey();
int mod = pref.getCaptureHotkeyModifiers();
installCaptureHotkey(key, mod);
key = pref.getStopHotkey();
mod = pref.getStopHotkeyModifiers();
installStopHotkey(key, mod);
}
//</editor-fold>
//<editor-fold defaultstate="collapsed" desc="IDE Unit Testing --- RaiMan not used">
private void initSidePane() {
initUnitPane();
_sidePane = new JXCollapsiblePane(JXCollapsiblePane.Direction.RIGHT);
_sidePane.setMinimumSize(new Dimension(0, 0));
CloseableTabbedPane tabPane = new CloseableTabbedPane();
_sidePane.getContentPane().add(tabPane);
tabPane.setMinimumSize(new Dimension(0, 0));
tabPane.addTab(_I("tabUnitTest"), _unitPane);
tabPane.addCloseableTabbedPaneListener(new CloseableTabbedPaneListener() {
@Override
public boolean closeTab(int tabIndexToClose) {
_sidePane.setCollapsed(true);
_chkShowUnitTest.setState(false);
return false;
}
});
_sidePane.setCollapsed(true);
}
private void initUnitPane() {
_testRunner = new UnitTestRunner();
_unitPane = _testRunner.getPanel();
_chkShowUnitTest.setState(false);
addAuxTab(_I("paneTestTrace"), _testRunner.getTracePane());
}
public void addAuxTab(String tabName, JComponent com) {
msgPane.addTab(tabName, com);
}
public void jumpTo(String funcName) throws BadLocationException {
EditorPane pane = SikuliIDE.getInstance().getCurrentCodePane();
pane.jumpTo(funcName);
pane.grabFocus();
}
public void jumpTo(int lineNo) throws BadLocationException {
EditorPane pane = SikuliIDE.getInstance().getCurrentCodePane();
pane.jumpTo(lineNo);
pane.grabFocus();
}
//</editor-fold>
}