Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
16754f3
Phase 0: Add FlatLaf + DJ-Raven + MigLayout, neutralize mac_widgets
claude Apr 5, 2026
21b00ea
Fix console message colors for dark theme
claude Apr 5, 2026
a7eee34
Phase 1: Sidebar navigation, accelerator migration, FlatLaf tabs
claude Apr 5, 2026
d3c8820
Fix sidebar: widen to 200px, shorten button labels
claude Apr 5, 2026
82e2a21
Major UX overhaul: grouped sidebar, welcome tab, status bar, menu cle…
claude Apr 5, 2026
2f2bdcd
Fix welcome tab, tab close, menu separators, add modern fonts
claude Apr 5, 2026
4c082fd
Refactor sidebar: all items as submenus, no mixed UI
claude Apr 5, 2026
e706a7b
Fix tiny thumbnail: use preference height instead of hardcoded 20px
claude Apr 5, 2026
1bda337
Fix IDE startup crash: protect session restore and thumbnail init
claude Apr 5, 2026
89eaac0
Fix WelcomeTab errors: border syntax, context crash, logo size
claude Apr 5, 2026
34d3138
Grey out Run/Capture/Record when no script is open
claude Apr 5, 2026
5d344c5
Fix sidebar width (180px min) and WelcomeTab border errors
claude Apr 5, 2026
c21cd85
Add live info panels to sidebar: project, status, last run
claude Apr 5, 2026
9825388
Fix Welcome Tab lifecycle, image ratio, null context safety
claude Apr 5, 2026
2139355
Fix Welcome Tab: don't hide until a file is actually selected
claude Apr 5, 2026
713e62a
Fix quit crash: saveSession NPE when no scripts open
claude Apr 5, 2026
7161f02
Fix startup crash: restoreSession assumed empty script existed
claude Apr 5, 2026
0a0276a
Eclipse-style layout: explorer left, console bottom, dark welcome
claude Apr 5, 2026
620358a
Sidebar logo: OculiX in bold Serif + IDE subtitle in bordered box
claude Apr 5, 2026
e6a0110
Fix logo: center text, add SikuliX-style orange color
claude Apr 5, 2026
4e947c4
Fix greyed-out buttons and explorer placeholder issues
claude Apr 5, 2026
1845d96
Fix explorer placeholder on new script creation
claude Apr 5, 2026
dd4b855
Rewrite ScriptExplorer as workspace with visual script cards
claude Apr 5, 2026
523409d
Add workspace management: create, open, rename, auto-refresh
claude Apr 5, 2026
7e415d2
Fix File menu: flat layout with section headers
claude Apr 5, 2026
2e00561
Fix file dialogs: open on workspace/script directory
claude Apr 5, 2026
a891b6c
Fix menu section headers in sidebar popup
claude Apr 5, 2026
b052e06
Fix File menu: build popup manually with visible section headers
claude Apr 5, 2026
5a63d6e
Fix Save As: refresh workspace cards + open in workspace directory
claude Apr 5, 2026
77c7516
Fix workspace open crash: validate .sikuli bundles before loading
claude Apr 5, 2026
1757815
Fix workspace open: NPE in setFile + flexible .py detection
claude Apr 5, 2026
dc730fc
Default save dialog to folder.sikuli instead of plain file
claude Apr 5, 2026
9293fa9
Fix Save As: add .py extension to script file inside .sikuli bundle
claude Apr 5, 2026
a3c1016
Fix setFile error handling: use local var, return false instead of fatal
claude Apr 5, 2026
27abdd2
Fix 5 critical bugs found in final audit
claude Apr 5, 2026
2db79b0
Restore -s CLI flag to launch legacy ServerRunner
julienmerconsulting Apr 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions API/src/main/java/org/sikuli/script/Sikulix.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,31 @@

public class Sikulix {

public static void main(String[] args) throws FindFailed {
public static void main(String[] args) throws FindFailed {
// Mode serveur: java -jar oculixapi.jar -s
// Demarre le ServerRunner legacy sur le port 50001
for (String arg : args) {
if ("-s".equals(arg)) {
try {
Class<?> cServer = Class.forName("org.sikuli.script.runners.ServerRunner");
cServer.getMethod("run").invoke(null);
System.exit(0);
} catch (Exception e) {
System.err.println("[ERROR] Failed to start ServerRunner: " + e.getMessage());
e.printStackTrace();
System.exit(1);
}
}
}

if (args.length == 1 && "buildDate".equals(args[0])) {
System.out.println(Commons.getSxBuildStamp());
System.exit(0);
}

System.out.println("SikuliX API: nothing to do");
System.exit(0);
}
}

//<editor-fold desc="00 log">
private static int lvl = 3;
Expand Down
3 changes: 2 additions & 1 deletion API/src/main/java/org/sikuli/util/SikulixFileChooser.java
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,13 @@ public File saveAs(String extension, boolean isBundle) {
File selectedFile;
if (isBundle)
selectedFile = show("Save as .sikuli, folder or file", SAVE, DIRSANDFILES
, new SXFilter("as folder.sikuli", SXFilter.SIKULI)
, new SXFilter("as file", extension)
, new SXFilter("as plain folder", SXFilter.FOLDER)
, new SXFilter("as folder.sikuli", SXFilter.SIKULI)
);
else {
selectedFile = show("Save as .sikuli, folder or file", SAVE, DIRSANDFILES
, new SXFilter("as folder.sikuli", SXFilter.SIKULI)
, new SXFilter("as file", extension)
);
}
Expand Down
24 changes: 24 additions & 0 deletions IDE/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,30 @@
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
<!-- FlatLaf modern Look & Feel -->
<dependency>
<groupId>com.formdev</groupId>
<artifactId>flatlaf</artifactId>
<version>3.7.1</version>
</dependency>
<!-- DJ-Raven : modal dialogs, toasts, animations -->
<dependency>
<groupId>io.github.dj-raven</groupId>
<artifactId>modal-dialog</artifactId>
<version>2.6.1</version>
</dependency>
<!-- DJ-Raven : modern swing components -->
<dependency>
<groupId>io.github.dj-raven</groupId>
<artifactId>swing-pack</artifactId>
<version>1.0.1</version>
</dependency>
<!-- MigLayout : modern layout manager -->
<dependency>
<groupId>com.miglayout</groupId>
<artifactId>miglayout-swing</artifactId>
<version>11.4.3</version>
</dependency>
</dependencies>

<profiles>
Expand Down
5 changes: 1 addition & 4 deletions IDE/src/main/java/org/sikuli/ide/ButtonOnToolbar.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
*/
package org.sikuli.ide;

import com.explodingpixels.macwidgets.plaf.UnifiedToolbarButtonUI;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
Expand All @@ -18,8 +16,7 @@ public class ButtonOnToolbar extends JButton implements ActionListener {

public ButtonOnToolbar(){
setBorderPainted(false);
putClientProperty("JButton.buttonType", "textured");
setUI(new UnifiedToolbarButtonUI());
putClientProperty("JButton.buttonType", "toolBarButton");
setBorder(BorderFactory.createEmptyBorder(3,10,3,10));
}

Expand Down
20 changes: 10 additions & 10 deletions IDE/src/main/java/org/sikuli/ide/EditorConsolePane.java
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,11 @@ public synchronized void windowClosing(WindowEvent evt)
static final String lineSep = System.getProperty("line.separator");

public final static String CSS_Colors =
".normal{ color: black; }"
+ ".debug { color:#505000; }"
+ ".info { color: blue; }"
+ ".log { color: #09806A; }"
+ ".error { color: red; }";
".normal{ color: #BBBBBB; }"
+ ".debug { color:#C0A000; }"
+ ".info { color: #6CB6FF; }"
+ ".log { color: #3DDBA4; }"
+ ".error { color: #FF6B6B; }";

private String htmlize(String msg) {
StringBuilder sb = new StringBuilder();
Expand All @@ -255,16 +255,16 @@ private String htmlize(String msg) {
.replace("<", "&lt;")
.replace(">", "&gt;");

String color = "color: black;";
String color = "color: #BBBBBB;";

for (String line : msg.split(lineSep)) {
Matcher m = patMsgCat.matcher(line);
if (m.matches()) {
String logType = m.group(1).toLowerCase();
if (logType.contains("error")) color = "color: red;";
else if (logType.contains("debug")) color = "color: #505000;";
else if (logType.contains("log")) color = "color: #09806A;";
else if (logType.contains("info")) color = "color: blue;";
if (logType.contains("error")) color = "color: #FF6B6B;";
else if (logType.contains("debug")) color = "color: #C0A000;";
else if (logType.contains("log")) color = "color: #3DDBA4;";
else if (logType.contains("info")) color = "color: #6CB6FF;";
}
String font = "font-family:monospace; font-size: medium;";
int margin = 0;
Expand Down
11 changes: 10 additions & 1 deletion IDE/src/main/java/org/sikuli/ide/EditorImageButton.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
package org.sikuli.ide;

import org.apache.commons.io.FilenameUtils;
import org.sikuli.basics.PreferencesUser;
import org.sikuli.support.ide.IButton;
import org.sikuli.script.Location;
import org.sikuli.script.Pattern;
Expand Down Expand Up @@ -39,7 +40,15 @@ public String getFilename() {
return ((File) options.get(IButton.FILE)).getAbsolutePath();
}

int MAXHEIGHT = 20;
int MAXHEIGHT = getThumbHeight();

private static int getThumbHeight() {
try {
return PreferencesUser.get().getDefaultThumbHeight();
} catch (Exception e) {
return 50; // fallback
}
}

BufferedImage thumbnail;

Expand Down
72 changes: 43 additions & 29 deletions IDE/src/main/java/org/sikuli/ide/SikuliIDEStatusBar.java
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
/*
* Copyright (c) 2010-2020, sikuli.org, sikulix.com - MIT license
* Copyright (c) 2010-2026, sikuli.org, sikulix.com, oculix-org - MIT license
*/
package org.sikuli.ide;

import java.awt.*;
import javax.swing.*;

import com.explodingpixels.macwidgets.plaf.EmphasizedLabelUI;
import net.miginfocom.swing.MigLayout;
import org.sikuli.support.Commons;

import java.util.Date;
Expand All @@ -15,30 +15,33 @@ class SikuliIDEStatusBar extends JPanel {

private JLabel _lblMsg;
private JLabel _lblCaretPos;
private JLabel _lblOcrStatus;
private String currentContentType = "???";
private int currentRow;
private int currentCol;
private long starting;

public SikuliIDEStatusBar() {
setLayout(new BorderLayout());
setPreferredSize(new Dimension(10, 20));
setLayout(new MigLayout("insets 2 8 2 8, fill", "[]push[]12[]12[]", "[]"));
setPreferredSize(new Dimension(10, 22));

JPanel rightPanel = new JPanel(new BorderLayout());
rightPanel.setOpaque(false);
_lblMsg = new JLabel();
_lblMsg.setPreferredSize(new Dimension(500, 20));
_lblMsg.setUI(new EmphasizedLabelUI());
_lblMsg.setFont(new Font("Monaco", Font.TRUETYPE_FONT, 11));
_lblMsg.setFont(UIManager.getFont("Label.font").deriveFont(11.0f));

_lblOcrStatus = new JLabel();
_lblOcrStatus.setFont(UIManager.getFont("Label.font").deriveFont(11.0f));
checkOcrStatus();

_lblCaretPos = new JLabel();
_lblCaretPos.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 15));
_lblCaretPos.setUI(new EmphasizedLabelUI());
_lblCaretPos.setFont(UIManager.getFont("Button.font").deriveFont(11.0f));
_lblCaretPos.setFont(UIManager.getFont("Label.font").deriveFont(11.0f));

setCaretPosition(1, 1);
resetMessage();
add(_lblMsg, BorderLayout.WEST);
add(_lblCaretPos, BorderLayout.LINE_END);
// add(rightPanel, BorderLayout.EAST);

add(_lblMsg);
add(_lblOcrStatus);
add(new JSeparator(SwingConstants.VERTICAL), "growy");
add(_lblCaretPos);
}

public void setType(String contentType) {
Expand All @@ -57,32 +60,43 @@ public void setCaretPosition(int row, int col) {
currentRow = row;
currentCol = col;
}
_lblCaretPos.setText(String.format("(%s) | R: %d | C: %d", currentContentType, currentRow, currentCol));
_lblCaretPos.setText(String.format("[%s] R: %d C: %d", currentContentType, currentRow, currentCol));
if (starting > 0 && new Date().getTime() - starting > 3000) {
resetMessage();
}
}

public void setMessage(String text) {
_lblMsg.setText(" " + text);
_lblMsg.setText(text);
repaint();
starting = new Date().getTime();
}

public void resetMessage() {
String message = Commons.getSXVersionIDE();
message += " --- Java " + Commons.getJavaVersion();
String message = "OculiX " + Commons.getSXVersionShort() + " \u2502 Java " + Commons.getJavaVersion();
setMessage(message);
starting = 0;
}
// @Override
// protected void paintComponent(Graphics g) {
// super.paintComponent(g);
// int y = 0;
// g.setColor(new Color(156, 154, 140));
// g.drawLine(0, y, getWidth(), y);
// y++;
// g.setColor(new Color(196, 194, 183));
// g.drawLine(0, y, getWidth(), y);
// }

private void checkOcrStatus() {
try {
Class<?> engineClass = Class.forName("com.sikulix.ocr.PaddleOCREngine");
Object engine = engineClass.getDeclaredConstructor().newInstance();
boolean available = (boolean) engineClass.getMethod("isAvailable").invoke(engine);
if (available) {
_lblOcrStatus.setText("\u2B24 PaddleOCR");
_lblOcrStatus.setForeground(new Color(0x3D, 0xDB, 0xA4)); // green
} else {
_lblOcrStatus.setText("\u2B24 PaddleOCR");
_lblOcrStatus.setForeground(new Color(0xFF, 0x6B, 0x6B)); // red
}
} catch (Exception e) {
_lblOcrStatus.setText("\u2B24 PaddleOCR");
_lblOcrStatus.setForeground(UIManager.getColor("Label.disabledForeground"));
}
}

public void refreshOcrStatus() {
checkOcrStatus();
}
}
16 changes: 10 additions & 6 deletions IDE/src/main/java/org/sikuli/ide/Sikulix.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@
import org.sikuli.support.gui.SXDialog;
import org.sikuli.support.ide.SikuliIDEI18N;

import com.formdev.flatlaf.FlatDarkLaf;
import com.formdev.flatlaf.FlatLaf;

import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Method;
Expand Down Expand Up @@ -105,6 +108,12 @@ public void hotkeyPressed(HotkeyEvent e) {
Commons.startLog(1, "IDE starting (%4.1f)", Commons.getSinceStart());
//endregion

// FlatLaf must be initialized before any Swing component creation
// Use modern system fonts: Segoe UI (Win), SF Pro (Mac), Inter/Cantarell (Linux)
FlatLaf.setPreferredFontFamily("Segoe UI");
FlatLaf.setPreferredMonospacedFontFamily("Cascadia Code");
FlatDarkLaf.setup();

ideSplash = new SXDialog("sxidestartup", SikulixIDE.getWindowTop(), SXDialog.POSITION.TOP);
ideSplash.run();

Expand Down Expand Up @@ -170,12 +179,7 @@ public void hotkeyPressed(HotkeyEvent e) {
Commons.setIDETemp(ideTemp);
//endregion

if (Commons.runningMac()) {
try {
System.setProperty("apple.laf.useScreenMenuBar", "true");
} catch (Exception e) {
}
}
// apple.laf.useScreenMenuBar removed — FlatLaf handles macOS menu integration natively

SikulixIDE.start();

Expand Down
Loading
Loading