Skip to content

Commit 824a8b3

Browse files
Improve lazy loading of examples menu (JMenuLazy)
1 parent d350292 commit 824a8b3

File tree

3 files changed

+149
-13
lines changed

3 files changed

+149
-13
lines changed
+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
package cc.arduino.view;
2+
3+
import java.awt.Component;
4+
import java.io.File;
5+
import java.util.LinkedList;
6+
7+
import javax.swing.Icon;
8+
import javax.swing.ImageIcon;
9+
import javax.swing.JMenu;
10+
import javax.swing.JMenuItem;
11+
import javax.swing.JPopupMenu;
12+
import javax.swing.JSeparator;
13+
import javax.swing.event.MenuEvent;
14+
import javax.swing.event.MenuListener;
15+
16+
import processing.app.BaseNoGui;
17+
18+
/**
19+
* Avoid break rendering of menu while load full menu tree in background
20+
* @author Ricardo JL Rufino - ([email protected])
21+
* @date 13 de mai de 2020
22+
*/
23+
public class JMenuLazy extends JMenu {
24+
25+
private LinkedList<Component> components = new LinkedList<>();
26+
27+
private boolean loading = false;
28+
29+
public JMenuLazy(String s) {
30+
super(s);
31+
addMenuListener(new MenuListenerLazy());
32+
}
33+
34+
public void setLoading(boolean loading) {
35+
this.loading = loading;
36+
this.setEnabled(!loading);
37+
38+
File dir = new File(BaseNoGui.getContentFile("lib"), "icons/16x16");
39+
Icon leafIcon = new ImageIcon(new File(dir, "script.png").getAbsolutePath());
40+
this.setIcon(leafIcon);
41+
}
42+
43+
public boolean isLoading() {
44+
return loading;
45+
}
46+
47+
@Override
48+
public Component add(Component c) {
49+
if(isLoading()) {
50+
components.add(c);
51+
return c;
52+
}
53+
return super.add(c);
54+
}
55+
56+
@Override
57+
public JMenuItem add(JMenuItem c) {
58+
if(isLoading()) {
59+
components.add(c);
60+
return c;
61+
}
62+
return super.add(c);
63+
}
64+
65+
@Override
66+
public void addSeparator() {
67+
if(isLoading()) {
68+
components.add(new JPopupMenu.Separator());
69+
return;
70+
}
71+
super.addSeparator();
72+
}
73+
74+
private class MenuListenerLazy implements MenuListener{
75+
76+
@Override
77+
public void menuSelected(MenuEvent e) {
78+
if(!isLoading()) {
79+
if(loading == false) {
80+
if(!components.isEmpty()) {
81+
for (Component component : components) {
82+
if(component instanceof JSeparator) {
83+
JMenuLazy.super.addSeparator();
84+
}else {
85+
JMenuLazy.super.add(component);
86+
87+
}
88+
}
89+
components.clear();
90+
}
91+
}
92+
}
93+
}
94+
95+
@Override
96+
public void menuDeselected(MenuEvent e) {
97+
98+
}
99+
100+
@Override
101+
public void menuCanceled(MenuEvent e) {
102+
103+
}
104+
}
105+
106+
}

app/src/processing/app/Base.java

+38-9
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import cc.arduino.packages.DiscoveryManager;
4141
import cc.arduino.packages.Uploader;
4242
import cc.arduino.view.Event;
43+
import cc.arduino.view.JMenuLazy;
4344
import cc.arduino.view.JMenuUtils;
4445
import cc.arduino.view.SplashScreenHelper;
4546
import com.github.zafarkhaja.semver.Version;
@@ -71,6 +72,7 @@
7172
import java.util.List;
7273
import java.util.Timer;
7374
import java.util.concurrent.Executor;
75+
import java.util.concurrent.ExecutorService;
7476
import java.util.concurrent.Executors;
7577
import java.util.*;
7678
import java.util.logging.Handler;
@@ -90,6 +92,8 @@
9092
* files and images, etc) that comes from that.
9193
*/
9294
public class Base {
95+
96+
private Logger logger;
9397

9498
private static final int RECENT_SKETCHES_MAX_SIZE = 10;
9599

@@ -130,7 +134,7 @@ public class Base {
130134
private final List<JMenuItem> recentSketchesMenuItems = new LinkedList<>();
131135

132136
// Executor to load / reload menus in backgroud.
133-
private Executor menuExecutor = Executors.newCachedThreadPool();
137+
private ExecutorService menuExecutor = Executors.newCachedThreadPool();
134138

135139
static public void main(String args[]) throws Exception {
136140
if (!OSUtils.isWindows()) {
@@ -1176,12 +1180,17 @@ public void actionPerformed(ActionEvent e) {
11761180

11771181
}
11781182

1179-
1180-
protected void rebuildSketchbookMenu(JMenu menu) {
1183+
protected void rebuildSketchbookMenu(JMenuLazy menu) {
1184+
1185+
// Avoid call twice from "Editor.buildMenuBar"
1186+
if(menu.isLoading()) return;
1187+
1188+
menu.setLoading(true); // mark as not enabled
1189+
11811190
menu.removeAll();
1182-
1191+
11831192
// Execute in backgroud thread, no need UI thread becouse no rendering needed
1184-
menuExecutor.execute(() -> {
1193+
menuExecutor.submit(() -> {
11851194

11861195
addSketches(menu, BaseNoGui.getSketchbookFolder());
11871196

@@ -1193,6 +1202,8 @@ protected void rebuildSketchbookMenu(JMenu menu) {
11931202
if (hardwareMenu != null) {
11941203
menu.remove(hardwareMenu);
11951204
}
1205+
1206+
SwingUtilities.invokeLater(() -> menu.setLoading(false));
11961207
});
11971208

11981209
}
@@ -1268,15 +1279,28 @@ public void actionPerformed(ActionEvent event) {
12681279
}
12691280
}
12701281

1271-
public void rebuildExamplesMenu(JMenu menu) {
1282+
public void rebuildExamplesMenu(JMenuLazy menu) {
12721283
if (menu == null) {
12731284
return;
12741285
}
1275-
1286+
1287+
new Throwable().printStackTrace();
1288+
1289+
boolean showDialog = PreferencesData.getBoolean("menu.examples.dialog", true);
1290+
if(showDialog) {
1291+
return;
1292+
}
1293+
1294+
// Avoid call twice from "Editor.buildMenuBar"
1295+
if(menu.isLoading()) return;
1296+
1297+
menu.setLoading(true);
1298+
12761299
menu.removeAll();
12771300

12781301
// Execute in backgroud thread, no need UI thread becouse no rendering needed
12791302
menuExecutor.execute(() -> {
1303+
12801304
// Add examples from distribution "example" folder
12811305
JMenuItem label = new JMenuItem(tr("Built-in Examples"));
12821306
label.setEnabled(false);
@@ -1438,8 +1462,12 @@ public void rebuildExamplesMenu(JMenu menu) {
14381462
addSketchesSubmenu(menu, lib);
14391463
}
14401464
}
1465+
1466+
SwingUtilities.invokeLater(() -> {
1467+
menu.setLoading(false);
1468+
});
14411469
});
1442-
1470+
14431471
}
14441472

14451473
private static String priorPlatformFolder;
@@ -1537,7 +1565,7 @@ protected void onIndexesUpdated() throws Exception {
15371565
public void rebuildBoardsMenu() throws Exception {
15381566
boardsCustomMenus = new LinkedList<>();
15391567

1540-
// Execute in backgroud thread, no need UI thread becouse no rendering needed
1568+
// Execute in backgroud thread, no need UI thread because no rendering needed
15411569
menuExecutor.execute(() -> {
15421570
// The first custom menu is the "Board" selection submenu
15431571
JMenu boardMenu = new JMenu(tr("Board"));
@@ -1660,6 +1688,7 @@ public void actionPerformed(ActionEvent actionevent) {
16601688
menuItemToClick.setSelected(true);
16611689
menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, ""));
16621690
}
1691+
16631692
});
16641693

16651694
}

app/src/processing/app/Editor.java

+5-4
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@
9393
import cc.arduino.packages.Uploader;
9494
import cc.arduino.packages.uploaders.SerialUploader;
9595
import cc.arduino.view.GoToLineNumber;
96+
import cc.arduino.view.JMenuLazy;
9697
import cc.arduino.view.StubMenuListener;
9798
import cc.arduino.view.findreplace.FindReplace;
9899
import jssc.SerialPortException;
@@ -189,8 +190,8 @@ public boolean test(SketchController controller) {
189190
// these menus are shared so that they needn't be rebuilt for all windows
190191
// each time a sketch is created, renamed, or moved.
191192
static JMenu toolbarMenu;
192-
static JMenu sketchbookMenu;
193-
static JMenu examplesMenu;
193+
static JMenuLazy sketchbookMenu;
194+
static JMenuLazy examplesMenu;
194195
static JMenu importMenu;
195196

196197
private static JMenu portMenu;
@@ -600,14 +601,14 @@ private JMenu buildFileMenu() {
600601
fileMenu.add(recentSketchesMenu);
601602

602603
if (sketchbookMenu == null) {
603-
sketchbookMenu = new JMenu(tr("Sketchbook"));
604+
sketchbookMenu = new JMenuLazy(tr("Sketchbook"));
604605
MenuScroller.setScrollerFor(sketchbookMenu);
605606
base.rebuildSketchbookMenu(sketchbookMenu);
606607
}
607608
fileMenu.add(sketchbookMenu);
608609

609610
if (examplesMenu == null) {
610-
examplesMenu = new JMenu(tr("Examples"));
611+
examplesMenu = new JMenuLazy(tr("Examples"));
611612
MenuScroller.setScrollerFor(examplesMenu);
612613
base.rebuildExamplesMenu(examplesMenu);
613614
}

0 commit comments

Comments
 (0)