@@ -85,9 +85,14 @@ public static boolean run(RunnerListener listener) throws CancelledByUser {
8585 final Object lock = new Object ();
8686 SwingUtilities .invokeLater (() -> {
8787 Object [] options = { "Install" , "Cancel" };
88+ String missingMsg = isWin
89+ ? "C++ Mode needs a C++ compiler (g++) to compile sketches.\n \n "
90+ + "Click Install to download g++ automatically (~130 MB).\n "
91+ + "GLFW and GLEW are already bundled — no extra downloads needed."
92+ : "Missing: " + String .join (", " , missing ) + "\n \n "
93+ + "C++ Mode needs these to compile and run sketches." ;
8894 int choice = JOptionPane .showOptionDialog (null ,
89- "Missing: " + String .join (", " , missing ) + "\n \n "
90- + "C++ Mode needs these to compile and run sketches." ,
95+ missingMsg ,
9196 "C++ Mode — Missing Dependencies" ,
9297 JOptionPane .DEFAULT_OPTION , JOptionPane .WARNING_MESSAGE ,
9398 null , options , options [0 ]);
@@ -126,6 +131,7 @@ public static boolean run(RunnerListener listener) throws CancelledByUser {
126131 private JDialog dialog ;
127132 private JTextArea log ;
128133 private JLabel stepLabel ;
134+ private JProgressBar progressBar ;
129135 private JButton cancelButton ;
130136 private final AtomicBoolean cancelled = new AtomicBoolean (false );
131137 private final AtomicBoolean succeeded = new AtomicBoolean (false );
@@ -148,11 +154,17 @@ private void buildDialog(String title) {
148154 stepLabel .setFont (stepLabel .getFont ().deriveFont (Font .BOLD , 13f ));
149155 root .add (stepLabel , BorderLayout .NORTH );
150156
151- log = new JTextArea (14 , 56 );
157+ progressBar = new JProgressBar (0 , 100 );
158+ progressBar .setStringPainted (true );
159+ progressBar .setString ("" );
160+ progressBar .setValue (0 );
161+ root .add (progressBar , BorderLayout .CENTER );
162+
163+ log = new JTextArea (10 , 56 );
152164 log .setEditable (false );
153165 log .setFont (new Font (Font .MONOSPACED , Font .PLAIN , 12 ));
154166 JScrollPane scroll = new JScrollPane (log );
155- root .add (scroll , BorderLayout .CENTER );
167+ root .add (scroll , BorderLayout .SOUTH );
156168
157169 JPanel buttons = new JPanel (new FlowLayout (FlowLayout .RIGHT , 8 , 0 ));
158170 cancelButton = new JButton ("Cancel" );
@@ -177,6 +189,21 @@ private void appendLog(String text) {
177189 });
178190 }
179191
192+ private void setProgress (int pct ) {
193+ SwingUtilities .invokeLater (() -> {
194+ progressBar .setValue (pct );
195+ progressBar .setString (pct + "%" );
196+ if (pct >= 100 ) progressBar .setString ("Done" );
197+ });
198+ }
199+
200+ private void setIndeterminate (boolean b ) {
201+ SwingUtilities .invokeLater (() -> {
202+ progressBar .setIndeterminate (b );
203+ if (b ) progressBar .setString ("Working..." );
204+ });
205+ }
206+
180207 private void requestCancel () {
181208 cancelled .set (true );
182209 finishDialog (false , "Cancelled." );
@@ -186,6 +213,9 @@ private void finishDialog(boolean success, String finalMessage) {
186213 succeeded .set (success );
187214 SwingUtilities .invokeLater (() -> {
188215 if (finalMessage != null ) setStep (finalMessage );
216+ progressBar .setIndeterminate (false );
217+ progressBar .setValue (success ? 100 : progressBar .getValue ());
218+ progressBar .setString (success ? "Done" : "Failed" );
189219 cancelButton .setText ("Close" );
190220 });
191221 synchronized (doneLock ) {
@@ -260,6 +290,8 @@ private boolean installPortableGcc() {
260290 appendLog ("Source: " + WINLIBS_URL );
261291 appendLog ("Destination: " + gccDir .getAbsolutePath ());
262292 appendLog ("Size: ~130 MB — please wait..." );
293+ final long WINLIBS_SIZE = 136 * 1024 * 1024L ; // ~130 MB
294+ setProgress (0 );
263295 try (java .io .InputStream in = new java .net .URI (WINLIBS_URL ).toURL ().openStream ();
264296 java .io .OutputStream out = new java .io .FileOutputStream (zipFile )) {
265297 byte [] buf = new byte [64 * 1024 ];
@@ -268,12 +300,16 @@ private boolean installPortableGcc() {
268300 if (cancelled .get ()) return false ;
269301 out .write (buf , 0 , n );
270302 total += n ;
271- if (total % (5 * 1024 * 1024 ) < buf .length )
303+ int pct = (int ) Math .min (99 , total * 100 / WINLIBS_SIZE );
304+ setProgress (pct );
305+ if (total % (10 * 1024 * 1024 ) < buf .length )
272306 appendLog ("Downloaded " + (total / (1024 * 1024 )) + " MB..." );
273307 }
274308 }
309+ setProgress (100 );
275310 setStep ("Extracting gcc..." );
276311 appendLog ("Extracting to " + gccDir .getAbsolutePath ());
312+ setIndeterminate (true );
277313 // Use PowerShell Expand-Archive (available on all modern Windows)
278314 Process extract = new ProcessBuilder (
279315 "powershell" , "-NoProfile" , "-Command" ,
@@ -283,6 +319,8 @@ private boolean installPortableGcc() {
283319 streamToLog (extract );
284320 int code = extract .waitFor ();
285321 zipFile .delete (); // clean up zip after extraction
322+ setIndeterminate (false );
323+ setProgress (100 );
286324 if (code != 0 ) { appendLog ("Extraction failed." ); return false ; }
287325 if (!getPortableGpp ().exists ()) {
288326 appendLog ("g++.exe not found after extraction -- unexpected zip structure." );
@@ -308,8 +346,6 @@ private java.util.List<String> detectWindowsMissing() {
308346 if (new File (p ).exists ()) { haveGpp = true ; break ; }
309347 }
310348 }
311- // GLFW and GLEW are bundled in libs/windows-x64/ -- no MSYS2 needed for them.
312- // Only report them missing if the bundled DLLs aren't present AND MSYS2 doesn't have them.
313349 java .util .List <String > missing = new java .util .ArrayList <>();
314350 if (!haveGpp ) missing .add ("g++" );
315351 return missing ;
@@ -486,8 +522,6 @@ private boolean runMac(java.util.List<String> missing) {
486522 if (missing .contains ("glew" )) missingLibs .add ("glew" );
487523
488524 Thread worker = new Thread (() -> {
489- // Resolve brew at known locations first -- Processing may launch without
490- // /opt/homebrew/bin in PATH on Apple Silicon Macs.
491525 String brewExe = null ;
492526 if (new File ("/opt/homebrew/bin/brew" ).exists ()) brewExe = "/opt/homebrew/bin/brew" ;
493527 else if (new File ("/usr/local/bin/brew" ).exists ()) brewExe = "/usr/local/bin/brew" ;
@@ -539,6 +573,7 @@ private boolean runMac(java.util.List<String> missing) {
539573 }
540574
541575 setStep ("Installing: " + String .join (", " , missingLibs ));
576+ setIndeterminate (true );
542577 try {
543578 java .util .List <String > cmd = new java .util .ArrayList <>();
544579 cmd .add (brewExe ); cmd .add ("install" ); cmd .addAll (missingLibs );
0 commit comments