From f936d59e98956bb4198c5676acf831a138b14664 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Thu, 7 May 2020 16:36:44 -0300 Subject: [PATCH 01/17] improved responsiveness of dialogues: Boards and Library manager (using invokeLater ) --- .../BuiltInCoreIsNewerCheck.java | 4 +- .../contributions/ContributionsSelfCheck.java | 2 +- app/src/processing/app/Base.java | 338 ++++++++++-------- app/src/processing/app/NewBoardListener.java | 8 +- 4 files changed, 185 insertions(+), 167 deletions(-) diff --git a/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java b/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java index d28d735e35f..b894cca767b 100644 --- a/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java +++ b/app/src/cc/arduino/contributions/BuiltInCoreIsNewerCheck.java @@ -85,9 +85,7 @@ private void builtInPackageIsNewerCheck() throws InterruptedException { return; } - while (!base.hasActiveEditor()) { - Thread.sleep(100); - } + base.getWaitActiveEditor(); if (VersionComparator.greaterThan(installedBuiltIn.getParsedVersion(), installedNotBuiltIn.getParsedVersion())) { SwingUtilities.invokeLater(() -> { diff --git a/app/src/cc/arduino/contributions/ContributionsSelfCheck.java b/app/src/cc/arduino/contributions/ContributionsSelfCheck.java index 96fd987b099..614fe1610e6 100644 --- a/app/src/cc/arduino/contributions/ContributionsSelfCheck.java +++ b/app/src/cc/arduino/contributions/ContributionsSelfCheck.java @@ -125,7 +125,7 @@ public void run() { } SwingUtilities.invokeLater(() -> { - Editor ed = base.getActiveEditor(); + Editor ed = base.getWaitActiveEditor(); boolean accessibleIde = PreferencesData.getBoolean("ide.accessible"); if (accessibleIde) { notificationPopup = new NotificationPopup(ed, hyperlinkListener, text, false, this, button1Name, button2Name); diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 34193e07dbf..9b76778c252 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -489,7 +489,7 @@ public Base(String[] args) throws Exception { } installKeyboardInputMap(); - + // Check if there were previously opened sketches to be restored restoreSketches(); @@ -1086,16 +1086,22 @@ public void actionPerformed(ActionEvent e) { protected void rebuildSketchbookMenu(JMenu menu) { menu.removeAll(); - addSketches(menu, BaseNoGui.getSketchbookFolder()); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + addSketches(menu, BaseNoGui.getSketchbookFolder()); - JMenu librariesMenu = JMenuUtils.findSubMenuWithLabel(menu, "libraries"); - if (librariesMenu != null) { - menu.remove(librariesMenu); - } - JMenu hardwareMenu = JMenuUtils.findSubMenuWithLabel(menu, "hardware"); - if (hardwareMenu != null) { - menu.remove(hardwareMenu); - } + JMenu librariesMenu = JMenuUtils.findSubMenuWithLabel(menu, "libraries"); + if (librariesMenu != null) { + menu.remove(librariesMenu); + } + JMenu hardwareMenu = JMenuUtils.findSubMenuWithLabel(menu, "hardware"); + if (hardwareMenu != null) { + menu.remove(hardwareMenu); + } + } + }); } private LibraryList getSortedLibraries() { @@ -1175,168 +1181,175 @@ public void rebuildExamplesMenu(JMenu menu) { } menu.removeAll(); + + SwingUtilities.invokeLater(new Runnable() { + + @Override + public void run() { + // Add examples from distribution "example" folder + JMenuItem label = new JMenuItem(tr("Built-in Examples")); + label.setEnabled(false); + menu.add(label); + boolean found = addSketches(menu, BaseNoGui.getExamplesFolder()); + if (found) { + menu.addSeparator(); + } - // Add examples from distribution "example" folder - JMenuItem label = new JMenuItem(tr("Built-in Examples")); - label.setEnabled(false); - menu.add(label); - boolean found = addSketches(menu, BaseNoGui.getExamplesFolder()); - if (found) { - menu.addSeparator(); - } - - // Libraries can come from 4 locations: collect info about all four - String boardId = null; - String referencedPlatformName = null; - String myArch = null; - TargetPlatform targetPlatform = BaseNoGui.getTargetPlatform(); - if (targetPlatform != null) { - myArch = targetPlatform.getId(); - boardId = BaseNoGui.getTargetBoard().getName(); - String core = BaseNoGui.getBoardPreferences().get("build.core", "arduino"); - if (core.contains(":")) { - String refcore = core.split(":")[0]; - TargetPlatform referencedPlatform = BaseNoGui.getTargetPlatform(refcore, myArch); - if (referencedPlatform != null) { - referencedPlatformName = referencedPlatform.getPreferences().get("name"); + // Libraries can come from 4 locations: collect info about all four + String boardId = null; + String referencedPlatformName = null; + String myArch = null; + TargetPlatform targetPlatform = BaseNoGui.getTargetPlatform(); + if (targetPlatform != null) { + myArch = targetPlatform.getId(); + boardId = BaseNoGui.getTargetBoard().getName(); + String core = BaseNoGui.getBoardPreferences().get("build.core", "arduino"); + if (core.contains(":")) { + String refcore = core.split(":")[0]; + TargetPlatform referencedPlatform = BaseNoGui.getTargetPlatform(refcore, myArch); + if (referencedPlatform != null) { + referencedPlatformName = referencedPlatform.getPreferences().get("name"); + } + } } - } - } - // Divide the libraries into 7 lists, corresponding to the 4 locations - // with the retired IDE libs further divided into their own list, and - // any incompatible sketchbook libs further divided into their own list. - // The 7th list of "other" libraries should always be empty, but serves - // as a safety feature to prevent any library from vanishing. - LibraryList allLibraries = BaseNoGui.librariesIndexer.getInstalledLibraries(); - LibraryList ideLibs = new LibraryList(); - LibraryList retiredIdeLibs = new LibraryList(); - LibraryList platformLibs = new LibraryList(); - LibraryList referencedPlatformLibs = new LibraryList(); - LibraryList sketchbookLibs = new LibraryList(); - LibraryList sketchbookIncompatibleLibs = new LibraryList(); - LibraryList otherLibs = new LibraryList(); - for (UserLibrary lib : allLibraries) { - // Get the library's location - used for sorting into categories - Location location = lib.getLocation(); - // Is this library compatible? - List arch = lib.getArchitectures(); - boolean compatible; - if (myArch == null || arch == null || arch.contains("*")) { - compatible = true; - } else { - compatible = arch.contains(myArch); - } - // IDE Libaries (including retired) - if (location == Location.IDE_BUILTIN) { - if (compatible) { - // only compatible IDE libs are shown - if (lib.getTypes().contains("Retired")) { - retiredIdeLibs.add(lib); + // Divide the libraries into 7 lists, corresponding to the 4 locations + // with the retired IDE libs further divided into their own list, and + // any incompatible sketchbook libs further divided into their own list. + // The 7th list of "other" libraries should always be empty, but serves + // as a safety feature to prevent any library from vanishing. + LibraryList allLibraries = BaseNoGui.librariesIndexer.getInstalledLibraries(); + LibraryList ideLibs = new LibraryList(); + LibraryList retiredIdeLibs = new LibraryList(); + LibraryList platformLibs = new LibraryList(); + LibraryList referencedPlatformLibs = new LibraryList(); + LibraryList sketchbookLibs = new LibraryList(); + LibraryList sketchbookIncompatibleLibs = new LibraryList(); + LibraryList otherLibs = new LibraryList(); + for (UserLibrary lib : allLibraries) { + // Get the library's location - used for sorting into categories + Location location = lib.getLocation(); + // Is this library compatible? + List arch = lib.getArchitectures(); + boolean compatible; + if (myArch == null || arch == null || arch.contains("*")) { + compatible = true; } else { - ideLibs.add(lib); + compatible = arch.contains(myArch); } - } - // Platform Libraries - } else if (location == Location.CORE) { - // all platform libs are assumed to be compatible - platformLibs.add(lib); - // Referenced Platform Libraries - } else if (location == Location.REFERENCED_CORE) { - // all referenced platform libs are assumed to be compatible - referencedPlatformLibs.add(lib); - // Sketchbook Libraries (including incompatible) - } else if (location == Location.SKETCHBOOK) { - if (compatible) { - // libraries promoted from sketchbook (behave as builtin) - if (!lib.getTypes().isEmpty() && lib.getTypes().contains("Arduino") - && lib.getArchitectures().contains("*")) { - ideLibs.add(lib); + // IDE Libaries (including retired) + if (location == Location.IDE_BUILTIN) { + if (compatible) { + // only compatible IDE libs are shown + if (lib.getTypes().contains("Retired")) { + retiredIdeLibs.add(lib); + } else { + ideLibs.add(lib); + } + } + // Platform Libraries + } else if (location == Location.CORE) { + // all platform libs are assumed to be compatible + platformLibs.add(lib); + // Referenced Platform Libraries + } else if (location == Location.REFERENCED_CORE) { + // all referenced platform libs are assumed to be compatible + referencedPlatformLibs.add(lib); + // Sketchbook Libraries (including incompatible) + } else if (location == Location.SKETCHBOOK) { + if (compatible) { + // libraries promoted from sketchbook (behave as builtin) + if (!lib.getTypes().isEmpty() && lib.getTypes().contains("Arduino") + && lib.getArchitectures().contains("*")) { + ideLibs.add(lib); + } else { + sketchbookLibs.add(lib); + } + } else { + sketchbookIncompatibleLibs.add(lib); + } + // Other libraries of unknown type (should never occur) } else { - sketchbookLibs.add(lib); + otherLibs.add(lib); } - } else { - sketchbookIncompatibleLibs.add(lib); } - // Other libraries of unknown type (should never occur) - } else { - otherLibs.add(lib); - } - } - // Add examples from libraries - if (!ideLibs.isEmpty()) { - ideLibs.sort(); - label = new JMenuItem(tr("Examples for any board")); - label.setEnabled(false); - menu.add(label); - } - for (UserLibrary lib : ideLibs) { - addSketchesSubmenu(menu, lib); - } + // Add examples from libraries + if (!ideLibs.isEmpty()) { + ideLibs.sort(); + label = new JMenuItem(tr("Examples for any board")); + label.setEnabled(false); + menu.add(label); + } + for (UserLibrary lib : ideLibs) { + addSketchesSubmenu(menu, lib); + } - if (!retiredIdeLibs.isEmpty()) { - retiredIdeLibs.sort(); - JMenu retired = new JMenu(tr("RETIRED")); - menu.add(retired); - for (UserLibrary lib : retiredIdeLibs) { - addSketchesSubmenu(retired, lib); - } - } + if (!retiredIdeLibs.isEmpty()) { + retiredIdeLibs.sort(); + JMenu retired = new JMenu(tr("RETIRED")); + menu.add(retired); + for (UserLibrary lib : retiredIdeLibs) { + addSketchesSubmenu(retired, lib); + } + } - if (!platformLibs.isEmpty()) { - menu.addSeparator(); - platformLibs.sort(); - label = new JMenuItem(format(tr("Examples for {0}"), boardId)); - label.setEnabled(false); - menu.add(label); - for (UserLibrary lib : platformLibs) { - addSketchesSubmenu(menu, lib); - } - } + if (!platformLibs.isEmpty()) { + menu.addSeparator(); + platformLibs.sort(); + label = new JMenuItem(format(tr("Examples for {0}"), boardId)); + label.setEnabled(false); + menu.add(label); + for (UserLibrary lib : platformLibs) { + addSketchesSubmenu(menu, lib); + } + } - if (!referencedPlatformLibs.isEmpty()) { - menu.addSeparator(); - referencedPlatformLibs.sort(); - label = new JMenuItem(format(tr("Examples for {0}"), referencedPlatformName)); - label.setEnabled(false); - menu.add(label); - for (UserLibrary lib : referencedPlatformLibs) { - addSketchesSubmenu(menu, lib); - } - } + if (!referencedPlatformLibs.isEmpty()) { + menu.addSeparator(); + referencedPlatformLibs.sort(); + label = new JMenuItem(format(tr("Examples for {0}"), referencedPlatformName)); + label.setEnabled(false); + menu.add(label); + for (UserLibrary lib : referencedPlatformLibs) { + addSketchesSubmenu(menu, lib); + } + } - if (!sketchbookLibs.isEmpty()) { - menu.addSeparator(); - sketchbookLibs.sort(); - label = new JMenuItem(tr("Examples from Custom Libraries")); - label.setEnabled(false); - menu.add(label); - for (UserLibrary lib : sketchbookLibs) { - addSketchesSubmenu(menu, lib); - } - } + if (!sketchbookLibs.isEmpty()) { + menu.addSeparator(); + sketchbookLibs.sort(); + label = new JMenuItem(tr("Examples from Custom Libraries")); + label.setEnabled(false); + menu.add(label); + for (UserLibrary lib : sketchbookLibs) { + addSketchesSubmenu(menu, lib); + } + } - if (!sketchbookIncompatibleLibs.isEmpty()) { - sketchbookIncompatibleLibs.sort(); - JMenu incompatible = new JMenu(tr("INCOMPATIBLE")); - MenuScroller.setScrollerFor(incompatible); - menu.add(incompatible); - for (UserLibrary lib : sketchbookIncompatibleLibs) { - addSketchesSubmenu(incompatible, lib); - } - } + if (!sketchbookIncompatibleLibs.isEmpty()) { + sketchbookIncompatibleLibs.sort(); + JMenu incompatible = new JMenu(tr("INCOMPATIBLE")); + MenuScroller.setScrollerFor(incompatible); + menu.add(incompatible); + for (UserLibrary lib : sketchbookIncompatibleLibs) { + addSketchesSubmenu(incompatible, lib); + } + } - if (!otherLibs.isEmpty()) { - menu.addSeparator(); - otherLibs.sort(); - label = new JMenuItem(tr("Examples from Other Libraries")); - label.setEnabled(false); - menu.add(label); - for (UserLibrary lib : otherLibs) { - addSketchesSubmenu(menu, lib); + if (!otherLibs.isEmpty()) { + menu.addSeparator(); + otherLibs.sort(); + label = new JMenuItem(tr("Examples from Other Libraries")); + label.setEnabled(false); + menu.add(label); + for (UserLibrary lib : otherLibs) { + addSketchesSubmenu(menu, lib); + } + } } - } + }); + } private static String priorPlatformFolder; @@ -2486,6 +2499,19 @@ public static DiscoveryManager getDiscoveryManager() { public Editor getActiveEditor() { return activeEditor; } + + public Editor getWaitActiveEditor() { + while (getActiveEditor() == null) { + try { + Thread.sleep(200); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + return getActiveEditor(); + } + + public boolean hasActiveEditor() { return activeEditor != null; diff --git a/app/src/processing/app/NewBoardListener.java b/app/src/processing/app/NewBoardListener.java index 7e0fe61d708..79938b5b92f 100644 --- a/app/src/processing/app/NewBoardListener.java +++ b/app/src/processing/app/NewBoardListener.java @@ -55,13 +55,7 @@ public void propertyChange(PropertyChangeEvent event) { @Override public void run() { - while (base.getActiveEditor() == null) { - try { - Thread.sleep(1000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + base.getWaitActiveEditor(); BaseNoGui.addPropertyChangeListener(this); checkForNewBoardAttached(); } From f2853fe2cd5b661640a41f40fe8b4b7a6bf3daa8 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Thu, 7 May 2020 16:41:24 -0300 Subject: [PATCH 02/17] Ask to re-open sketches, and load other things in backgroud... --- app/src/processing/app/Base.java | 64 ++++++++++++++++++++++++-------- 1 file changed, 49 insertions(+), 15 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 9b76778c252..8e70b809ab4 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -489,15 +489,10 @@ public Base(String[] args) throws Exception { } installKeyboardInputMap(); - + // Check if there were previously opened sketches to be restored restoreSketches(); - // Create a new empty window (will be replaced with any files to be opened) - if (editors.isEmpty()) { - handleNew(); - } - new Thread(new BuiltInCoreIsNewerCheck(this)).start(); // Check for boards which need an additional core @@ -534,13 +529,19 @@ private void installKeyboardInputMap() { * * @throws Exception */ - protected boolean restoreSketches() throws Exception { + protected void restoreSketches() throws Exception { // Iterate through all sketches that were open last time p5 was running. // If !windowPositionValid, then ignore the coordinates found for each. - + // Save the sketch path and window placement for each open sketch int count = PreferencesData.getInteger("last.sketch.count"); - int opened = 0; + + if(count <= 0) { + handleNew(); + return; + } + + ArrayList options = new ArrayList<>(); for (int i = count - 1; i >= 0; i--) { String path = PreferencesData.get("last.sketch" + i + ".path"); if (path == null) { @@ -554,13 +555,46 @@ protected boolean restoreSketches() throws Exception { // path unchanged. } } - int[] location = retrieveSketchLocation("" + i); - // If file did not exist, null will be returned for the Editor - if (handleOpen(new File(path), location, nextEditorLocation(), false, false) != null) { - opened++; - } + + options.add(path); + } + + // Show dialog + ArrayList checkboxList = new ArrayList(); + for (String opt : options) { + JCheckBox box = new JCheckBox(opt); + box.setActionCommand(opt); + box.setSelected(true); + checkboxList.add(box); + } + + int chosenOption = JOptionPane.showConfirmDialog(null, checkboxList.toArray(new Object[checkboxList.size()]), tr("Restore last opened Sketchs ?"), JOptionPane.YES_NO_OPTION); + + if (chosenOption == JOptionPane.YES_OPTION) { + + Runnable runnable = new Runnable() { + public void run() { + try { + for (int j = 0; j < checkboxList.size(); j++) { + JCheckBox checkbox = checkboxList.get(j); + if(checkbox.isSelected()) { + int[] location = retrieveSketchLocation("" + j); + // If file did not exist, null will be returned for the Editor + handleOpen(new File(checkbox.getActionCommand()), location, nextEditorLocation(), false, false); + } + } + + } catch (Exception e) { + e.printStackTrace(); + } + } + }; + + new Thread(runnable).start(); + + }else { + handleNew(); } - return (opened > 0); } /** From 73e80bb1c50e49be6f7cd889ade4e75510f5368f Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Thu, 7 May 2020 19:58:50 -0300 Subject: [PATCH 03/17] fix avoid log4j scan packages for plugins.. --- app/src/log4j2.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/log4j2.xml b/app/src/log4j2.xml index 64f6b8f063f..9213b320841 100644 --- a/app/src/log4j2.xml +++ b/app/src/log4j2.xml @@ -1,5 +1,5 @@ - + From b4c4cd2a46792df0b01620f14295ee742dc87fbd Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Thu, 7 May 2020 21:17:29 -0300 Subject: [PATCH 04/17] rebuildToolbarMenu, rebuildBoardsMenu, in background --- app/src/processing/app/Base.java | 243 +++++++++++++++++-------------- 1 file changed, 133 insertions(+), 110 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 8e70b809ab4..a18379fba39 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -45,6 +45,8 @@ import com.github.zafarkhaja.semver.Version; import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.LogManager; + import processing.app.debug.TargetBoard; import processing.app.debug.TargetPackage; import processing.app.debug.TargetPlatform; @@ -160,6 +162,9 @@ public static boolean isMacOsAboutMenuItemPresent() { } static public void initLogger() { + + LogManager.getLogger(Base.class); // init log4j + Handler consoleHandler = new ConsoleLogger(); consoleHandler.setLevel(Level.ALL); consoleHandler.setFormatter(new LogFormatter("%1$tl:%1$tM:%1$tS [%4$7s] %2$s: %5$s%n")); @@ -1107,14 +1112,20 @@ public void actionPerformed(ActionEvent e) { }); menu.add(item); menu.addSeparator(); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // Add a list of all sketches and subfolders + boolean sketches = addSketches(menu, BaseNoGui.getSketchbookFolder()); + if (sketches) menu.addSeparator(); - // Add a list of all sketches and subfolders - boolean sketches = addSketches(menu, BaseNoGui.getSketchbookFolder()); - if (sketches) menu.addSeparator(); + // Add each of the subfolders of examples directly to the menu + boolean found = addSketches(menu, BaseNoGui.getExamplesFolder()); + if (found) menu.addSeparator(); + } + }); - // Add each of the subfolders of examples directly to the menu - boolean found = addSketches(menu, BaseNoGui.getExamplesFolder()); - if (found) menu.addSeparator(); } @@ -1480,122 +1491,134 @@ protected void onIndexesUpdated() throws Exception { public void rebuildBoardsMenu() throws Exception { boardsCustomMenus = new LinkedList<>(); + + SwingUtilities.invokeLater(new Runnable() { + @Override + public void run() { + // The first custom menu is the "Board" selection submenu + JMenu boardMenu = new JMenu(tr("Board")); + boardMenu.putClientProperty("removeOnWindowDeactivation", true); + MenuScroller.setScrollerFor(boardMenu).setTopFixedCount(1); + + boardMenu.add(new JMenuItem(new AbstractAction(tr("Boards Manager...")) { + public void actionPerformed(ActionEvent actionevent) { + String filterText = ""; + String dropdownItem = ""; + if (actionevent instanceof Event) { + Event e = ((Event) actionevent); + filterText = e.getPayload().get("filterText").toString(); + dropdownItem = e.getPayload().get("dropdownItem").toString(); + } + try { + openBoardsManager(filterText, dropdownItem); + } catch (Exception e) { + //TODO show error + e.printStackTrace(); + } + } + })); + boardsCustomMenus.add(boardMenu); - // The first custom menu is the "Board" selection submenu - JMenu boardMenu = new JMenu(tr("Board")); - boardMenu.putClientProperty("removeOnWindowDeactivation", true); - MenuScroller.setScrollerFor(boardMenu).setTopFixedCount(1); + // If there are no platforms installed we are done + if (BaseNoGui.packages.size() == 0) + return; - boardMenu.add(new JMenuItem(new AbstractAction(tr("Boards Manager...")) { - public void actionPerformed(ActionEvent actionevent) { - String filterText = ""; - String dropdownItem = ""; - if (actionevent instanceof Event) { - Event e = ((Event) actionevent); - filterText = e.getPayload().get("filterText").toString(); - dropdownItem = e.getPayload().get("dropdownItem").toString(); - } - try { - openBoardsManager(filterText, dropdownItem); - } catch (Exception e) { - //TODO show error - e.printStackTrace(); + // Separate "Install boards..." command from installed boards + boardMenu.add(new JSeparator()); + + // Generate custom menus for all platforms + for (TargetPackage targetPackage : BaseNoGui.packages.values()) { + for (TargetPlatform targetPlatform : targetPackage.platforms()) { + for (String customMenuTitle : targetPlatform.getCustomMenus().values()) { + JMenu customMenu = new JMenu(tr(customMenuTitle)); + customMenu.putClientProperty("platform", getPlatformUniqueId(targetPlatform)); + customMenu.putClientProperty("removeOnWindowDeactivation", true); + boardsCustomMenus.add(customMenu); + } + } } - } - })); - boardsCustomMenus.add(boardMenu); - // If there are no platforms installed we are done - if (BaseNoGui.packages.size() == 0) - return; - - // Separate "Install boards..." command from installed boards - boardMenu.add(new JSeparator()); - - // Generate custom menus for all platforms - for (TargetPackage targetPackage : BaseNoGui.packages.values()) { - for (TargetPlatform targetPlatform : targetPackage.platforms()) { - for (String customMenuTitle : targetPlatform.getCustomMenus().values()) { - JMenu customMenu = new JMenu(tr(customMenuTitle)); - customMenu.putClientProperty("platform", getPlatformUniqueId(targetPlatform)); - customMenu.putClientProperty("removeOnWindowDeactivation", true); - boardsCustomMenus.add(customMenu); + List menuItemsToClickAfterStartup = new LinkedList<>(); + + ButtonGroup boardsButtonGroup = new ButtonGroup(); + Map buttonGroupsMap = new HashMap<>(); + + List platformMenus = new ArrayList<>(); + + // Cycle through all packages + for (TargetPackage targetPackage : BaseNoGui.packages.values()) { + // For every package cycle through all platform + for (TargetPlatform targetPlatform : targetPackage.platforms()) { + + // Add a title for each platform + String platformLabel = targetPlatform.getPreferences().get("name"); + if (platformLabel == null) + platformLabel = targetPackage.getId() + "-" + targetPlatform.getId(); + + // add an hint that this core lives in sketchbook + if (targetPlatform.isInSketchbook()) + platformLabel += " (in sketchbook)"; + + JMenu platformBoardsMenu = new JMenu(platformLabel); + MenuScroller.setScrollerFor(platformBoardsMenu); + platformMenus.add(platformBoardsMenu); + + // Cycle through all boards of this platform + for (TargetBoard board : targetPlatform.getBoards().values()) { + if (board.getPreferences().get("hide") != null) + continue; + + try { + JMenuItem item = createBoardMenusAndCustomMenus(boardsCustomMenus, menuItemsToClickAfterStartup, + buttonGroupsMap, + board, targetPlatform, targetPackage); + platformBoardsMenu.add(item); + boardsButtonGroup.add(item); + + } catch (Exception e) { + e.printStackTrace(); + } + } + } } - } - } - - List menuItemsToClickAfterStartup = new LinkedList<>(); - - ButtonGroup boardsButtonGroup = new ButtonGroup(); - Map buttonGroupsMap = new HashMap<>(); - - List platformMenus = new ArrayList<>(); - // Cycle through all packages - for (TargetPackage targetPackage : BaseNoGui.packages.values()) { - // For every package cycle through all platform - for (TargetPlatform targetPlatform : targetPackage.platforms()) { + platformMenus.sort((x,y) -> x.getText().compareToIgnoreCase(y.getText())); - // Add a title for each platform - String platformLabel = targetPlatform.getPreferences().get("name"); - if (platformLabel == null) - platformLabel = targetPackage.getId() + "-" + targetPlatform.getId(); - - // add an hint that this core lives in sketchbook - if (targetPlatform.isInSketchbook()) - platformLabel += " (in sketchbook)"; - - JMenu platformBoardsMenu = new JMenu(platformLabel); - MenuScroller.setScrollerFor(platformBoardsMenu); - platformMenus.add(platformBoardsMenu); + JMenuItem firstBoardItem = null; + if (platformMenus.size() == 1) { + // When just one platform exists, add the board items directly, + // rather than using a submenu + for (Component boardItem : platformMenus.get(0).getMenuComponents()) { + boardMenu.add(boardItem); + if (firstBoardItem == null) + firstBoardItem = (JMenuItem)boardItem; + } + } else { + // For multiple platforms, use submenus + for (JMenu platformMenu : platformMenus) { + if (firstBoardItem == null && platformMenu.getItemCount() > 0) + firstBoardItem = platformMenu.getItem(0); + boardMenu.add(platformMenu); + } + } - // Cycle through all boards of this platform - for (TargetBoard board : targetPlatform.getBoards().values()) { - if (board.getPreferences().get("hide") != null) - continue; - JMenuItem item = createBoardMenusAndCustomMenus(boardsCustomMenus, menuItemsToClickAfterStartup, - buttonGroupsMap, - board, targetPlatform, targetPackage); - platformBoardsMenu.add(item); - boardsButtonGroup.add(item); + if (firstBoardItem == null) { + throw new IllegalStateException("No available boards"); } - } - } - platformMenus.sort((x,y) -> x.getText().compareToIgnoreCase(y.getText())); + // If there is no current board yet (first startup, or selected + // board no longer defined), select first available board. + if (menuItemsToClickAfterStartup.isEmpty()) { + menuItemsToClickAfterStartup.add(firstBoardItem); + } - JMenuItem firstBoardItem = null; - if (platformMenus.size() == 1) { - // When just one platform exists, add the board items directly, - // rather than using a submenu - for (Component boardItem : platformMenus.get(0).getMenuComponents()) { - boardMenu.add(boardItem); - if (firstBoardItem == null) - firstBoardItem = (JMenuItem)boardItem; - } - } else { - // For multiple platforms, use submenus - for (JMenu platformMenu : platformMenus) { - if (firstBoardItem == null && platformMenu.getItemCount() > 0) - firstBoardItem = platformMenu.getItem(0); - boardMenu.add(platformMenu); + for (JMenuItem menuItemToClick : menuItemsToClickAfterStartup) { + menuItemToClick.setSelected(true); + menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); + } } - } - - if (firstBoardItem == null) { - throw new IllegalStateException("No available boards"); - } - - // If there is no current board yet (first startup, or selected - // board no longer defined), select first available board. - if (menuItemsToClickAfterStartup.isEmpty()) { - menuItemsToClickAfterStartup.add(firstBoardItem); - } - - for (JMenuItem menuItemToClick : menuItemsToClickAfterStartup) { - menuItemToClick.setSelected(true); - menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); - } + }); + } private String getPlatformUniqueId(TargetPlatform platform) { From 6fb467cd88c18a411660c883dbbc715a861bc1d0 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Sun, 10 May 2020 19:33:03 -0300 Subject: [PATCH 05/17] Improve startup, use backgroud tread (executor version) --- app/src/processing/app/Base.java | 48 ++++++++++++++------------------ 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index a18379fba39..921712d6646 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -70,6 +70,8 @@ import java.io.*; import java.util.List; import java.util.Timer; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.*; import java.util.logging.Handler; import java.util.logging.Level; @@ -126,6 +128,9 @@ public class Base { private PdeKeywords pdeKeywords; private final List recentSketchesMenuItems = new LinkedList<>(); + + // Executor to load / reload menus in backgroud. + private Executor menuExecutor = Executors.newCachedThreadPool(); static public void main(String args[]) throws Exception { if (!OSUtils.isWindows()) { @@ -1083,14 +1088,10 @@ protected boolean handleQuitEach() { public void rebuildSketchbookMenus() { //System.out.println("async enter"); //new Exception().printStackTrace(); - SwingUtilities.invokeLater(new Runnable() { - public void run() { - //System.out.println("starting rebuild"); - rebuildSketchbookMenu(Editor.sketchbookMenu); - rebuildToolbarMenu(Editor.toolbarMenu); - //System.out.println("done with rebuild"); - } - }); + //System.out.println("starting rebuild"); + rebuildSketchbookMenu(Editor.sketchbookMenu); + rebuildToolbarMenu(Editor.toolbarMenu); + //System.out.println("done with rebuild"); //System.out.println("async exit"); } @@ -1113,9 +1114,8 @@ public void actionPerformed(ActionEvent e) { menu.add(item); menu.addSeparator(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { + // Execute in backgroud thread, no need UI thread becouse no rendering needed + menuExecutor.execute(() -> { // Add a list of all sketches and subfolders boolean sketches = addSketches(menu, BaseNoGui.getSketchbookFolder()); if (sketches) menu.addSeparator(); @@ -1123,7 +1123,6 @@ public void run() { // Add each of the subfolders of examples directly to the menu boolean found = addSketches(menu, BaseNoGui.getExamplesFolder()); if (found) menu.addSeparator(); - } }); } @@ -1131,12 +1130,12 @@ public void run() { protected void rebuildSketchbookMenu(JMenu menu) { menu.removeAll(); - - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { - addSketches(menu, BaseNoGui.getSketchbookFolder()); + // Execute in backgroud thread, no need UI thread becouse no rendering needed + menuExecutor.execute(() -> { + + addSketches(menu, BaseNoGui.getSketchbookFolder()); + JMenu librariesMenu = JMenuUtils.findSubMenuWithLabel(menu, "libraries"); if (librariesMenu != null) { menu.remove(librariesMenu); @@ -1145,8 +1144,8 @@ public void run() { if (hardwareMenu != null) { menu.remove(hardwareMenu); } - } }); + } private LibraryList getSortedLibraries() { @@ -1227,10 +1226,8 @@ public void rebuildExamplesMenu(JMenu menu) { menu.removeAll(); - SwingUtilities.invokeLater(new Runnable() { - - @Override - public void run() { + // Execute in backgroud thread, no need UI thread becouse no rendering needed + menuExecutor.execute(() -> { // Add examples from distribution "example" folder JMenuItem label = new JMenuItem(tr("Built-in Examples")); label.setEnabled(false); @@ -1392,7 +1389,6 @@ public void run() { addSketchesSubmenu(menu, lib); } } - } }); } @@ -1492,9 +1488,8 @@ protected void onIndexesUpdated() throws Exception { public void rebuildBoardsMenu() throws Exception { boardsCustomMenus = new LinkedList<>(); - SwingUtilities.invokeLater(new Runnable() { - @Override - public void run() { + // Execute in backgroud thread, no need UI thread becouse no rendering needed + menuExecutor.execute(() -> { // The first custom menu is the "Board" selection submenu JMenu boardMenu = new JMenu(tr("Board")); boardMenu.putClientProperty("removeOnWindowDeactivation", true); @@ -1616,7 +1611,6 @@ public void actionPerformed(ActionEvent actionevent) { menuItemToClick.setSelected(true); menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); } - } }); } From c9da8cea6d2e098b0a156dc8acbefad36f189643 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Mon, 11 May 2020 16:17:20 -0300 Subject: [PATCH 06/17] Show progress bar in Splash.. --- .../cc/arduino/view/SplashScreenHelper.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/app/src/cc/arduino/view/SplashScreenHelper.java b/app/src/cc/arduino/view/SplashScreenHelper.java index 108c1c8b2f6..b6ebf3672f7 100644 --- a/app/src/cc/arduino/view/SplashScreenHelper.java +++ b/app/src/cc/arduino/view/SplashScreenHelper.java @@ -48,6 +48,8 @@ public class SplashScreenHelper { private final SplashScreen splash; private Rectangle2D.Double splashTextArea; private Graphics2D splashGraphics; + private int progress = 0; + private String text; public SplashScreenHelper(SplashScreen splash) { this.splash = splash; @@ -58,8 +60,19 @@ public SplashScreenHelper(SplashScreen splash) { desktopHints = null; } } + + public void setProgress(int progress) { + this.progress = progress; + splashText(text); + } + + public void splashText(String text, int progress) { + this.progress = progress; + splashText(text); + } public void splashText(String text) { + this.text = text; if (splash == null) { printText(text); return; @@ -76,10 +89,13 @@ public void splashText(String text) { eraseLastStatusText(); drawText(text); + + if(progress > 0) drawProgress(); ensureTextIsDiplayed(); } + private void ensureTextIsDiplayed() { synchronized (SplashScreen.class) { if (splash.isVisible()) { @@ -88,6 +104,14 @@ private void ensureTextIsDiplayed() { } } + + private void drawProgress() { + splashGraphics.setPaint(new Color(0, 100, 104)); + splashGraphics.setStroke(new BasicStroke(2)); + int w = (int)(splashTextArea.getWidth()*(progress/100.0f)); + splashGraphics.drawLine( (int) splashTextArea.getX(), (int) splashTextArea.getY(), (int) splashTextArea.getX() + w, (int) splashTextArea.getY()); + } + private void drawText(String str) { splashGraphics.setPaint(Color.BLACK); FontMetrics metrics = splashGraphics.getFontMetrics(); From a3568b248ce6b7a474b74805ae138f3a14c32f38 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Mon, 11 May 2020 16:18:43 -0300 Subject: [PATCH 07/17] Restore skectch dialog and preferences --- .../arduino/view/preferences/Preferences.java | 11 +++ app/src/processing/app/Base.java | 83 +++++++++++++++---- 2 files changed, 77 insertions(+), 17 deletions(-) diff --git a/app/src/cc/arduino/view/preferences/Preferences.java b/app/src/cc/arduino/view/preferences/Preferences.java index 005d2f83e54..d1f139616ef 100644 --- a/app/src/cc/arduino/view/preferences/Preferences.java +++ b/app/src/cc/arduino/view/preferences/Preferences.java @@ -135,6 +135,7 @@ private void initComponents() { checkUpdatesBox = new javax.swing.JCheckBox(); saveVerifyUploadBox = new javax.swing.JCheckBox(); accessibleIDEBox = new javax.swing.JCheckBox(); + checkRestoreSketch = new javax.swing.JCheckBox(); jLabel1 = new javax.swing.JLabel(); jLabel2 = new javax.swing.JLabel(); scaleSpinner = new javax.swing.JSpinner(); @@ -284,6 +285,9 @@ public void mouseEntered(java.awt.event.MouseEvent evt) { accessibleIDEBox.setText(tr("Use accessibility features")); checkboxesContainer.add(accessibleIDEBox); + + checkRestoreSketch.setText(tr("Ask to restore sketches")); + checkboxesContainer.add(checkRestoreSketch); jLabel1.setText(tr("Interface scale:")); @@ -718,6 +722,7 @@ private void autoScaleCheckBoxItemStateChanged(java.awt.event.ItemEvent evt) {// private javax.swing.JButton browseButton; private javax.swing.JCheckBox checkUpdatesBox; private javax.swing.JCheckBox accessibleIDEBox; + private javax.swing.JCheckBox checkRestoreSketch; private javax.swing.JPanel checkboxesContainer; private javax.swing.JComboBox comboLanguage; private javax.swing.JLabel comboLanguageLabel; @@ -832,6 +837,10 @@ private void savePreferencesData() { PreferencesData.setBoolean("update.check", checkUpdatesBox.isSelected()); PreferencesData.setBoolean("ide.accessible", accessibleIDEBox.isSelected()); + + if(checkRestoreSketch.isSelected()) { + PreferencesData.set("last.sketch.restore", "ask"); + } PreferencesData.set("boardsmanager.additional.urls", additionalBoardsManagerField.getText().replace("\r\n", "\n").replace("\r", "\n").replace("\n", ",")); @@ -912,6 +921,8 @@ private void showPreferencesData() { } accessibleIDEBox.setSelected(PreferencesData.getBoolean("ide.accessible")); + + checkRestoreSketch.setSelected(PreferencesData.get("last.sketch.restore", "ask").equals("ask")); saveVerifyUploadBox.setSelected(PreferencesData.getBoolean("editor.save_on_verify")); diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 921712d6646..3fed6bdfb3a 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -168,6 +168,8 @@ public static boolean isMacOsAboutMenuItemPresent() { static public void initLogger() { + System.setProperty("log4j.dir", BaseNoGui.getSettingsFolder().getAbsolutePath()); + LogManager.getLogger(Base.class); // init log4j Handler consoleHandler = new ConsoleLogger(); @@ -215,8 +217,6 @@ public Base(String[] args) throws Exception { BaseNoGui.initLogger(); - initLogger(); - BaseNoGui.initPlatform(); BaseNoGui.getPlatform().init(); @@ -234,7 +234,8 @@ public Base(String[] args) throws Exception { if (parser.isGuiMode()) { System.out.println("Set log4j store directory " + BaseNoGui.getSettingsFolder().getAbsolutePath()); } - System.setProperty("log4j.dir", BaseNoGui.getSettingsFolder().getAbsolutePath()); + + initLogger(); BaseNoGui.checkInstallationFolder(); @@ -273,7 +274,7 @@ public Base(String[] args) throws Exception { splash = new SplashScreenHelper(null); } - splash.splashText(tr("Loading configuration...")); + splash.splashText(tr("Loading configuration..."), 10); BaseNoGui.initVersion(); @@ -284,12 +285,12 @@ public Base(String[] args) throws Exception { untitledFolder = FileUtils.createTempFolder("untitled" + new Random().nextInt(Integer.MAX_VALUE), ".tmp"); DeleteFilesOnShutdown.add(untitledFolder); - splash.splashText(tr("Initializing packages...")); + splash.splashText(tr("Initializing packages..."), 20); BaseNoGui.initPackages(); parser.getUploadPort().ifPresent(BaseNoGui::selectSerialPort); - splash.splashText(tr("Preparing boards...")); + splash.splashText(tr("Preparing boards..."), 30); if (!isCommandLine()) { rebuildBoardsMenu(); @@ -468,7 +469,7 @@ public Base(String[] args) throws Exception { // No errors exit gracefully System.exit(0); } else if (parser.isGuiMode()) { - splash.splashText(tr("Starting...")); + splash.splashText(tr("Starting..."), 80); for (String path : parser.getFilenames()) { // Correctly resolve relative paths @@ -502,6 +503,8 @@ public Base(String[] args) throws Exception { // Check if there were previously opened sketches to be restored restoreSketches(); + + splash.setProgress(90); // last 10% is not predictable, but ide should open fast from here new Thread(new BuiltInCoreIsNewerCheck(this)).start(); @@ -543,6 +546,14 @@ protected void restoreSketches() throws Exception { // Iterate through all sketches that were open last time p5 was running. // If !windowPositionValid, then ignore the coordinates found for each. + String restoreOption = PreferencesData.get("last.sketch.restore", "ask"); + + // Always New + if(restoreOption.equals("blank")) { + handleNew(); + return; + } + // Save the sketch path and window placement for each open sketch int count = PreferencesData.getInteger("last.sketch.count"); @@ -551,7 +562,7 @@ protected void restoreSketches() throws Exception { return; } - ArrayList options = new ArrayList<>(); + ArrayList options = new ArrayList<>(); for (int i = count - 1; i >= 0; i--) { String path = PreferencesData.get("last.sketch" + i + ".path"); if (path == null) { @@ -566,20 +577,58 @@ protected void restoreSketches() throws Exception { } } - options.add(path); + options.add(new File(path)); } // Show dialog - ArrayList checkboxList = new ArrayList(); - for (String opt : options) { - JCheckBox box = new JCheckBox(opt); - box.setActionCommand(opt); + + JPanel restore = new JPanel(); + restore.setLayout(new BorderLayout()); + JPanel checkBoxPanel = new JPanel(); + checkBoxPanel.setBorder(BorderFactory.createTitledBorder(tr("Select to restore"))); + List checkboxList = new LinkedList<>(); + for (File opt : options) { + JCheckBox box = new JCheckBox(opt.getName()); + box.setActionCommand(opt.getAbsolutePath()); box.setSelected(true); checkboxList.add(box); + checkBoxPanel.add(box); + } + restore.add(checkBoxPanel); + JCheckBox alwaysAskCB = new JCheckBox(tr("Always ask")); + restore.add(alwaysAskCB, BorderLayout.SOUTH); + + int chosenOption; + + if(restoreOption.equals("ask")) { + alwaysAskCB.setSelected(true); + + // Allow set icon on JOptionPane + JFrame frame = new JFrame(); + setIcon(frame); + + chosenOption = JOptionPane.showConfirmDialog(frame, restore, tr("Restore Sketchs ?"), JOptionPane.YES_NO_OPTION); + + }else { // restoreOption = restore + chosenOption = JOptionPane.YES_OPTION; + } + + // Save preferences + if(alwaysAskCB.isSelected()) { + PreferencesData.set("last.sketch.restore", "ask"); + }else { + if(chosenOption == JOptionPane.YES_OPTION) + PreferencesData.set("last.sketch.restore", "restore"); + else { + PreferencesData.set("last.sketch.restore", "blank"); + } + } + + if(chosenOption == JOptionPane.CLOSED_OPTION) { + System.err.println("Exiting..."); + System.exit(0); } - int chosenOption = JOptionPane.showConfirmDialog(null, checkboxList.toArray(new Object[checkboxList.size()]), tr("Restore last opened Sketchs ?"), JOptionPane.YES_NO_OPTION); - if (chosenOption == JOptionPane.YES_OPTION) { Runnable runnable = new Runnable() { @@ -1832,7 +1881,7 @@ public int compare(File file, File file2) { boolean ifound = false; for (File subfolder : files) { - if (!FileUtils.isSCCSOrHiddenFile(subfolder) && subfolder.isDirectory() + if (subfolder.isDirectory() && !FileUtils.isSCCSOrHiddenFile(subfolder) && addSketchesSubmenu(menu, subfolder.getName(), subfolder)) { ifound = true; } @@ -2196,7 +2245,7 @@ static public File selectFolder(String prompt, File folder, Component parent) { /** * Give this Frame an icon. */ - static public void setIcon(Frame frame) { + static public void setIcon(Window frame) { if (OSUtils.isMacOS()) { return; } From d350292d866688cf9f43e3a5a7cdfbd9299cfff5 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 13 May 2020 02:23:51 -0300 Subject: [PATCH 08/17] Fix menu scroller - not trigger events on initialization --- app/src/processing/app/tools/MenuScroller.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/processing/app/tools/MenuScroller.java b/app/src/processing/app/tools/MenuScroller.java index 9e9aacbcafd..b403f12a356 100644 --- a/app/src/processing/app/tools/MenuScroller.java +++ b/app/src/processing/app/tools/MenuScroller.java @@ -289,7 +289,7 @@ public MenuScroller(JPopupMenu menu, int scrollCount, int interval, upItem = new MenuScrollItem(MenuIcon.UP, -1); downItem = new MenuScrollItem(MenuIcon.DOWN, +1); - setScrollCount(scrollCount); + this.scrollCount = scrollCount; setInterval(interval); setTopFixedCount(topFixedCount); setBottomFixedCount(bottomFixedCount); From 824a8b3a6018b8f48fae0773eafed5aff7f6199f Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 13 May 2020 02:26:17 -0300 Subject: [PATCH 09/17] Improve lazy loading of examples menu (JMenuLazy) --- app/src/cc/arduino/view/JMenuLazy.java | 106 +++++++++++++++++++++++++ app/src/processing/app/Base.java | 47 ++++++++--- app/src/processing/app/Editor.java | 9 ++- 3 files changed, 149 insertions(+), 13 deletions(-) create mode 100755 app/src/cc/arduino/view/JMenuLazy.java diff --git a/app/src/cc/arduino/view/JMenuLazy.java b/app/src/cc/arduino/view/JMenuLazy.java new file mode 100755 index 00000000000..763807559bf --- /dev/null +++ b/app/src/cc/arduino/view/JMenuLazy.java @@ -0,0 +1,106 @@ +package cc.arduino.view; + +import java.awt.Component; +import java.io.File; +import java.util.LinkedList; + +import javax.swing.Icon; +import javax.swing.ImageIcon; +import javax.swing.JMenu; +import javax.swing.JMenuItem; +import javax.swing.JPopupMenu; +import javax.swing.JSeparator; +import javax.swing.event.MenuEvent; +import javax.swing.event.MenuListener; + +import processing.app.BaseNoGui; + +/** + * Avoid break rendering of menu while load full menu tree in background + * @author Ricardo JL Rufino - (ricardo.jl.rufino@gmail.com) + * @date 13 de mai de 2020 + */ +public class JMenuLazy extends JMenu { + + private LinkedList components = new LinkedList<>(); + + private boolean loading = false; + + public JMenuLazy(String s) { + super(s); + addMenuListener(new MenuListenerLazy()); + } + + public void setLoading(boolean loading) { + this.loading = loading; + this.setEnabled(!loading); + + File dir = new File(BaseNoGui.getContentFile("lib"), "icons/16x16"); + Icon leafIcon = new ImageIcon(new File(dir, "script.png").getAbsolutePath()); + this.setIcon(leafIcon); + } + + public boolean isLoading() { + return loading; + } + + @Override + public Component add(Component c) { + if(isLoading()) { + components.add(c); + return c; + } + return super.add(c); + } + + @Override + public JMenuItem add(JMenuItem c) { + if(isLoading()) { + components.add(c); + return c; + } + return super.add(c); + } + + @Override + public void addSeparator() { + if(isLoading()) { + components.add(new JPopupMenu.Separator()); + return; + } + super.addSeparator(); + } + + private class MenuListenerLazy implements MenuListener{ + + @Override + public void menuSelected(MenuEvent e) { + if(!isLoading()) { + if(loading == false) { + if(!components.isEmpty()) { + for (Component component : components) { + if(component instanceof JSeparator) { + JMenuLazy.super.addSeparator(); + }else { + JMenuLazy.super.add(component); + + } + } + components.clear(); + } + } + } + } + + @Override + public void menuDeselected(MenuEvent e) { + + } + + @Override + public void menuCanceled(MenuEvent e) { + + } + } + +} diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 3fed6bdfb3a..cbc832cbd0b 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -40,6 +40,7 @@ import cc.arduino.packages.DiscoveryManager; import cc.arduino.packages.Uploader; import cc.arduino.view.Event; +import cc.arduino.view.JMenuLazy; import cc.arduino.view.JMenuUtils; import cc.arduino.view.SplashScreenHelper; import com.github.zafarkhaja.semver.Version; @@ -71,6 +72,7 @@ import java.util.List; import java.util.Timer; import java.util.concurrent.Executor; +import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.*; import java.util.logging.Handler; @@ -90,6 +92,8 @@ * files and images, etc) that comes from that. */ public class Base { + + private Logger logger; private static final int RECENT_SKETCHES_MAX_SIZE = 10; @@ -130,7 +134,7 @@ public class Base { private final List recentSketchesMenuItems = new LinkedList<>(); // Executor to load / reload menus in backgroud. - private Executor menuExecutor = Executors.newCachedThreadPool(); + private ExecutorService menuExecutor = Executors.newCachedThreadPool(); static public void main(String args[]) throws Exception { if (!OSUtils.isWindows()) { @@ -1176,12 +1180,17 @@ public void actionPerformed(ActionEvent e) { } - - protected void rebuildSketchbookMenu(JMenu menu) { + protected void rebuildSketchbookMenu(JMenuLazy menu) { + + // Avoid call twice from "Editor.buildMenuBar" + if(menu.isLoading()) return; + + menu.setLoading(true); // mark as not enabled + menu.removeAll(); - + // Execute in backgroud thread, no need UI thread becouse no rendering needed - menuExecutor.execute(() -> { + menuExecutor.submit(() -> { addSketches(menu, BaseNoGui.getSketchbookFolder()); @@ -1193,6 +1202,8 @@ protected void rebuildSketchbookMenu(JMenu menu) { if (hardwareMenu != null) { menu.remove(hardwareMenu); } + + SwingUtilities.invokeLater(() -> menu.setLoading(false)); }); } @@ -1268,15 +1279,28 @@ public void actionPerformed(ActionEvent event) { } } - public void rebuildExamplesMenu(JMenu menu) { + public void rebuildExamplesMenu(JMenuLazy menu) { if (menu == null) { return; } - + + new Throwable().printStackTrace(); + + boolean showDialog = PreferencesData.getBoolean("menu.examples.dialog", true); + if(showDialog) { + return; + } + + // Avoid call twice from "Editor.buildMenuBar" + if(menu.isLoading()) return; + + menu.setLoading(true); + menu.removeAll(); // Execute in backgroud thread, no need UI thread becouse no rendering needed menuExecutor.execute(() -> { + // Add examples from distribution "example" folder JMenuItem label = new JMenuItem(tr("Built-in Examples")); label.setEnabled(false); @@ -1438,8 +1462,12 @@ public void rebuildExamplesMenu(JMenu menu) { addSketchesSubmenu(menu, lib); } } + + SwingUtilities.invokeLater(() -> { + menu.setLoading(false); + }); }); - + } private static String priorPlatformFolder; @@ -1537,7 +1565,7 @@ protected void onIndexesUpdated() throws Exception { public void rebuildBoardsMenu() throws Exception { boardsCustomMenus = new LinkedList<>(); - // Execute in backgroud thread, no need UI thread becouse no rendering needed + // Execute in backgroud thread, no need UI thread because no rendering needed menuExecutor.execute(() -> { // The first custom menu is the "Board" selection submenu JMenu boardMenu = new JMenu(tr("Board")); @@ -1660,6 +1688,7 @@ public void actionPerformed(ActionEvent actionevent) { menuItemToClick.setSelected(true); menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); } + }); } diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 2ec29c498cb..d2dfef146e9 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -93,6 +93,7 @@ import cc.arduino.packages.Uploader; import cc.arduino.packages.uploaders.SerialUploader; import cc.arduino.view.GoToLineNumber; +import cc.arduino.view.JMenuLazy; import cc.arduino.view.StubMenuListener; import cc.arduino.view.findreplace.FindReplace; import jssc.SerialPortException; @@ -189,8 +190,8 @@ public boolean test(SketchController controller) { // these menus are shared so that they needn't be rebuilt for all windows // each time a sketch is created, renamed, or moved. static JMenu toolbarMenu; - static JMenu sketchbookMenu; - static JMenu examplesMenu; + static JMenuLazy sketchbookMenu; + static JMenuLazy examplesMenu; static JMenu importMenu; private static JMenu portMenu; @@ -600,14 +601,14 @@ private JMenu buildFileMenu() { fileMenu.add(recentSketchesMenu); if (sketchbookMenu == null) { - sketchbookMenu = new JMenu(tr("Sketchbook")); + sketchbookMenu = new JMenuLazy(tr("Sketchbook")); MenuScroller.setScrollerFor(sketchbookMenu); base.rebuildSketchbookMenu(sketchbookMenu); } fileMenu.add(sketchbookMenu); if (examplesMenu == null) { - examplesMenu = new JMenu(tr("Examples")); + examplesMenu = new JMenuLazy(tr("Examples")); MenuScroller.setScrollerFor(examplesMenu); base.rebuildExamplesMenu(examplesMenu); } From a1887df4e5f0f38665e23d9da1d2d3ecd5d345e7 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 13 May 2020 21:21:17 -0300 Subject: [PATCH 10/17] Avoid concurrency error while loading menus in backgroud thread. No call onBoardOrPortChange, because this is called in Base Contructor --- app/src/processing/app/Base.java | 16 ++++++++-------- .../libraries/LibrariesIndexer.java | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index cbc832cbd0b..32d56aaca40 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -129,6 +129,7 @@ public class Base { // actually used are determined by the preferences, which are shared) private List boardsCustomMenus; private List programmerMenus; + private boolean boardsCustomMenusLoading; private PdeKeywords pdeKeywords; private final List recentSketchesMenuItems = new LinkedList<>(); @@ -1284,13 +1285,6 @@ public void rebuildExamplesMenu(JMenuLazy menu) { return; } - new Throwable().printStackTrace(); - - boolean showDialog = PreferencesData.getBoolean("menu.examples.dialog", true); - if(showDialog) { - return; - } - // Avoid call twice from "Editor.buildMenuBar" if(menu.isLoading()) return; @@ -1564,6 +1558,7 @@ protected void onIndexesUpdated() throws Exception { public void rebuildBoardsMenu() throws Exception { boardsCustomMenus = new LinkedList<>(); + boardsCustomMenusLoading = true; // Execute in backgroud thread, no need UI thread because no rendering needed menuExecutor.execute(() -> { @@ -1689,6 +1684,8 @@ public void actionPerformed(ActionEvent actionevent) { menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); } + boardsCustomMenusLoading = false; + }); } @@ -1717,7 +1714,10 @@ public void actionPerformed(ActionEvent actionevent) { BaseNoGui.selectBoard((TargetBoard) getValue("b")); filterVisibilityOfSubsequentBoardMenus(boardsCustomMenus, (TargetBoard) getValue("b"), 1); - onBoardOrPortChange(); + // Avoid concurrency error while loading menus in backgroud thread. + // No call onBoardOrPortChange, because this is called in Base Contructor + if(!boardsCustomMenusLoading) onBoardOrPortChange(); + rebuildImportMenu(Editor.importMenu); rebuildExamplesMenu(Editor.examplesMenu); rebuildProgrammerMenu(); diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index fb0b0c76abe..c6085c67bfb 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -142,7 +142,7 @@ public void setArchitecturePriority(String arch) { priorityComparator = new UserLibraryPriorityComparator(arch); } - public void rescanLibraries() { + public synchronized void rescanLibraries() { // Clear all installed flags installedLibraries.clear(); From fedad2fd7cc5501b40fb529adc319385011aa0ae Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 13 May 2020 22:02:19 -0300 Subject: [PATCH 11/17] JMenu, remove test icon --- app/src/cc/arduino/view/JMenuLazy.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/app/src/cc/arduino/view/JMenuLazy.java b/app/src/cc/arduino/view/JMenuLazy.java index 763807559bf..57670c3f485 100755 --- a/app/src/cc/arduino/view/JMenuLazy.java +++ b/app/src/cc/arduino/view/JMenuLazy.java @@ -34,10 +34,6 @@ public JMenuLazy(String s) { public void setLoading(boolean loading) { this.loading = loading; this.setEnabled(!loading); - - File dir = new File(BaseNoGui.getContentFile("lib"), "icons/16x16"); - Icon leafIcon = new ImageIcon(new File(dir, "script.png").getAbsolutePath()); - this.setIcon(leafIcon); } public boolean isLoading() { From 60f19a8384f7829dbac61399a1d4a10e6d3bf749 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Sun, 17 May 2020 17:03:47 -0300 Subject: [PATCH 12/17] Avoid call rescanLibraries() twice #10228 --- .../cc/arduino/contributions/UpdatableLibraryTest.java | 2 ++ .../arduino/contributions/libraries/LibrariesIndexer.java | 8 ++++++-- arduino-core/src/processing/app/BaseNoGui.java | 3 ++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/app/test/cc/arduino/contributions/UpdatableLibraryTest.java b/app/test/cc/arduino/contributions/UpdatableLibraryTest.java index e06c12710bf..ef3563fb314 100644 --- a/app/test/cc/arduino/contributions/UpdatableLibraryTest.java +++ b/app/test/cc/arduino/contributions/UpdatableLibraryTest.java @@ -47,6 +47,7 @@ public void testUpdatableLibrary() throws Exception { folders.add(new UserLibraryFolder(SD121, Location.SKETCHBOOK)); indexer.setLibrariesFolders(folders); + indexer.rescanLibraries(); sdLib = indexer.getIndex().getInstalled("SD").get(); assertTrue("SD lib is installed", sdLib.isLibraryInstalled()); @@ -74,6 +75,7 @@ public void testUpdatableLibraryWithBundled() throws Exception { folders.add(new UserLibraryFolder(Bridge170, Location.SKETCHBOOK)); indexer.setLibrariesFolders(folders); + indexer.rescanLibraries(); l = indexer.getIndex().getInstalled("Bridge").get(); assertTrue("Bridge lib is installed", l.isLibraryInstalled()); diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index c6085c67bfb..53d6cc2d30f 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -114,9 +114,13 @@ private void parseIndex(File file) throws IOException { } public void setLibrariesFolders(List folders) { - librariesFolders = folders; - rescanLibraries(); + setLibrariesFolders(folders, false); } + + public void setLibrariesFolders(List folders, boolean rescan) { + librariesFolders = folders; + if(rescan) rescanLibraries(); + } public List getLibrariesFolders() { return librariesFolders; diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index c47a82d69b8..552395ccc86 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -674,10 +674,11 @@ static public void onBoardOrPortChange() { // Scan for libraries in each library folder. // Libraries located in the latest folders on the list can override // other libraries with the same name. - librariesIndexer.setLibrariesFolders(librariesFolders); + librariesIndexer.setLibrariesFolders(librariesFolders, false); if (getTargetPlatform() != null) { librariesIndexer.setArchitecturePriority(getTargetPlatform().getId()); } + librariesIndexer.rescanLibraries(); populateImportToLibraryTable(); From 6621f625d82743950e9187521afc37e4085c76c2 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 20 May 2020 21:05:31 -0300 Subject: [PATCH 13/17] Helper class to load menus in backgroud. --- app/src/cc/arduino/view/JMenuLazy.java | 63 ++++++++++++++------------ 1 file changed, 33 insertions(+), 30 deletions(-) diff --git a/app/src/cc/arduino/view/JMenuLazy.java b/app/src/cc/arduino/view/JMenuLazy.java index 57670c3f485..e1398ac9ffa 100755 --- a/app/src/cc/arduino/view/JMenuLazy.java +++ b/app/src/cc/arduino/view/JMenuLazy.java @@ -1,11 +1,8 @@ package cc.arduino.view; import java.awt.Component; -import java.io.File; import java.util.LinkedList; -import javax.swing.Icon; -import javax.swing.ImageIcon; import javax.swing.JMenu; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; @@ -13,73 +10,79 @@ import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; -import processing.app.BaseNoGui; - /** - * Avoid break rendering of menu while load full menu tree in background + * Avoid slow rendering of menu while load full menu tree in background + * * @author Ricardo JL Rufino - (ricardo.jl.rufino@gmail.com) * @date 13 de mai de 2020 */ public class JMenuLazy extends JMenu { - + private LinkedList components = new LinkedList<>(); - + private boolean loading = false; - + public JMenuLazy(String s) { super(s); - addMenuListener(new MenuListenerLazy()); + addMenuListener(menuListener); } public void setLoading(boolean loading) { this.loading = loading; this.setEnabled(!loading); } - + public boolean isLoading() { return loading; } - + @Override public Component add(Component c) { - if(isLoading()) { + if (isLoading()) { components.add(c); return c; } return super.add(c); } - + @Override public JMenuItem add(JMenuItem c) { - if(isLoading()) { + if (isLoading()) { components.add(c); return c; } return super.add(c); } - + @Override public void addSeparator() { - if(isLoading()) { + if (isLoading()) { components.add(new JPopupMenu.Separator()); return; } super.addSeparator(); } - - private class MenuListenerLazy implements MenuListener{ + + public void removeAll() { + super.removeAll(); + synchronized (components) { + components.clear(); + } + }; + + private MenuListener menuListener = new MenuListener() { @Override public void menuSelected(MenuEvent e) { - if(!isLoading()) { - if(loading == false) { - if(!components.isEmpty()) { + if (!isLoading()) { + if (loading == false) { + if (!components.isEmpty()) { for (Component component : components) { - if(component instanceof JSeparator) { + if (component instanceof JSeparator) { JMenuLazy.super.addSeparator(); - }else { + } else { JMenuLazy.super.add(component); - + } } components.clear(); @@ -87,16 +90,16 @@ public void menuSelected(MenuEvent e) { } } } - + @Override public void menuDeselected(MenuEvent e) { - + } - + @Override public void menuCanceled(MenuEvent e) { - + } - } + }; } From d1557311131fa78aae7ed5d19e8dcb61bdd5b299 Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 20 May 2020 21:06:36 -0300 Subject: [PATCH 14/17] PdeKeywords, reload only if need --- .../processing/app/syntax/PdeKeywords.java | 28 +++++++++++++++++-- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/app/src/processing/app/syntax/PdeKeywords.java b/app/src/processing/app/syntax/PdeKeywords.java index 838800b3d5d..c3fb22f707d 100644 --- a/app/src/processing/app/syntax/PdeKeywords.java +++ b/app/src/processing/app/syntax/PdeKeywords.java @@ -45,6 +45,8 @@ public class PdeKeywords { private static final Map KNOWN_TOKEN_TYPES = new HashMap<>(); private static final Pattern ALPHA = Pattern.compile("\\w"); + + private boolean needReload = true; static { KNOWN_TOKEN_TYPES.put("RESERVED_WORD", TokenTypes.RESERVED_WORD); @@ -99,6 +101,23 @@ public void reload() { Base.showError("Problem loading keywords", "Could not load keywords.txt,\nplease re-install Arduino.", e); System.exit(1); } + + needReload = false; + } + + public boolean reloadIfNeed() { + + if(needReload) { + reload(); + return true; + }else { + return false; + } + + } + + public void setNeedReload(boolean needReload) { + this.needReload = needReload; } private void parseKeywordsTxt(File input) throws Exception { @@ -129,6 +148,7 @@ private void parseKeywordsTxt(File input) throws Exception { if (pieces.length >= 3) { parseHTMLReferenceFileName(pieces[2], keyword); } + if (pieces.length >= 4) { parseRSyntaxTextAreaTokenType(pieces[3], keyword); } @@ -173,9 +193,11 @@ private void parseRSyntaxTextAreaTokenType(String tokenTypeAsString, String keyw } private void parseHTMLReferenceFileName(String piece, String keyword) { - String htmlFilename = piece.trim(); - if (htmlFilename.length() > 0) { - keywordToReference.put(keyword, htmlFilename); + if(piece != null && keyword != null && !piece.isEmpty()) { + String htmlFilename = piece.trim(); + if (htmlFilename.length() > 0) { + keywordToReference.put(keyword, htmlFilename); + } } } From c07719d8e629017191f770abd4f81ea46185c71e Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 20 May 2020 21:09:26 -0300 Subject: [PATCH 15/17] fix call rescanLibraries() twice #10228 --- .../arduino/contributions/UpdatableLibraryTest.java | 12 ++++-------- .../contributions/libraries/LibrariesIndexer.java | 12 ++++++------ 2 files changed, 10 insertions(+), 14 deletions(-) diff --git a/app/test/cc/arduino/contributions/UpdatableLibraryTest.java b/app/test/cc/arduino/contributions/UpdatableLibraryTest.java index ef3563fb314..0dab3531cd1 100644 --- a/app/test/cc/arduino/contributions/UpdatableLibraryTest.java +++ b/app/test/cc/arduino/contributions/UpdatableLibraryTest.java @@ -36,8 +36,7 @@ public void testUpdatableLibrary() throws Exception { LibrariesIndexer indexer = new LibrariesIndexer(index_SD_only); BaseNoGui.librariesIndexer = indexer; indexer.parseIndex(); - indexer.setLibrariesFolders(folders); - indexer.rescanLibraries(); + indexer.setLibrariesFoldersAndRescan(folders); ContributedLibrary sdLib = indexer.getIndex().getInstalled("SD").get(); assertTrue("SD lib is installed", sdLib.isLibraryInstalled()); @@ -46,8 +45,7 @@ public void testUpdatableLibrary() throws Exception { assertTrue(ContributionsSelfCheck.checkForUpdatableLibraries()); folders.add(new UserLibraryFolder(SD121, Location.SKETCHBOOK)); - indexer.setLibrariesFolders(folders); - indexer.rescanLibraries(); + indexer.setLibrariesFoldersAndRescan(folders); sdLib = indexer.getIndex().getInstalled("SD").get(); assertTrue("SD lib is installed", sdLib.isLibraryInstalled()); @@ -64,8 +62,7 @@ public void testUpdatableLibraryWithBundled() throws Exception { LibrariesIndexer indexer = new LibrariesIndexer(index_Bridge_only); BaseNoGui.librariesIndexer = indexer; indexer.parseIndex(); - indexer.setLibrariesFolders(folders); - indexer.rescanLibraries(); + indexer.setLibrariesFoldersAndRescan(folders); ContributedLibrary l = indexer.getIndex().getInstalled("Bridge").get(); assertTrue("Bridge lib is installed", l.isLibraryInstalled()); @@ -74,8 +71,7 @@ public void testUpdatableLibraryWithBundled() throws Exception { assertTrue(ContributionsSelfCheck.checkForUpdatableLibraries()); folders.add(new UserLibraryFolder(Bridge170, Location.SKETCHBOOK)); - indexer.setLibrariesFolders(folders); - indexer.rescanLibraries(); + indexer.setLibrariesFoldersAndRescan(folders); l = indexer.getIndex().getInstalled("Bridge").get(); assertTrue("Bridge lib is installed", l.isLibraryInstalled()); diff --git a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java index 53d6cc2d30f..20169af056d 100644 --- a/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java +++ b/arduino-core/src/cc/arduino/contributions/libraries/LibrariesIndexer.java @@ -113,14 +113,14 @@ private void parseIndex(File file) throws IOException { } } - public void setLibrariesFolders(List folders) { - setLibrariesFolders(folders, false); + public void setLibrariesFolders( List folders ) { + this.librariesFolders = folders; } - public void setLibrariesFolders(List folders, boolean rescan) { - librariesFolders = folders; - if(rescan) rescanLibraries(); - } + public void setLibrariesFoldersAndRescan( List folders ) { + setLibrariesFolders(folders); + rescanLibraries(); + } public List getLibrariesFolders() { return librariesFolders; From ef9e504cc05e1579d99e56d58b5a318cae8fe95c Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 20 May 2020 21:11:50 -0300 Subject: [PATCH 16/17] Scan only examples folder - FIX #10235 --- .../app/helpers/filefilters/ExamplesFilter.java | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100755 arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java diff --git a/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java b/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java new file mode 100755 index 00000000000..8b94429e02b --- /dev/null +++ b/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java @@ -0,0 +1,16 @@ +package processing.app.helpers.filefilters; + +import java.io.File; + +public class ExamplesFilter extends OnlyDirs { + + + @Override + public boolean accept( File dir , String name ) { + + if(!super.accept(dir, name)) return false; + + return name.equalsIgnoreCase("example") || name.equalsIgnoreCase("examples") ; + } + +} From d4fb303f20c466b852ae4badb446429fdc2bf73d Mon Sep 17 00:00:00 2001 From: Ricardo JL Rufino Date: Wed, 20 May 2020 23:11:32 -0300 Subject: [PATCH 17/17] Use a Event-Driven model to speed up IDE FIX #10214 #10235 --- app/.classpath | 1 + app/lib/eventbus4j-0.0.1.jar | Bin 0 -> 15310 bytes app/src/processing/app/Base.java | 286 ++++++++++++------ app/src/processing/app/Editor.java | 34 ++- app/src/processing/app/helpers/UIEvents.java | 73 +++++ .../processing/app/syntax/PdeKeywords.java | 4 +- .../src/processing/app/BaseNoGui.java | 2 +- .../helpers/filefilters/ExamplesFilter.java | 2 +- 8 files changed, 301 insertions(+), 101 deletions(-) create mode 100755 app/lib/eventbus4j-0.0.1.jar create mode 100755 app/src/processing/app/helpers/UIEvents.java diff --git a/app/.classpath b/app/.classpath index 27164be5b04..956c4a5c8f2 100644 --- a/app/.classpath +++ b/app/.classpath @@ -54,5 +54,6 @@ + diff --git a/app/lib/eventbus4j-0.0.1.jar b/app/lib/eventbus4j-0.0.1.jar new file mode 100755 index 0000000000000000000000000000000000000000..ba882e56e48ec1499d434c62c5b66eafff9ee488 GIT binary patch literal 15310 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 Oqk35iVt$^80{uTM(;%V% literal 0 HcmV?d00001 diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 32d56aaca40..90e77739d4e 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -43,15 +43,26 @@ import cc.arduino.view.JMenuLazy; import cc.arduino.view.JMenuUtils; import cc.arduino.view.SplashScreenHelper; + import com.github.zafarkhaja.semver.Version; +import com.ricardojlrufino.eventbus.EventBus; +import com.ricardojlrufino.eventbus.EventBusListener; +import com.ricardojlrufino.eventbus.EventDispatcher; +import com.ricardojlrufino.eventbus.EventHandler; +import com.ricardojlrufino.eventbus.EventMessage; +import com.ricardojlrufino.eventbus.dispatcher.DebounceEventDispatcher; +import com.ricardojlrufino.eventbus.dispatcher.SingleThreadEventDispatcher; + import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import processing.app.debug.TargetBoard; import processing.app.debug.TargetPackage; import processing.app.debug.TargetPlatform; import processing.app.helpers.*; +import processing.app.helpers.filefilters.ExamplesFilter; import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyFilesWithExtension; import processing.app.javax.swing.filechooser.FileNameExtensionFilter; @@ -71,13 +82,11 @@ import java.io.*; import java.util.List; import java.util.Timer; -import java.util.concurrent.Executor; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.*; import java.util.logging.Handler; import java.util.logging.Level; -import java.util.logging.Logger; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -93,12 +102,12 @@ */ public class Base { - private Logger logger; - private static final int RECENT_SKETCHES_MAX_SIZE = 10; private static boolean commandLine; public static volatile Base INSTANCE; + + public static Logger log; public static Map FIND_DIALOG_STATE = new HashMap<>(); private final ContributionInstaller contributionInstaller; @@ -129,7 +138,6 @@ public class Base { // actually used are determined by the preferences, which are shared) private List boardsCustomMenus; private List programmerMenus; - private boolean boardsCustomMenusLoading; private PdeKeywords pdeKeywords; private final List recentSketchesMenuItems = new LinkedList<>(); @@ -175,13 +183,14 @@ static public void initLogger() { System.setProperty("log4j.dir", BaseNoGui.getSettingsFolder().getAbsolutePath()); - LogManager.getLogger(Base.class); // init log4j + log = LogManager.getLogger(Base.class); // init log4j + // JAVA UTIL LOGS .... Handler consoleHandler = new ConsoleLogger(); consoleHandler.setLevel(Level.ALL); consoleHandler.setFormatter(new LogFormatter("%1$tl:%1$tM:%1$tS [%4$7s] %2$s: %5$s%n")); - Logger globalLogger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + java.util.logging.Logger globalLogger = java.util.logging.Logger.getLogger(java.util.logging.Logger.GLOBAL_LOGGER_NAME); globalLogger.setLevel(consoleHandler.getLevel()); // Remove default @@ -189,7 +198,7 @@ static public void initLogger() { for(Handler handler : handlers) { globalLogger.removeHandler(handler); } - Logger root = Logger.getLogger(""); + java.util.logging.Logger root = java.util.logging.Logger.getLogger(""); handlers = root.getHandlers(); for(Handler handler : handlers) { root.removeHandler(handler); @@ -197,10 +206,103 @@ static public void initLogger() { globalLogger.addHandler(consoleHandler); - Logger.getLogger("cc.arduino.packages.autocomplete").setParent(globalLogger); - Logger.getLogger("br.com.criativasoft.cpluslibparser").setParent(globalLogger); - Logger.getLogger(Base.class.getPackage().getName()).setParent(globalLogger); + java.util.logging.Logger.getLogger("cc.arduino.packages.autocomplete").setParent(globalLogger); + java.util.logging.Logger.getLogger("br.com.criativasoft.cpluslibparser").setParent(globalLogger); + java.util.logging.Logger.getLogger(Base.class.getPackage().getName()).setParent(globalLogger); + + } + + /** + * Configuration of internal events launched by the application. + * Only certain types of events will need a specific dispatcher, such as those that need a debounce. + * The other types of events do not need a dispatcher, they will use the standard dispatcher {@link SingleThreadEventDispatcher} + */ + public void initEvents() { + + // Avoids call same method multiple time... + EventBus.configDispatcher(UIEvents.MenuBoardSettingsChanged.class, new DebounceEventDispatcher(1000)); + EventBus.configDispatcher(UIEvents.TriggerFixBoardOrPortChange.class, new DebounceEventDispatcher(200)); + + EventBus.addBusListener(new EventBusListener() { + + @Override + public void onError(Exception e, E event, EventHandler handler) { + + BaseNoGui.showWarning("Event Handler Exception", e.getMessage(), e); + + } + + /** + * Called before the event is "scheduled" to run. It is the responsibility of the dispatcher to accept or not the event. + * This method is executed on the same thread as the method that triggered the event, thus allowing tracking. + * NOTE: It may be that events here are not actually executed, as they can be ignored by the dispatcher + */ + @Override + public void beforeDispatch(E event, EventHandler handler, EventDispatcher eventDispatcher) { + +// // Here you can enable to see which methods are launching the events. +// if (event instanceof UIEvents.TriggerFixBoardOrPortChange) { +// EventBusUtils.printStack(event, handler); +// } + } + @Override + public void eventIgnored(E event, EventDispatcher eventDispatcher,String reason) { + + log.debug("[IGNORED] Event: " + event + ", Reason: '"+reason ); + + if (UIEvents.BoardOrPortChange.class == event.getClass()) { + // EventBusUtils.printStack(); + } + + } + + }); + + initEventsHandlers(); + } + + public void initEventsHandlers() { + + // ==== MenuBoardSettingsChanged ==== + // Custom menus from Board clicked. + // This method is also called at the first startup of the menu + EventBus.register(UIEvents.MenuBoardSettingsChanged.class, event -> { + + onBoardOrPortChange(); + + }); + + // There are several places in the IDE that call onBoardOrPortChange indiscriminately, causing poor performance. + // This wind will serve to debounce the method. + EventBus.register(UIEvents.TriggerFixBoardOrPortChange.class, event -> { + + _onBoardOrPortChange(); + + }); + + + // Rebuild Menus. + EventBus.register(UIEvents.LibraryIndexUpdated.class, event -> { + + Base.this.rebuildImportMenu(Editor.importMenu); + Base.this.rebuildExamplesMenu(Editor.examplesMenu); + + }); + + // Update PdeKeywords + EventBus.register(UIEvents.LibraryIndexUpdated.class, event -> { + + boolean reload = getPdeKeywords().reloadIfNeed(); + + if (reload) { + for (Editor editor : editors) { + editor.updateKeywords(getPdeKeywords()); + } + } + + }); + } static protected boolean isCommandLine() { @@ -265,6 +367,9 @@ public Base(String[] args) throws Exception { // Setup the theme coloring fun Theme.init(); System.setProperty("swing.aatext", PreferencesData.get("editor.antialias", "true")); + + // Setup event system + initEvents(); // Set the look and feel before opening the window try { @@ -309,9 +414,6 @@ public Base(String[] args) throws Exception { // Setup board-dependent variables. onBoardOrPortChange(); - pdeKeywords = new PdeKeywords(); - pdeKeywords.reload(); - final GPGDetachedSignatureVerifier gpgDetachedSignatureVerifier = new GPGDetachedSignatureVerifier(); contributionInstaller = new ContributionInstaller(BaseNoGui.getPlatform(), gpgDetachedSignatureVerifier); libraryInstaller = new LibraryInstaller(BaseNoGui.getPlatform(), gpgDetachedSignatureVerifier); @@ -554,7 +656,7 @@ protected void restoreSketches() throws Exception { String restoreOption = PreferencesData.get("last.sketch.restore", "ask"); // Always New - if(restoreOption.equals("blank")) { + if (restoreOption.equals("blank")) { handleNew(); return; } @@ -562,7 +664,7 @@ protected void restoreSketches() throws Exception { // Save the sketch path and window placement for each open sketch int count = PreferencesData.getInteger("last.sketch.count"); - if(count <= 0) { + if (count <= 0) { handleNew(); return; } @@ -605,7 +707,7 @@ protected void restoreSketches() throws Exception { int chosenOption; - if(restoreOption.equals("ask")) { + if (restoreOption.equals("ask")) { alwaysAskCB.setSelected(true); // Allow set icon on JOptionPane @@ -619,17 +721,17 @@ protected void restoreSketches() throws Exception { } // Save preferences - if(alwaysAskCB.isSelected()) { + if (alwaysAskCB.isSelected()) { PreferencesData.set("last.sketch.restore", "ask"); }else { - if(chosenOption == JOptionPane.YES_OPTION) + if (chosenOption == JOptionPane.YES_OPTION) PreferencesData.set("last.sketch.restore", "restore"); else { PreferencesData.set("last.sketch.restore", "blank"); } } - if(chosenOption == JOptionPane.CLOSED_OPTION) { + if (chosenOption == JOptionPane.CLOSED_OPTION) { System.err.println("Exiting..."); System.exit(0); } @@ -641,7 +743,7 @@ public void run() { try { for (int j = 0; j < checkboxList.size(); j++) { JCheckBox checkbox = checkboxList.get(j); - if(checkbox.isSelected()) { + if (checkbox.isSelected()) { int[] location = retrieveSketchLocation("" + j); // If file did not exist, null will be returned for the Editor handleOpen(new File(checkbox.getActionCommand()), location, nextEditorLocation(), false, false); @@ -859,7 +961,7 @@ protected File createNewUntitled() throws IOException { int multiples = index / 26; - if(multiples > 0){ + if (multiples > 0){ newbieName = ((char) ('a' + (multiples-1))) + "" + ((char) ('a' + (index % 26))) + ""; }else{ newbieName = ((char) ('a' + index)) + ""; @@ -1184,7 +1286,7 @@ public void actionPerformed(ActionEvent e) { protected void rebuildSketchbookMenu(JMenuLazy menu) { // Avoid call twice from "Editor.buildMenuBar" - if(menu.isLoading()) return; + if (menu.isLoading()) return; menu.setLoading(true); // mark as not enabled @@ -1233,10 +1335,7 @@ public void rebuildImportMenu(JMenu importMenu) { addLibraryMenuItem.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { Base.this.handleAddLibrary(); - BaseNoGui.librariesIndexer.rescanLibraries(); - Base.this.onBoardOrPortChange(); - Base.this.rebuildImportMenu(Editor.importMenu); - Base.this.rebuildExamplesMenu(Editor.examplesMenu); + Base.this.rescanLibraries(); } }); importMenu.add(addLibraryMenuItem); @@ -1280,13 +1379,29 @@ public void actionPerformed(ActionEvent event) { } } + /** + * Rescan libraries in backgroud. + * Fire: {@link LibraryIndexUpdated} + */ + protected void rescanLibraries() { + + menuExecutor.execute(new Runnable() { + @Override + public void run() { + BaseNoGui.librariesIndexer.rescanLibraries(); + EventBus.notify(new UIEvents.LibraryIndexUpdated()); + } + }); + + } + public void rebuildExamplesMenu(JMenuLazy menu) { if (menu == null) { return; } // Avoid call twice from "Editor.buildMenuBar" - if(menu.isLoading()) return; + if (menu.isLoading()) return; menu.setLoading(true); @@ -1465,30 +1580,40 @@ public void rebuildExamplesMenu(JMenuLazy menu) { } private static String priorPlatformFolder; - private static boolean newLibraryImported; - + + /** + * Trigger: {@link UIEvents.LibraryIndexUpdated} and {@link UIEvents.BoardOrPortChange} + */ public void onBoardOrPortChange() { - BaseNoGui.onBoardOrPortChange(); + EventBus.notify(new UIEvents.TriggerFixBoardOrPortChange()); + } + // this will be called from: UIEvents.TriggerFixBoardOrPortChange + private void _onBoardOrPortChange() { + // reload keywords when package/platform changes TargetPlatform tp = BaseNoGui.getTargetPlatform(); + + log.debug("BoardOrPortChange : board = {}" , tp.getId()); + if (tp != null) { String platformFolder = tp.getFolder().getAbsolutePath(); - if (priorPlatformFolder == null || !priorPlatformFolder.equals(platformFolder) || newLibraryImported) { - pdeKeywords = new PdeKeywords(); - pdeKeywords.reload(); + if (priorPlatformFolder == null || !priorPlatformFolder.equals(platformFolder)) { priorPlatformFolder = platformFolder; - newLibraryImported = false; - for (Editor editor : editors) { - editor.updateKeywords(pdeKeywords); - } + getPdeKeywords().setNeedReload(true); } } - - // Update editors status bar - for (Editor editor : editors) { - editor.onBoardOrPortChange(); - } + + // TODO: Here it would be better to load it in the background. + // For some listeners are only interested in changing the board, not in libraries. + BaseNoGui.onBoardOrPortChange(); + + // Notify interested parties such as: rebuildExamplesMenu | PdeKeywords.reload() + EventBus.notify(new UIEvents.LibraryIndexUpdated()); + + // NOTE Before events: 'for' in editors[i].onBoardOrPortChange(); + EventBus.notify(new UIEvents.BoardOrPortChange()); + } public void openLibraryManager(final String filterText, String dropdownItem) { @@ -1518,10 +1643,8 @@ protected void onIndexesUpdated() throws Exception { // Manager dialog is modal, waits here until closed //handleAddLibrary(); - newLibraryImported = true; + getPdeKeywords().setNeedReload(true); onBoardOrPortChange(); - rebuildImportMenu(Editor.importMenu); - rebuildExamplesMenu(Editor.examplesMenu); } public void openBoardsManager(final String filterText, String dropdownItem) throws Exception { @@ -1558,8 +1681,7 @@ protected void onIndexesUpdated() throws Exception { public void rebuildBoardsMenu() throws Exception { boardsCustomMenus = new LinkedList<>(); - boardsCustomMenusLoading = true; - + // Execute in backgroud thread, no need UI thread because no rendering needed menuExecutor.execute(() -> { // The first custom menu is the "Board" selection submenu @@ -1684,8 +1806,6 @@ public void actionPerformed(ActionEvent actionevent) { menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); } - boardsCustomMenusLoading = false; - }); } @@ -1711,15 +1831,12 @@ private JRadioButtonMenuItem createBoardMenusAndCustomMenus( @SuppressWarnings("serial") Action action = new AbstractAction(board.getName()) { public void actionPerformed(ActionEvent actionevent) { + BaseNoGui.selectBoard((TargetBoard) getValue("b")); + filterVisibilityOfSubsequentBoardMenus(boardsCustomMenus, (TargetBoard) getValue("b"), 1); - // Avoid concurrency error while loading menus in backgroud thread. - // No call onBoardOrPortChange, because this is called in Base Contructor - if(!boardsCustomMenusLoading) onBoardOrPortChange(); - - rebuildImportMenu(Editor.importMenu); - rebuildExamplesMenu(Editor.examplesMenu); + onBoardOrPortChange(); rebuildProgrammerMenu(); } }; @@ -1743,8 +1860,11 @@ public void actionPerformed(ActionEvent actionevent) { @SuppressWarnings("serial") Action subAction = new AbstractAction(tr(boardCustomMenu.get(customMenuOption))) { public void actionPerformed(ActionEvent e) { + PreferencesData.set("custom_" + menuId, ((List) getValue("board")).get(0).getId() + "_" + getValue("custom_menu_option")); - onBoardOrPortChange(); + + EventBus.notify(new UIEvents.MenuBoardSettingsChanged(((List) getValue("board")).get(0), (String) getValue("custom_menu_option"))); + } }; List boards = (List) subAction.getValue("board"); @@ -1773,7 +1893,7 @@ public void actionPerformed(ActionEvent e) { return item; } - + private void filterVisibilityOfSubsequentBoardMenus(List boardsCustomMenus, TargetBoard board, int fromIndex) { for (int i = fromIndex; i < boardsCustomMenus.size(); i++) { @@ -1919,7 +2039,22 @@ && addSketchesSubmenu(menu, subfolder.getName(), subfolder)) { } private boolean addSketchesSubmenu(JMenu menu, UserLibrary lib) { - return addSketchesSubmenu(menu, lib.getName(), lib.getInstalledFolder()); + + JMenu submenu = new JMenu(lib.getName()); + + // Compatibility mode: not all community libraries are following the specification, look for common names found. + File[] list = lib.getInstalledFolder().listFiles(new ExamplesFilter()); + + // By spec only exist 1 Examples folder, on top level. + if (list.length > 0) { + if (addSketches(submenu, list[0])) { + menu.add(submenu); + MenuScroller.setScrollerFor(submenu); + return true; + } + } + + return false; } private boolean addSketchesSubmenu(JMenu menu, String name, File folder) { @@ -1986,34 +2121,6 @@ public void actionPerformed(ActionEvent e) { return found; } - protected void addLibraries(JMenu menu, LibraryList libs) throws IOException { - - LibraryList list = new LibraryList(libs); - list.sort(); - - for (UserLibrary lib : list) { - @SuppressWarnings("serial") - AbstractAction action = new AbstractAction(lib.getName()) { - public void actionPerformed(ActionEvent event) { - UserLibrary l = (UserLibrary) getValue("library"); - try { - activeEditor.getSketchController().importLibrary(l); - } catch (IOException e) { - showWarning(tr("Error"), format("Unable to list header files in {0}", l.getSrcFolder()), e); - } - } - }; - action.putValue("library", lib); - - // Add new element at the bottom - JMenuItem item = new JMenuItem(action); - item.putClientProperty("library", lib); - menu.add(item); - - // XXX: DAM: should recurse here so that library folders can be nested - } - } - /** * Given a folder, return a list of the header files in that folder (but not * the header files in its sub-folders, as those should be included from @@ -2319,7 +2426,7 @@ static public void showReference(String prefix, String filename) { if (!referenceFile.exists()) referenceFile = new File(referenceFolder, filename + ".html"); - if(referenceFile.exists()){ + if (referenceFile.exists()){ openURL(referenceFile.getAbsolutePath()); }else{ showWarning(tr("Problem Opening URL"), format(tr("Could not open the URL\n{0}"), referenceFile), null); @@ -2616,7 +2723,7 @@ public void handleAddLibrary() { // FIXME error when importing. ignoring :( } finally { // delete zip created temp folder, if exists - newLibraryImported = true; + getPdeKeywords().setNeedReload(true); FileUtils.recursiveDelete(tmpFolder); } } @@ -2651,6 +2758,7 @@ public List getEditors() { } public PdeKeywords getPdeKeywords() { + if (pdeKeywords == null) pdeKeywords = new PdeKeywords() ; // make method safe, while load in backgroud.. return pdeKeywords; } diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index d2dfef146e9..2f84b4fd240 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -80,12 +80,11 @@ import javax.swing.event.MenuEvent; import javax.swing.event.MenuListener; import javax.swing.text.BadLocationException; -import javax.swing.text.Document; -import javax.swing.text.Element; import org.fife.ui.rsyntaxtextarea.folding.FoldManager; import com.jcraft.jsch.JSchException; +import com.ricardojlrufino.eventbus.EventBus; import cc.arduino.CompilerProgressListener; import cc.arduino.packages.BoardPort; @@ -105,6 +104,7 @@ import processing.app.helpers.OSUtils; import processing.app.helpers.PreferencesMapException; import processing.app.helpers.StringReplacer; +import processing.app.helpers.UIEvents; import processing.app.legacy.PApplet; import processing.app.syntax.PdeKeywords; import processing.app.syntax.SketchTextArea; @@ -382,6 +382,25 @@ public void windowDeactivated(WindowEvent e) { // default the console output to the last opened editor EditorConsole.setCurrentEditorConsole(console); + + // Init EventBus handlers + registerEventBus(); + } + + + private void registerEventBus() { + + EventBus.register(this, UIEvents.BoardOrPortChange.class, event -> { + onBoardOrPortChange(); + }); + + } + + @Override + public void dispose() { + super.dispose(); + EventBus.unregisterHandlers(this); + EventBus.notify(new UIEvents.EditorClosed()); } @@ -610,7 +629,6 @@ private JMenu buildFileMenu() { if (examplesMenu == null) { examplesMenu = new JMenuLazy(tr("Examples")); MenuScroller.setScrollerFor(examplesMenu); - base.rebuildExamplesMenu(examplesMenu); } fileMenu.add(examplesMenu); @@ -1004,7 +1022,7 @@ private void addInternalTools(JMenu menu) { private void selectSerialPort(String name) { - if(portMenu == null) { + if (portMenu == null) { System.out.println(tr("serialMenu is null")); return; } @@ -2167,8 +2185,8 @@ public void run() { } public void handleSerial() { - if(serialPlotter != null) { - if(serialPlotter.isClosed()) { + if (serialPlotter != null) { + if (serialPlotter.isClosed()) { serialPlotter = null; } else { statusError(tr("Serial monitor not available while plotter is open")); @@ -2277,8 +2295,8 @@ public void handleSerial() { } public void handlePlotter() { - if(serialMonitor != null) { - if(serialMonitor.isClosed()) { + if (serialMonitor != null) { + if (serialMonitor.isClosed()) { serialMonitor = null; } else { statusError(tr("Plotter not available while serial monitor is open")); diff --git a/app/src/processing/app/helpers/UIEvents.java b/app/src/processing/app/helpers/UIEvents.java new file mode 100755 index 00000000000..6f6e234cfec --- /dev/null +++ b/app/src/processing/app/helpers/UIEvents.java @@ -0,0 +1,73 @@ +/* -*- mode: java; c-basic-offset: 2; indent-tabs-mode: nil -*- */ + +/* + PdeKeywords - handles text coloring and links to html reference + Part of the Processing project - http://processing.org + + Copyright (c) 2004-06 Ben Fry and Casey Reas + Copyright (c) 2001-04 Massachusetts Institute of Technology + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +package processing.app.helpers; + +import com.ricardojlrufino.eventbus.EventMessage; + +import processing.app.debug.TargetBoard; + +/** + * Events for UI Interface. + * + * @author Ricardo JL Rufino - (ricardo.jl.rufino@gmail.com) + * @date 21 de mai de 2020 + */ +public interface UIEvents { + + public static class BoardOrPortChange implements EventMessage { } + + public static class LibraryIndexUpdated implements EventMessage {} + + public static class PlatformChage implements EventMessage {} + + public static class EditorClosed implements EventMessage {} + + /** + * Please do not use this event. It should only be used internally by the + * Base.onBoardOrPortChange method. Use: {@link BoardOrPortChange} + **/ + public static class TriggerFixBoardOrPortChange implements EventMessage { + } + + public static class MenuBoardSettingsChanged implements EventMessage { + private String custosOption; + private TargetBoard board; + + public MenuBoardSettingsChanged(TargetBoard board, String custosOption) { + this.board = board; + this.custosOption = custosOption; + } + + public TargetBoard getBoard() { + return board; + } + + public String getCustosOption() { + return custosOption; + } + + } + +} diff --git a/app/src/processing/app/syntax/PdeKeywords.java b/app/src/processing/app/syntax/PdeKeywords.java index c3fb22f707d..4fa394af067 100644 --- a/app/src/processing/app/syntax/PdeKeywords.java +++ b/app/src/processing/app/syntax/PdeKeywords.java @@ -107,7 +107,7 @@ public void reload() { public boolean reloadIfNeed() { - if(needReload) { + if (needReload) { reload(); return true; }else { @@ -193,7 +193,7 @@ private void parseRSyntaxTextAreaTokenType(String tokenTypeAsString, String keyw } private void parseHTMLReferenceFileName(String piece, String keyword) { - if(piece != null && keyword != null && !piece.isEmpty()) { + if (piece != null && keyword != null && !piece.isEmpty()) { String htmlFilename = piece.trim(); if (htmlFilename.length() > 0) { keywordToReference.put(keyword, htmlFilename); diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index 552395ccc86..4cf07691bb1 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -674,7 +674,7 @@ static public void onBoardOrPortChange() { // Scan for libraries in each library folder. // Libraries located in the latest folders on the list can override // other libraries with the same name. - librariesIndexer.setLibrariesFolders(librariesFolders, false); + librariesIndexer.setLibrariesFolders(librariesFolders); if (getTargetPlatform() != null) { librariesIndexer.setArchitecturePriority(getTargetPlatform().getId()); } diff --git a/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java b/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java index 8b94429e02b..8bf90e699c6 100755 --- a/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java +++ b/arduino-core/src/processing/app/helpers/filefilters/ExamplesFilter.java @@ -8,7 +8,7 @@ public class ExamplesFilter extends OnlyDirs { @Override public boolean accept( File dir , String name ) { - if(!super.accept(dir, name)) return false; + if (!super.accept(dir, name)) return false; return name.equalsIgnoreCase("example") || name.equalsIgnoreCase("examples") ; }