From 0096b3878191696580e167ce71a330fd228ecc40 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 8 Mar 2019 10:08:22 +0100 Subject: [PATCH 1/5] Refactor boardMenu creation This commit is part of https://github.com/arduino/Arduino/pull/7120 by @sandeepmistry --- app/src/processing/app/Base.java | 33 +++++++++++++++++++++++++------- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 62ebfc2acaf..ceae0714e9e 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -117,6 +117,8 @@ public class Base { List editors = Collections.synchronizedList(new ArrayList()); Editor activeEditor; + private static JMenu boardMenu; + // these menus are shared so that the board and serial port selections // are the same for all windows (since the board and serial port that are // actually used are determined by the preferences, which are shared) @@ -1313,6 +1315,28 @@ public void rebuildExamplesMenu(JMenu menu) { private static String priorPlatformFolder; private static boolean newLibraryImported; + public void selectTargetBoard(TargetBoard targetBoard) { + for (int i = 0; i < boardMenu.getItemCount(); i++) { + JMenuItem menuItem = boardMenu.getItem(i); + if (!(menuItem instanceof JRadioButtonMenuItem)) { + continue; + } + + JRadioButtonMenuItem radioButtonMenuItem = ((JRadioButtonMenuItem) menuItem); + if (targetBoard.getName().equals(radioButtonMenuItem.getText())) { + radioButtonMenuItem.setSelected(true); + break; + } + } + + BaseNoGui.selectBoard(targetBoard); + filterVisibilityOfSubsequentBoardMenus(boardsCustomMenus, targetBoard, 1); + + onBoardOrPortChange(); + rebuildImportMenu(Editor.importMenu); + rebuildExamplesMenu(Editor.examplesMenu); + } + public void onBoardOrPortChange() { BaseNoGui.onBoardOrPortChange(); @@ -1406,7 +1430,7 @@ public void rebuildBoardsMenu() throws Exception { boardsCustomMenus = new LinkedList<>(); // The first custom menu is the "Board" selection submenu - JMenu boardMenu = new JMenu(tr("Board")); + boardMenu = new JMenu(tr("Board")); boardMenu.putClientProperty("removeOnWindowDeactivation", true); MenuScroller.setScrollerFor(boardMenu).setTopFixedCount(1); @@ -1512,12 +1536,7 @@ 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); - - onBoardOrPortChange(); - rebuildImportMenu(Editor.importMenu); - rebuildExamplesMenu(Editor.examplesMenu); + selectTargetBoard((TargetBoard) getValue("b")); } }; action.putValue("b", board); From 94f6bb5ebbba4d6dd0ce03eaac9a01b32194cdd5 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Wed, 6 Mar 2019 18:47:20 +0100 Subject: [PATCH 2/5] Add per-session recently used boards list The list appears at the top of Board submenu Boards are also reachable via a CTRL+SHIFT+number (starting from 1) --- app/src/processing/app/Base.java | 69 ++++++++++++++++--- .../src/processing/app/BaseNoGui.java | 13 ++++ 2 files changed, 72 insertions(+), 10 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index ceae0714e9e..59c8b160377 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -118,6 +118,11 @@ public class Base { Editor activeEditor; private static JMenu boardMenu; + private static ButtonGroup boardsButtonGroup; + private static ButtonGroup recentBoardsButtonGroup; + private static Map buttonGroupsMap; + private static List menuItemsToClickAfterStartup; + private static MenuScroller boardMenuScroller; // these menus are shared so that the board and serial port selections // are the same for all windows (since the board and serial port that are @@ -1335,6 +1340,41 @@ public void selectTargetBoard(TargetBoard targetBoard) { onBoardOrPortChange(); rebuildImportMenu(Editor.importMenu); rebuildExamplesMenu(Editor.examplesMenu); + try { + rebuildRecentBoardsMenu(); + } catch (Exception e) { + // fail silently + } + } + + public void rebuildRecentBoardsMenu() throws Exception { + + Enumeration btns = recentBoardsButtonGroup.getElements(); + while (btns.hasMoreElements()) { + AbstractButton x = btns.nextElement(); + if (x.isSelected()) { + return; + } + } + btns = recentBoardsButtonGroup.getElements(); + while (btns.hasMoreElements()) { + AbstractButton x = btns.nextElement(); + boardMenu.remove(x); + } + int index = 0; + for (TargetBoard board : BaseNoGui.getRecentlyUsedBoards()) { + JMenuItem item = createBoardMenusAndCustomMenus(boardsCustomMenus, menuItemsToClickAfterStartup, + buttonGroupsMap, + board, board.getContainerPlatform(), board.getContainerPlatform().getContainerPackage()); + boardMenu.insert(item, 3); + item.setAccelerator(KeyStroke.getKeyStroke('0' + index, + Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | + ActionEvent.SHIFT_MASK)); + recentBoardsButtonGroup.add(item); + boardsButtonGroup.add(item); + index ++; + } + boardMenuScroller.setTopFixedCount(3 + index); } public void onBoardOrPortChange() { @@ -1432,7 +1472,8 @@ public void rebuildBoardsMenu() throws Exception { // The first custom menu is the "Board" selection submenu boardMenu = new JMenu(tr("Board")); boardMenu.putClientProperty("removeOnWindowDeactivation", true); - MenuScroller.setScrollerFor(boardMenu).setTopFixedCount(1); + boardMenuScroller = MenuScroller.setScrollerFor(boardMenu); + boardMenuScroller.setTopFixedCount(1); boardMenu.add(new JMenuItem(new AbstractAction(tr("Boards Manager...")) { public void actionPerformed(ActionEvent actionevent) { @@ -1472,21 +1513,26 @@ public void actionPerformed(ActionEvent actionevent) { boardsCustomMenus.add(customMenu); } - List menuItemsToClickAfterStartup = new LinkedList<>(); + menuItemsToClickAfterStartup = new LinkedList<>(); + boardsButtonGroup = new ButtonGroup(); + recentBoardsButtonGroup = new ButtonGroup(); + buttonGroupsMap = new HashMap<>(); - ButtonGroup boardsButtonGroup = new ButtonGroup(); - Map buttonGroupsMap = new HashMap<>(); + if (BaseNoGui.getRecentlyUsedBoards() != null) { + JMenuItem recentLabel = new JMenuItem(tr("Recently used boards")); + recentLabel.setEnabled(false); + boardMenu.add(recentLabel); + rebuildRecentBoardsMenu(); + //rebuildRecentBoardsMenu(null); + } // Cycle through all packages - boolean first = true; for (TargetPackage targetPackage : BaseNoGui.packages.values()) { // For every package cycle through all platform for (TargetPlatform targetPlatform : targetPackage.platforms()) { // Add a separator from the previous platform - if (!first) - boardMenu.add(new JSeparator()); - first = false; + boardMenu.add(new JSeparator()); // Add a title for each platform String platformLabel = targetPlatform.getPreferences().get("name"); @@ -1552,6 +1598,9 @@ public void actionPerformed(ActionEvent actionevent) { for (final String menuId : customMenus.keySet()) { String title = customMenus.get(menuId); JMenu menu = getBoardCustomMenu(tr(title)); + if (menu == null) { + continue; + } if (board.hasMenu(menuId)) { PreferencesMap boardCustomMenu = board.getMenuLabels(menuId); @@ -1614,13 +1663,13 @@ private static boolean ifThereAreVisibleItemsOn(JMenu menu) { return false; } - private JMenu getBoardCustomMenu(String label) throws Exception { + private JMenu getBoardCustomMenu(String label) { for (JMenu menu : boardsCustomMenus) { if (label.equals(menu.getText())) { return menu; } } - throw new Exception("Custom menu not found!"); + return null; } public List getProgrammerMenus() { diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index 0a58769712a..ee38975a7b7 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -915,6 +915,12 @@ static public void saveFile(String str, File file) throws IOException { } } + static private LinkedList recentlyUsedBoards = new LinkedList(); + + static public LinkedList getRecentlyUsedBoards() { + return recentlyUsedBoards; + } + static public void selectBoard(TargetBoard targetBoard) { TargetPlatform targetPlatform = targetBoard.getContainerPlatform(); TargetPackage targetPackage = targetPlatform.getContainerPackage(); @@ -926,6 +932,13 @@ static public void selectBoard(TargetBoard targetBoard) { File platformFolder = targetPlatform.getFolder(); PreferencesData.set("runtime.platform.path", platformFolder.getAbsolutePath()); PreferencesData.set("runtime.hardware.path", platformFolder.getParentFile().getAbsolutePath()); + + if (!recentlyUsedBoards.contains(targetBoard)) { + recentlyUsedBoards.add(targetBoard); + } + if (recentlyUsedBoards.size() > 4) { + recentlyUsedBoards.remove(); + } } public static void selectSerialPort(String port) { From 90835089d9f5f529835bb191b256a363954edce1 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Thu, 7 Mar 2019 10:21:59 +0100 Subject: [PATCH 3/5] Fix concurrent access to menuItemsToClickAfterStartup --- app/src/processing/app/Base.java | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 59c8b160377..1d88010bb0c 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -1367,7 +1367,7 @@ public void rebuildRecentBoardsMenu() throws Exception { buttonGroupsMap, board, board.getContainerPlatform(), board.getContainerPlatform().getContainerPackage()); boardMenu.insert(item, 3); - item.setAccelerator(KeyStroke.getKeyStroke('0' + index, + item.setAccelerator(KeyStroke.getKeyStroke('1' + index, Toolkit.getDefaultToolkit().getMenuShortcutKeyMask() | ActionEvent.SHIFT_MASK)); recentBoardsButtonGroup.add(item); @@ -1513,18 +1513,14 @@ public void actionPerformed(ActionEvent actionevent) { boardsCustomMenus.add(customMenu); } - menuItemsToClickAfterStartup = new LinkedList<>(); + List _menuItemsToClickAfterStartup = new LinkedList<>(); boardsButtonGroup = new ButtonGroup(); recentBoardsButtonGroup = new ButtonGroup(); buttonGroupsMap = new HashMap<>(); - if (BaseNoGui.getRecentlyUsedBoards() != null) { - JMenuItem recentLabel = new JMenuItem(tr("Recently used boards")); - recentLabel.setEnabled(false); - boardMenu.add(recentLabel); - rebuildRecentBoardsMenu(); - //rebuildRecentBoardsMenu(null); - } + JMenuItem recentLabel = new JMenuItem(tr("Recently used boards")); + recentLabel.setEnabled(false); + boardMenu.add(recentLabel); // Cycle through all packages for (TargetPackage targetPackage : BaseNoGui.packages.values()) { @@ -1546,7 +1542,7 @@ public void actionPerformed(ActionEvent actionevent) { for (TargetBoard board : targetPlatform.getBoards().values()) { if (board.getPreferences().get("hide") != null) continue; - JMenuItem item = createBoardMenusAndCustomMenus(boardsCustomMenus, menuItemsToClickAfterStartup, + JMenuItem item = createBoardMenusAndCustomMenus(boardsCustomMenus, _menuItemsToClickAfterStartup, buttonGroupsMap, board, targetPlatform, targetPackage); boardMenu.add(item); @@ -1555,14 +1551,16 @@ public void actionPerformed(ActionEvent actionevent) { } } - if (menuItemsToClickAfterStartup.isEmpty()) { - menuItemsToClickAfterStartup.add(selectFirstEnabledMenuItem(boardMenu)); + if (_menuItemsToClickAfterStartup.isEmpty()) { + _menuItemsToClickAfterStartup.add(selectFirstEnabledMenuItem(boardMenu)); } - for (JMenuItem menuItemToClick : menuItemsToClickAfterStartup) { + for (JMenuItem menuItemToClick : _menuItemsToClickAfterStartup) { menuItemToClick.setSelected(true); menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, "")); } + + menuItemsToClickAfterStartup = _menuItemsToClickAfterStartup; } private JRadioButtonMenuItem createBoardMenusAndCustomMenus( From b21cfa00e93d127c84b73d5d9ce60f289ff074e0 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 8 Mar 2019 11:24:51 +0100 Subject: [PATCH 4/5] Make Recently used boards size configurable from preferences --- app/src/processing/app/Base.java | 10 +++++++--- arduino-core/src/processing/app/BaseNoGui.java | 2 +- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 1d88010bb0c..04afa54ee35 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -1518,9 +1518,13 @@ public void actionPerformed(ActionEvent actionevent) { recentBoardsButtonGroup = new ButtonGroup(); buttonGroupsMap = new HashMap<>(); - JMenuItem recentLabel = new JMenuItem(tr("Recently used boards")); - recentLabel.setEnabled(false); - boardMenu.add(recentLabel); + boolean hasRecentBoardsMenu = (PreferencesData.getInteger("editor.recent_boards.size", 4) != 0); + + if (hasRecentBoardsMenu) { + JMenuItem recentLabel = new JMenuItem(tr("Recently used boards")); + recentLabel.setEnabled(false); + boardMenu.add(recentLabel); + } // Cycle through all packages for (TargetPackage targetPackage : BaseNoGui.packages.values()) { diff --git a/arduino-core/src/processing/app/BaseNoGui.java b/arduino-core/src/processing/app/BaseNoGui.java index ee38975a7b7..e0fa5f1d5e9 100644 --- a/arduino-core/src/processing/app/BaseNoGui.java +++ b/arduino-core/src/processing/app/BaseNoGui.java @@ -936,7 +936,7 @@ static public void selectBoard(TargetBoard targetBoard) { if (!recentlyUsedBoards.contains(targetBoard)) { recentlyUsedBoards.add(targetBoard); } - if (recentlyUsedBoards.size() > 4) { + if (recentlyUsedBoards.size() > PreferencesData.getInteger("editor.recent_boards.size", 4)) { recentlyUsedBoards.remove(); } } From c0710e0309577d01b4e70ed6a43e25f779c4bb42 Mon Sep 17 00:00:00 2001 From: Martino Facchin Date: Fri, 8 Mar 2019 11:25:24 +0100 Subject: [PATCH 5/5] Prepare for LRU persistency --- app/src/processing/app/Base.java | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 04afa54ee35..897df1dd01a 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -559,6 +559,36 @@ protected boolean restoreSketches() throws Exception { return (opened > 0); } + protected boolean restoreRecentlyUsedBoards() 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.recent_boards.count"); + int opened = 0; + for (int i = count - 1; i >= 0; i--) { + String fqbn = PreferencesData.get("last.recent_board" + i + ".fqbn"); + if (fqbn == null) { + continue; + } + //selectTargetBoard(new TargetBoard()); + } + return count != 0; + } + + /** + * Store list of sketches that are currently open. + * Called when the application is quitting and documents are still open. + */ + protected void storeRecentlyUsedBoards() { + int i = 0; + for (TargetBoard board : BaseNoGui.getRecentlyUsedBoards()) { + PreferencesData.set("last.recent_board" + i + ".fqbn", board.getFQBN()); + i++; + } + PreferencesData.setInteger("last.recent_boards.count", BaseNoGui.getRecentlyUsedBoards().size()); + } + /** * Store screen dimensions on last close */