diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 2551a54d64..fb6f1cd820 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -302,7 +302,7 @@ static private void createAndShowGUI(String[] args) { // t6 = System.currentTimeMillis(); // Prevent more than one copy of the PDE from running. - SingleInstance.startServer(base); + new Thread(() -> { SingleInstance.startServer(base); } ).start(); handleWelcomeScreen(base); handleCrustyDisplay(); @@ -485,12 +485,18 @@ static public boolean isCommandLine() { public Base(String[] args) throws Exception { long t1 = System.currentTimeMillis(); - ContributionManager.init(this); + new Thread(() -> { + try { + ContributionManager.init(this); + } catch (Exception e) { + throw new RuntimeException(e); + } + }).start(); long t2 = System.currentTimeMillis(); buildCoreModes(); long t2b = System.currentTimeMillis(); - rebuildContribModes(); + new Thread(this::rebuildContribModes).start(); long t2c = System.currentTimeMillis(); rebuildContribExamples(); @@ -498,7 +504,7 @@ public Base(String[] args) throws Exception { // Needs to happen after the sketchbook folder has been located. // Also relies on the modes to be loaded, so it knows what can be // marked as an example. - Recent.init(this); + new Thread(() -> { Recent.init(this); }).start(); long t4 = System.currentTimeMillis(); String lastModeIdentifier = Preferences.get("mode.last"); //$NON-NLS-1$ @@ -523,7 +529,7 @@ public Base(String[] args) throws Exception { long t5 = System.currentTimeMillis(); // Make sure ThinkDifferent has library examples too - nextMode.rebuildLibraryList(); +// nextMode.rebuildLibraryList(); // Put this after loading the examples, so that building the default file // menu works on Mac OS X (since it needs examplesFolder to be set). @@ -863,7 +869,7 @@ public List getContribTools() { return contribTools; } - + private List toolsToInit = new ArrayList<>(); public void rebuildToolList() { // Only do these once because the list of internal tools will never change if (internalTools == null) { @@ -883,43 +889,12 @@ public void rebuildToolList() { // Only init() these the first time they're loaded if (coreTools == null) { coreTools = ToolContribution.loadAll(Base.getToolsFolder()); - for (Tool tool : coreTools) { - tool.init(this); - } + toolsToInit.addAll(coreTools); } // Reset the contributed tools and re-init() all of them. contribTools = ToolContribution.loadAll(Base.getSketchbookToolsFolder()); - for (Tool tool : contribTools) { - try { - tool.init(this); - - // With the exceptions, we can't call statusError because the window - // isn't completely set up yet. Also not gonna pop up a warning because - // people may still be running different versions of Processing. - - } catch (VerifyError | AbstractMethodError ve) { - System.err.println("\"" + tool.getMenuTitle() + "\" is not " + - "compatible with this version of Processing"); - Messages.err("Incompatible Tool found during tool.init()", ve); - - } catch (NoSuchMethodError nsme) { - System.err.println("\"" + tool.getMenuTitle() + "\" is not " + - "compatible with this version of Processing"); - System.err.println("The " + nsme.getMessage() + " method no longer exists."); - Messages.err("Incompatible Tool found during tool.init()", nsme); - - } catch (NoClassDefFoundError ncdfe) { - System.err.println("\"" + tool.getMenuTitle() + "\" is not " + - "compatible with this version of Processing"); - System.err.println("The " + ncdfe.getMessage() + " class is no longer available."); - Messages.err("Incompatible Tool found during tool.init()", ncdfe); - - } catch (Error | Exception e) { - System.err.println("An error occurred inside \"" + tool.getMenuTitle() + "\""); - e.printStackTrace(); - } - } + toolsToInit.addAll(contribTools); } @@ -928,7 +903,7 @@ protected void initInternalTool(Class toolClass) { final Tool tool = (Tool) toolClass.getDeclaredConstructor().newInstance(); - tool.init(this); + toolsToInit.add(tool); internalTools.add(tool); } catch (Exception e) { @@ -976,12 +951,40 @@ public void populateToolsMenu(JMenu toolsMenu) { toolsMenu.add(manageTools); } + void initTool(Tool tool) { + if(!toolsToInit.contains(tool)) {return;} + try { + tool.init(this); + toolsToInit.remove(tool); + } catch (VerifyError | AbstractMethodError ve) { + System.err.println("\"" + tool.getMenuTitle() + "\" is not " + + "compatible with this version of Processing"); + Messages.err("Incompatible Tool found during tool.init()", ve); + + } catch (NoSuchMethodError nsme) { + System.err.println("\"" + tool.getMenuTitle() + "\" is not " + + "compatible with this version of Processing"); + System.err.println("The " + nsme.getMessage() + " method no longer exists."); + Messages.err("Incompatible Tool found during tool.init()", nsme); + + } catch (NoClassDefFoundError ncdfe) { + System.err.println("\"" + tool.getMenuTitle() + "\" is not " + + "compatible with this version of Processing"); + System.err.println("The " + ncdfe.getMessage() + " class is no longer available."); + Messages.err("Incompatible Tool found during tool.init()", ncdfe); + + } catch (Error | Exception e) { + System.err.println("An error occurred inside \"" + tool.getMenuTitle() + "\""); + e.printStackTrace(); + } + } JMenuItem createToolItem(final Tool tool) { //, Map toolItems) { String title = tool.getMenuTitle(); final JMenuItem item = new JMenuItem(title); item.addActionListener(e -> { try { + initTool(tool); tool.run(); } catch (NoSuchMethodError | NoClassDefFoundError ne) { diff --git a/app/src/processing/app/Processing.kt b/app/src/processing/app/Processing.kt index 6bc6b64a7e..e1b07737a5 100644 --- a/app/src/processing/app/Processing.kt +++ b/app/src/processing/app/Processing.kt @@ -56,7 +56,7 @@ class Processing: SuspendingCliktCommand("processing"){ val subcommand = currentContext.invokedSubcommand if (subcommand == null) { - Start.main(sketches.toTypedArray()) + Base.main(sketches.toTypedArray()) } } } diff --git a/app/src/processing/app/platform/DefaultPlatform.java b/app/src/processing/app/platform/DefaultPlatform.java index 18997755b7..10dc90e2f2 100644 --- a/app/src/processing/app/platform/DefaultPlatform.java +++ b/app/src/processing/app/platform/DefaultPlatform.java @@ -27,7 +27,7 @@ import java.awt.Font; import java.io.File; -import javax.swing.UIManager; +import javax.swing.*; import javax.swing.border.EmptyBorder; import com.formdev.flatlaf.FlatLaf; @@ -115,18 +115,29 @@ public void setLookAndFeel() throws Exception { // (i.e. Nimbus on Linux) with our custom components is badness. // dummy font call so that it's registered for FlatLaf - Font defaultFont = Toolkit.getSansFont(14, Font.PLAIN); - UIManager.put("defaultFont", defaultFont); + new Thread(() -> { + Font defaultFont = Toolkit.getSansFont(14, Font.PLAIN); + UIManager.put("defaultFont", defaultFont); + }).start(); + // pull in FlatLaf.properties from the processing.app.laf folder FlatLaf.registerCustomDefaultsSource("processing.app.laf"); - // start with Light, but updateTheme() will be called soon - UIManager.setLookAndFeel(new FlatLightLaf()); + new Thread(() -> { + // start with Light, but updateTheme() will be called soon + try { + UIManager.setLookAndFeel(new FlatLightLaf()); + } catch (UnsupportedLookAndFeelException e) { + throw new RuntimeException(e); + } + }).start(); // Does not fully remove the gray hairline (probably from a parent // Window object), but is an improvement from the heavier default. - UIManager.put("ToolTip.border", new EmptyBorder(0, 0, 0, 0)); + new Thread(() -> { + UIManager.put("ToolTip.border", new EmptyBorder(0, 0, 0, 0)); + }).start(); /* javax.swing.UIDefaults defaults = UIManager.getDefaults(); diff --git a/app/src/processing/app/ui/Editor.java b/app/src/processing/app/ui/Editor.java index df2440d391..c1250777a1 100644 --- a/app/src/processing/app/ui/Editor.java +++ b/app/src/processing/app/ui/Editor.java @@ -189,7 +189,7 @@ public void windowDeactivated(WindowEvent e) { timer = new Timer(); - buildMenuBar(); + new Thread(this::buildMenuBar).start(); JPanel contentPain = new JPanel(); setContentPane(contentPain); diff --git a/app/src/processing/app/ui/Toolkit.java b/app/src/processing/app/ui/Toolkit.java index 8a5ae418bb..50eaf6a2c9 100644 --- a/app/src/processing/app/ui/Toolkit.java +++ b/app/src/processing/app/ui/Toolkit.java @@ -44,16 +44,19 @@ import java.awt.geom.AffineTransform; import java.awt.geom.GeneralPath; import java.awt.image.ImageObserver; +import java.awt.image.RenderedImage; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; +import java.nio.file.Files; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.regex.Pattern; +import javax.imageio.ImageIO; import javax.swing.Action; import javax.swing.ImageIcon; import javax.swing.JButton; @@ -68,14 +71,12 @@ import javax.swing.text.html.HTMLEditorKit; import javax.swing.text.html.StyleSheet; -import processing.app.Language; -import processing.app.Messages; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.Util; +import processing.app.*; import processing.awt.PGraphicsJava2D; import processing.awt.PShapeJava2D; +import processing.awt.ShimAWT; import processing.core.PApplet; +import processing.core.PImage; import processing.core.PShape; import processing.data.StringDict; import processing.data.StringList; @@ -794,6 +795,7 @@ static private Image svgToImageMult(String xmlStr, int wide, int high) { */ + static public Image svgToImageMult(String xmlStr, int wide, int high, StringDict replacements) { /* for (StringDict.Entry entry : replacements.entries()) { @@ -823,8 +825,25 @@ static private Image svgToImage(String xmlStr, int wide, int high) { pg.setSize(wide, high); pg.smooth(); + + + + pg.beginDraw(); + var cacheKey = (xmlStr + "|" + wide + "x" + high).hashCode(); + var cachePath = Base.getSettingsFolder().toPath().resolve("svg_cache").resolve(String.valueOf(cacheKey) + ".png"); + if(!Base.DEBUG || true){ + if(Files.exists(cachePath)){ + byte[] bytes = PApplet.loadBytes(cachePath.toFile()); + if (bytes == null) { + return null; + } else { + return new ImageIcon(bytes).getImage(); + } + } + } + try { XML xml = XML.parse(xmlStr); PShape shape = new PShapeJava2D(xml); @@ -835,6 +854,12 @@ static private Image svgToImage(String xmlStr, int wide, int high) { } pg.endDraw(); + try { + Files.createDirectories(cachePath.getParent()); + pg.save(cachePath.toString()); + } catch (IOException e) { + e.printStackTrace(); + } return pg.image; } @@ -1361,8 +1386,9 @@ static private Font initFont(String filename, int size) throws IOException, Font Font font = Font.createFont(Font.TRUETYPE_FONT, input); input.close(); - // Register the font to be available for other function calls - GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); + new Thread(() -> { + GraphicsEnvironment.getLocalGraphicsEnvironment().registerFont(font); + }).start(); return font.deriveFont((float) size); } diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index 4fccd1a535..f3dc64af5f 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -6822,28 +6822,9 @@ static public String[] loadStrings(InputStream input) { static public String[] loadStrings(BufferedReader reader) { try { - String[] lines = new String[100]; - int lineCount = 0; - String line; - while ((line = reader.readLine()) != null) { - if (lineCount == lines.length) { - String[] temp = new String[lineCount << 1]; - System.arraycopy(lines, 0, temp, 0, lineCount); - lines = temp; - } - lines[lineCount++] = line; - } + var lines = reader.lines().toArray(String[]::new); reader.close(); - - if (lineCount == lines.length) { - return lines; - } - - // resize array to appropriate amount for these lines - String[] output = new String[lineCount]; - System.arraycopy(lines, 0, output, 0, lineCount); - return output; - + return lines; } catch (IOException e) { e.printStackTrace(); //throw new RuntimeException("Error inside loadStrings()"); diff --git a/java/src/processing/mode/java/JavaTextArea.java b/java/src/processing/mode/java/JavaTextArea.java index ecab00eed1..628a47fdcc 100644 --- a/java/src/processing/mode/java/JavaTextArea.java +++ b/java/src/processing/mode/java/JavaTextArea.java @@ -52,7 +52,9 @@ public class JavaTextArea extends PdeTextArea { public JavaTextArea(TextAreaDefaults defaults, JavaEditor editor) { super(defaults, new JavaInputHandler(editor), editor); - suggestionGenerator = new CompletionGenerator((JavaMode) editor.getMode()); + new Thread(() -> { + suggestionGenerator = new CompletionGenerator((JavaMode) editor.getMode()); + }).start(); tweakMode = false; } diff --git a/java/src/processing/mode/java/PreprocService.java b/java/src/processing/mode/java/PreprocService.java index 410cff02f6..bf144fa542 100644 --- a/java/src/processing/mode/java/PreprocService.java +++ b/java/src/processing/mode/java/PreprocService.java @@ -80,7 +80,7 @@ public class PreprocService { protected final JavaMode javaMode; protected final Sketch sketch; - protected final ASTParser parser = ASTParser.newParser(AST.JLS11); + protected ASTParser parser; private final Thread preprocessingThread; private final BlockingQueue requestQueue = new ArrayBlockingQueue<>(1); @@ -116,6 +116,9 @@ public PreprocService(JavaMode javaMode, Sketch sketch) { * The "main loop" for the background thread that checks for code issues. */ private void mainLoop() { + if(parser == null) { + parser = ASTParser.newParser(AST.JLS11); + } running = true; PreprocSketch prevResult = null; CompletableFuture runningCallbacks = null; diff --git a/java/src/processing/mode/java/debug/Debugger.java b/java/src/processing/mode/java/debug/Debugger.java index 0136793200..03c431ab8b 100644 --- a/java/src/processing/mode/java/debug/Debugger.java +++ b/java/src/processing/mode/java/debug/Debugger.java @@ -111,7 +111,7 @@ public class Debugger { public Debugger(JavaEditor editor) { this.editor = editor; - inspector = new VariableInspector(editor); +// inspector = new VariableInspector(editor); } @@ -206,6 +206,9 @@ public void toggleEnabled() { } else { debugItem.setText(Language.text("menu.debug.enable")); } + if(inspector == null) { + inspector = new VariableInspector(editor); + } inspector.setVisible(enabled); for (Component item : debugMenu.getMenuComponents()) { @@ -297,6 +300,7 @@ public void removeClassLoadListener(ClassLoadListener listener) { public void dispose() { + if(inspector == null) return; inspector.dispose(); }