diff --git a/app/src/cc/arduino/view/SplashScreenHelper.java b/app/src/cc/arduino/view/SplashScreenHelper.java index 0e6779026..108c1c8b2 100644 --- a/app/src/cc/arduino/view/SplashScreenHelper.java +++ b/app/src/cc/arduino/view/SplashScreenHelper.java @@ -51,8 +51,12 @@ public class SplashScreenHelper { public SplashScreenHelper(SplashScreen splash) { this.splash = splash; - Toolkit tk = Toolkit.getDefaultToolkit(); - desktopHints = (Map) tk.getDesktopProperty("awt.font.desktophints"); + if (splash != null) { + Toolkit tk = Toolkit.getDefaultToolkit(); + desktopHints = (Map) tk.getDesktopProperty("awt.font.desktophints"); + } else { + desktopHints = null; + } } public void splashText(String text) { diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index aff37e0a1..50d549d0c 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -22,8 +22,10 @@ package processing.app; +import cc.arduino.Compiler; import cc.arduino.Constants; import cc.arduino.UpdatableBoardsLibsFakeURLsHandler; +import cc.arduino.UploaderUtils; import cc.arduino.contributions.*; import cc.arduino.contributions.libraries.*; import cc.arduino.contributions.libraries.ui.LibraryManagerUI; @@ -84,7 +86,6 @@ public class Base { private static boolean commandLine; public static volatile Base INSTANCE; - public static SplashScreenHelper splashScreenHelper = new SplashScreenHelper(SplashScreen.getSplashScreen()); public static Map FIND_DIALOG_STATE = new HashMap<>(); private final ContributionInstaller contributionInstaller; private final LibraryInstaller libraryInstaller; @@ -128,59 +129,13 @@ public class Base { } try { - guardedMain(args); + INSTANCE = new Base(args); } catch (Throwable e) { e.printStackTrace(System.err); System.exit(255); } } - static public void guardedMain(String args[]) throws Exception { - Thread deleteFilesOnShutdownThread = new Thread(DeleteFilesOnShutdown.INSTANCE); - deleteFilesOnShutdownThread.setName("DeleteFilesOnShutdown"); - Runtime.getRuntime().addShutdownHook(deleteFilesOnShutdownThread); - - BaseNoGui.initLogger(); - - initLogger(); - - BaseNoGui.initPlatform(); - - BaseNoGui.getPlatform().init(); - - BaseNoGui.initPortableFolder(); - - BaseNoGui.initParameters(args); - - splashScreenHelper.splashText(tr("Loading configuration...")); - - BaseNoGui.initVersion(); - - // Use native popups so they don't look so crappy on osx - JPopupMenu.setDefaultLightWeightPopupEnabled(false); - - // Don't put anything above this line that might make GUI, - // because the platform has to be inited properly first. - - // setup the theme coloring fun - Theme.init(); - System.setProperty("swing.aatext", PreferencesData.get("editor.antialias", "true")); - - // Set the look and feel before opening the window - try { - BaseNoGui.getPlatform().setLookAndFeel(); - } catch (Exception e) { - // ignore - } - - // Create a location for untitled sketches - untitledFolder = FileUtils.createTempFolder("untitled" + new Random().nextInt(Integer.MAX_VALUE), ".tmp"); - DeleteFilesOnShutdown.add(untitledFolder); - - INSTANCE = new Base(args); - } - - static public void initLogger() { Handler consoleHandler = new ConsoleLogger(); consoleHandler.setLevel(Level.ALL); @@ -208,12 +163,6 @@ public class Base { } - - static protected void setCommandLine() { - commandLine = true; - } - - static protected boolean isCommandLine() { return commandLine; } @@ -227,10 +176,60 @@ public class Base { } public Base(String[] args) throws Exception { - BaseNoGui.notifier = new GUIUserNotifier(this); + Thread deleteFilesOnShutdownThread = new Thread(DeleteFilesOnShutdown.INSTANCE); + deleteFilesOnShutdownThread.setName("DeleteFilesOnShutdown"); + Runtime.getRuntime().addShutdownHook(deleteFilesOnShutdownThread); + + BaseNoGui.initLogger(); + + initLogger(); + + BaseNoGui.initPlatform(); + + BaseNoGui.getPlatform().init(); + + BaseNoGui.initPortableFolder(); + + // Look for a possible "--preferences-file" parameter and load preferences + BaseNoGui.initParameters(args); CommandlineParser parser = new CommandlineParser(args); parser.parseArgumentsPhase1(); + commandLine = !parser.isGuiMode(); + + SplashScreenHelper splash; + if (parser.isGuiMode()) { + // Setup all notification widgets + splash = new SplashScreenHelper(SplashScreen.getSplashScreen()); + BaseNoGui.notifier = new GUIUserNotifier(this); + + // Setup the theme coloring fun + Theme.init(); + System.setProperty("swing.aatext", PreferencesData.get("editor.antialias", "true")); + + // Set the look and feel before opening the window + try { + BaseNoGui.getPlatform().setLookAndFeel(); + } catch (Exception e) { + // ignore + } + + // Use native popups so they don't look so crappy on osx + JPopupMenu.setDefaultLightWeightPopupEnabled(false); + } else { + splash = new SplashScreenHelper(null); + } + + splash.splashText(tr("Loading configuration...")); + + BaseNoGui.initVersion(); + + // Don't put anything above this line that might make GUI, + // because the platform has to be inited properly first. + + // Create a location for untitled sketches + untitledFolder = FileUtils.createTempFolder("untitled" + new Random().nextInt(Integer.MAX_VALUE), ".tmp"); + DeleteFilesOnShutdown.add(untitledFolder); BaseNoGui.checkInstallationFolder(); @@ -246,11 +245,15 @@ public class Base { } } - splashScreenHelper.splashText(tr("Initializing packages...")); + splash.splashText(tr("Initializing packages...")); BaseNoGui.initPackages(); - splashScreenHelper.splashText(tr("Preparing boards...")); - rebuildBoardsMenu(); - rebuildProgrammerMenu(); + + splash.splashText(tr("Preparing boards...")); + + if (!isCommandLine()) { + rebuildBoardsMenu(); + rebuildProgrammerMenu(); + } // Setup board-dependent variables. onBoardOrPortChange(); @@ -263,35 +266,6 @@ public class Base { parser.parseArgumentsPhase2(); - for (String path : parser.getFilenames()) { - // Correctly resolve relative paths - File file = absoluteFile(path); - - // Fix a problem with systems that use a non-ASCII languages. Paths are - // being passed in with 8.3 syntax, which makes the sketch loader code - // unhappy, since the sketch folder naming doesn't match up correctly. - // http://dev.processing.org/bugs/show_bug.cgi?id=1089 - if (OSUtils.isWindows()) { - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - boolean showEditor = parser.isGuiMode(); - if (!parser.isForceSavePrefs()) - PreferencesData.setDoSave(showEditor); - if (handleOpen(file, retrieveSketchLocation(".default"), showEditor, false) == null) { - String mess = I18n.format(tr("Failed to open sketch: \"{0}\""), path); - // Open failure is fatal in upload/verify mode - if (parser.isVerifyOrUploadMode()) - showError(null, mess, 2); - else - showWarning(null, mess, null); - } - } - // Save the preferences. For GUI mode, this happens in the quit // handler, but for other modes we should also make sure to save // them. @@ -377,35 +351,90 @@ public class Base { System.exit(0); } else if (parser.isVerifyOrUploadMode()) { - splashScreenHelper.close(); // Set verbosity for command line build - PreferencesData.set("build.verbose", "" + parser.isDoVerboseBuild()); - PreferencesData.set("upload.verbose", "" + parser.isDoVerboseUpload()); - PreferencesData.set("runtime.preserve.temp.files", Boolean.toString(parser.isPreserveTempFiles())); + PreferencesData.setBoolean("build.verbose", parser.isDoVerboseBuild()); + PreferencesData.setBoolean("upload.verbose", parser.isDoVerboseUpload()); - // Make sure these verbosity preferences are only for the - // current session + // Set preserve-temp flag + PreferencesData.setBoolean("runtime.preserve.temp.files", parser.isPreserveTempFiles()); + + // Make sure these verbosity preferences are only for the current session PreferencesData.setDoSave(false); - Editor editor = editors.get(0); + Sketch sketch = null; + String outputFile = null; - if (parser.isUploadMode()) { - splashScreenHelper.splashText(tr("Verifying and uploading...")); - editor.exportHandler.run(); - } else { - splashScreenHelper.splashText(tr("Verifying...")); - editor.runHandler.run(); + try { + // Build + splash.splashText(tr("Verifying...")); + + File sketchFile = new File(parser.getFilenames().get(0)); + sketch = new Sketch(sketchFile); + + outputFile = new Compiler(sketch).build(progress -> {}, false); + } catch (Exception e) { + // Error during build + System.exit(1); } - // Error during build or upload - if (editor.status.isErr()) { - System.exit(1); + if (parser.isUploadMode()) { + // Upload + splash.splashText(tr("Uploading...")); + + try { + List warnings = new ArrayList<>(); + UploaderUtils uploader = new UploaderUtils(); + boolean res = uploader.upload(sketch, null, outputFile, + parser.isDoUseProgrammer(), + parser.isNoUploadPort(), warnings); + for (String warning : warnings) { + System.out.println(tr("Warning") + ": " + warning); + } + if (!res) { + throw new Exception(); + } + } catch (Exception e) { + // Error during upload + System.out.flush(); + System.err.flush(); + System.err + .println(tr("An error occurred while uploading the sketch")); + System.exit(1); + } } // No errors exit gracefully System.exit(0); } else if (parser.isGuiMode()) { - splashScreenHelper.splashText(tr("Starting...")); + splash.splashText(tr("Starting...")); + + for (String path : parser.getFilenames()) { + // Correctly resolve relative paths + File file = absoluteFile(path); + + // Fix a problem with systems that use a non-ASCII languages. Paths are + // being passed in with 8.3 syntax, which makes the sketch loader code + // unhappy, since the sketch folder naming doesn't match up correctly. + // http://dev.processing.org/bugs/show_bug.cgi?id=1089 + if (OSUtils.isWindows()) { + try { + file = file.getCanonicalFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + if (!parser.isForceSavePrefs()) + PreferencesData.setDoSave(true); + if (handleOpen(file, retrieveSketchLocation(".default"), false) == null) { + String mess = I18n.format(tr("Failed to open sketch: \"{0}\""), path); + // Open failure is fatal in upload/verify mode + if (parser.isVerifyOrUploadMode()) + showError(null, mess, 2); + else + showWarning(null, mess, null); + } + } installKeyboardInputMap(); @@ -472,7 +501,7 @@ public class Base { } int[] location = retrieveSketchLocation("" + i); // If file did not exist, null will be returned for the Editor - if (handleOpen(new File(path), location, nextEditorLocation(), true, false, false) != null) { + if (handleOpen(new File(path), location, nextEditorLocation(), false, false) != null) { opened++; } } @@ -764,14 +793,14 @@ public class Base { } public Editor handleOpen(File file, boolean untitled) throws Exception { - return handleOpen(file, nextEditorLocation(), true, untitled); + return handleOpen(file, nextEditorLocation(), untitled); } - protected Editor handleOpen(File file, int[] location, boolean showEditor, boolean untitled) throws Exception { - return handleOpen(file, location, location, showEditor, true, untitled); + protected Editor handleOpen(File file, int[] location, boolean untitled) throws Exception { + return handleOpen(file, location, location, true, untitled); } - protected Editor handleOpen(File file, int[] storedLocation, int[] defaultLocation, boolean showEditor, boolean storeOpenedSketches, boolean untitled) throws Exception { + protected Editor handleOpen(File file, int[] storedLocation, int[] defaultLocation, boolean storeOpenedSketches, boolean untitled) throws Exception { if (!file.exists()) return null; // Cycle through open windows to make sure that it's not already open. @@ -804,9 +833,7 @@ public class Base { // now that we're ready, show the window // (don't do earlier, cuz we might move it based on a window being closed) - if (showEditor) { - SwingUtilities.invokeLater(() -> editor.setVisible(true)); - } + SwingUtilities.invokeLater(() -> editor.setVisible(true)); return editor; } @@ -1810,10 +1837,9 @@ public class Base { } public File getDefaultSketchbookFolderOrPromptForIt() { - File sketchbookFolder = BaseNoGui.getDefaultSketchbookFolder(); - if (sketchbookFolder == null) { + if (sketchbookFolder == null && !isCommandLine()) { sketchbookFolder = promptSketchbookLocation(); } diff --git a/arduino-core/src/cc/arduino/contributions/ConsoleProgressListener.java b/arduino-core/src/cc/arduino/contributions/ConsoleProgressListener.java index edd5eb46e..34e8d9c0d 100644 --- a/arduino-core/src/cc/arduino/contributions/ConsoleProgressListener.java +++ b/arduino-core/src/cc/arduino/contributions/ConsoleProgressListener.java @@ -33,12 +33,19 @@ import cc.arduino.utils.Progress; public class ConsoleProgressListener implements ProgressListener { private String lastStatus = ""; + private double lastProgress = 0.0; @Override public void onProgress(Progress progress) { - if (!lastStatus.equals(progress.getStatus())) { + // Reduce verbosity when running in console + String s = progress.getStatus().replaceAll("[0-9]", ""); + double p = progress.getProgress(); + + if (!lastStatus.equals(s) || (p - lastProgress) > 1.0) { System.out.println(progress.getStatus()); + lastProgress = p; } - lastStatus = progress.getStatus(); + + lastStatus = s; } } diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index e1dc220b0..89498c3c6 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -1,8 +1,6 @@ package processing.app; -import cc.arduino.Compiler; import cc.arduino.Constants; -import cc.arduino.UploaderUtils; import cc.arduino.contributions.GPGDetachedSignatureVerifier; import cc.arduino.contributions.SignatureVerificationFailedException; import cc.arduino.contributions.VersionComparator; @@ -10,9 +8,7 @@ import cc.arduino.contributions.libraries.LibrariesIndexer; import cc.arduino.contributions.packages.ContributedPlatform; import cc.arduino.contributions.packages.ContributedTool; import cc.arduino.contributions.packages.ContributionsIndexer; -import cc.arduino.files.DeleteFilesOnShutdown; import cc.arduino.packages.DiscoveryManager; -import cc.arduino.packages.Uploader; import com.fasterxml.jackson.core.JsonProcessingException; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.logging.impl.LogFactoryImpl; @@ -442,156 +438,6 @@ public class BaseNoGui { return list; } - static public void init(String[] args) throws Exception { - CommandlineParser parser = new CommandlineParser(args); - parser.parseArgumentsPhase1(); - - String sketchbookPath = getSketchbookPath(); - - // If no path is set, get the default sketchbook folder for this platform - if (sketchbookPath == null) { - if (BaseNoGui.getPortableFolder() != null) - PreferencesData.set("sketchbook.path", getPortableSketchbookFolder()); - else - showError(tr("No sketchbook"), tr("Sketchbook path not defined"), null); - } - - BaseNoGui.initPackages(); - - parser.parseArgumentsPhase2(); - - for (String path: parser.getFilenames()) { - // Correctly resolve relative paths - File file = absoluteFile(path); - - // Fix a problem with systems that use a non-ASCII languages. Paths are - // being passed in with 8.3 syntax, which makes the sketch loader code - // unhappy, since the sketch folder naming doesn't match up correctly. - // http://dev.processing.org/bugs/show_bug.cgi?id=1089 - if (OSUtils.isWindows()) { - try { - file = file.getCanonicalFile(); - } catch (IOException e) { - e.printStackTrace(); - } - } - - if (!parser.isVerifyOrUploadMode() && !parser.isGetPrefMode()) - showError(tr("Mode not supported"), tr("Only --verify, --upload or --get-pref are supported"), null); - - if (!parser.isForceSavePrefs()) - PreferencesData.setDoSave(false); - if (!file.exists()) { - String mess = I18n.format(tr("Failed to open sketch: \"{0}\""), path); - // Open failure is fatal in upload/verify mode - showError(null, mess, 2); - } - } - - // Setup board-dependent variables. - onBoardOrPortChange(); - - // Save the preferences. For GUI mode, this happens in the quit - // handler, but for other modes we should also make sure to save - // them. - PreferencesData.save(); - - if (parser.isVerifyOrUploadMode()) { - // Set verbosity for command line build - PreferencesData.set("build.verbose", "" + parser.isDoVerboseBuild()); - PreferencesData.set("upload.verbose", "" + parser.isDoVerboseUpload()); - - // Make sure these verbosity preferences are only for the - // current session - PreferencesData.setDoSave(false); - - if (parser.isUploadMode()) { - - if (parser.getFilenames().size() != 1) - { - showError(tr("Multiple files not supported"), tr("The --upload option supports only one file at a time"), null); - } - - List warningsAccumulator = new LinkedList<>(); - boolean success = false; - try { - // Editor constructor loads the sketch with handleOpenInternal() that - // creates a new Sketch that, in turn, builds a SketchData - // inside its constructor. - // This translates here as: - // SketchData data = new SketchData(file); - // File tempBuildFolder = getBuildFolder(); - Sketch data = new Sketch(absoluteFile(parser.getFilenames().get(0))); - - // Sketch.exportApplet() - // - calls Sketch.prepare() that calls Sketch.ensureExistence() - // - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build() - // - calls Sketch.upload() (see later...) - if (!data.getFolder().exists()) { - showError(tr("No sketch"), tr("Can't find the sketch in the specified path"), null); - } - String suggestedClassName = new Compiler(data).build(null, false); - if (suggestedClassName == null) { - showError(tr("Error while verifying"), tr("An error occurred while verifying the sketch"), null); - } - showMessage(tr("Done compiling"), tr("Done compiling")); - - Uploader uploader = new UploaderUtils().getUploaderByPreferences(parser.isNoUploadPort()); - if (uploader.requiresAuthorization() && !PreferencesData.has(uploader.getAuthorizationKey())) showError("...", "...", null); - try { - success = new UploaderUtils().upload(data, uploader, suggestedClassName, parser.isDoUseProgrammer(), parser.isNoUploadPort(), warningsAccumulator); - showMessage(tr("Done uploading"), tr("Done uploading")); - } finally { - if (uploader.requiresAuthorization() && !success) { - PreferencesData.remove(uploader.getAuthorizationKey()); - } - } - } catch (Exception e) { - showError(tr("Error while verifying/uploading"), tr("An error occurred while verifying/uploading the sketch"), e); - } - for (String warning : warningsAccumulator) { - System.out.print(tr("Warning")); - System.out.print(": "); - System.out.println(warning); - } - if (!success) showError(tr("Error while uploading"), tr("An error occurred while uploading the sketch"), null); - } else { - - for (String path : parser.getFilenames()) - { - try { - // Editor constructor loads sketch with handleOpenInternal() that - // creates a new Sketch that calls load() in its constructor - // This translates here as: - // SketchData data = new SketchData(file); - // File tempBuildFolder = getBuildFolder(); - // data.load(); - Sketch data = new Sketch(absoluteFile(path)); - - // Sketch.prepare() calls Sketch.ensureExistence() - // Sketch.build(verbose) calls Sketch.ensureExistence() and set progressListener and, finally, calls Compiler.build() - // This translates here as: - // if (!data.getFolder().exists()) showError(...); - // String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose); - if (!data.getFolder().exists()) showError(tr("No sketch"), tr("Can't find the sketch in the specified path"), null); - String suggestedClassName = new Compiler(data).build(null, false); - if (suggestedClassName == null) showError(tr("Error while verifying"), tr("An error occurred while verifying the sketch"), null); - showMessage(tr("Done compiling"), tr("Done compiling")); - } catch (Exception e) { - showError(tr("Error while verifying"), tr("An error occurred while verifying the sketch"), e); - } - } - - } - - // No errors exit gracefully - System.exit(0); - } - else if (parser.isGetPrefMode()) { - dumpPrefs(parser); - } - } - protected static void dumpPrefs(CommandlineParser parser) { if (parser.getGetPref() != null) { String value = PreferencesData.get(parser.getGetPref(), null); @@ -761,29 +607,6 @@ public class BaseNoGui { return PApplet.join(contents, "\n"); } - static public void main(String args[]) throws Exception { - if (args.length == 0) { - showError(tr("No parameters"), tr("No command line parameters found"), null); - } - System.setProperty("java.net.useSystemProxies", "true"); - - Thread deleteFilesOnShutdownThread = new Thread(DeleteFilesOnShutdown.INSTANCE); - deleteFilesOnShutdownThread.setName("DeleteFilesOnShutdown"); - Runtime.getRuntime().addShutdownHook(deleteFilesOnShutdownThread); - - initPlatform(); - - getPlatform().init(); - - initPortableFolder(); - - initParameters(args); - - checkInstallationFolder(); - - init(args); - } - public static void checkInstallationFolder() { if (isIDEInstalledIntoSettingsFolder()) { showError(tr("Incorrect IDE installation folder"), tr("Your copy of the IDE is installed in a subfolder of your settings folder.\nPlease move the IDE to another folder."), 10);