mirror of
https://github.com/arduino/Arduino.git
synced 2025-01-29 18:52:13 +01:00
new boards menu with custom submenus
https://code.google.com/p/arduino/issues/detail?id=257
This commit is contained in:
parent
cf4d72c043
commit
9b7f473fae
@ -34,9 +34,11 @@ import javax.swing.filechooser.FileNameExtensionFilter;
|
||||
import processing.app.debug.TargetPackage;
|
||||
import processing.app.debug.TargetPlatform;
|
||||
import processing.app.helpers.FileUtils;
|
||||
import processing.app.helpers.Maps;
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.helpers.filefilters.OnlyDirs;
|
||||
import processing.app.helpers.filefilters.OnlyFilesWithExtension;
|
||||
import processing.app.tools.MapWithSubkeys;
|
||||
import processing.app.tools.ZipDeflater;
|
||||
import processing.core.*;
|
||||
import static processing.app.I18n._;
|
||||
@ -1121,18 +1123,19 @@ public class Base {
|
||||
editor.onBoardOrPortChange();
|
||||
}
|
||||
|
||||
|
||||
public void rebuildBoardsMenu(JMenu boardsMenu, final JMenu cpuTypeMenu, final Editor editor) {
|
||||
public void rebuildBoardsMenu(JMenu toolsMenu, final Editor editor) {
|
||||
JMenu boardsMenu = makeOrGetBoardMenu(toolsMenu, "Board");
|
||||
|
||||
String selPackage = Preferences.get("target_package");
|
||||
String selPlatform = Preferences.get("target_platform");
|
||||
String selBoard = Preferences.get("board");
|
||||
String selBoardContainer = Preferences.get("board_container");
|
||||
|
||||
boardsMenu.removeAll();
|
||||
boolean first = true;
|
||||
|
||||
List<JMenuItem> menuItemsToClickAfterStartup = new LinkedList<JMenuItem>();
|
||||
|
||||
ButtonGroup boardsButtonGroup = new ButtonGroup();
|
||||
ButtonGroup cpuTypesButtonGroup = new ButtonGroup();
|
||||
Map<String, ButtonGroup> buttonGroupsMap = new HashMap<String, ButtonGroup>();
|
||||
|
||||
// Cycle through all packages
|
||||
for (TargetPackage targetPackage : packages.values()) {
|
||||
@ -1142,115 +1145,160 @@ public class Base {
|
||||
for (TargetPlatform targetPlatform : targetPackage.platforms()) {
|
||||
String platformName = targetPlatform.getName();
|
||||
Map<String, PreferencesMap> boards = targetPlatform.getBoards();
|
||||
|
||||
if (targetPlatform.getPreferences().get("name") == null || targetPlatform.getOrderedBoards().isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Add a title for each group of boards
|
||||
if (!first)
|
||||
if (!first) {
|
||||
boardsMenu.add(new JSeparator());
|
||||
first = false;
|
||||
}
|
||||
first = false;
|
||||
|
||||
JMenuItem separator = new JMenuItem(targetPlatform.getPreferences().get("name"));
|
||||
separator.setEnabled(false);
|
||||
boardsMenu.add(separator);
|
||||
|
||||
// For every platform cycle through all boards
|
||||
for (String boardID : targetPlatform.getOrderedBoards()) {
|
||||
for (final String boardID : targetPlatform.getOrderedBoards()) {
|
||||
|
||||
PreferencesMap boardAttributes = boards.get(boardID);
|
||||
final String boardContainer = boardAttributes.get("container");
|
||||
|
||||
AbstractAction filterCPUTypeMenuAction = new AbstractAction() {
|
||||
AbstractAction action = new AbstractAction(boardAttributes.get("name")) {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Preferences.set("board_container", (String) getValue("board_container"));
|
||||
|
||||
cpuTypeMenu.setEnabled(true);
|
||||
|
||||
for (int i = 0; i < cpuTypeMenu.getItemCount(); i++) {
|
||||
JMenuItem cpuTypeMenuItem = cpuTypeMenu.getItem(i);
|
||||
boolean visible = boardContainer.equals(cpuTypeMenuItem.getAction().getValue("board_container"));
|
||||
cpuTypeMenuItem.setVisible(visible);
|
||||
}
|
||||
|
||||
JMenuItem selectSelectedOrFirstVisibleMenuItem = selectVisibleSelectedOrFirstMenuItem(cpuTypeMenu);
|
||||
selectSelectedOrFirstVisibleMenuItem.doClick();
|
||||
}
|
||||
};
|
||||
filterCPUTypeMenuAction.putValue("board_container", boardContainer);
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
final AbstractAction selectBoardAction = new AbstractAction(boardAttributes.get("cpu")) {
|
||||
public void actionPerformed(ActionEvent actionevent) {
|
||||
Preferences.set("target_package", (String) getValue("package"));
|
||||
Preferences.set("target_platform", (String) getValue("platform"));
|
||||
Preferences.set("board", (String) getValue("board"));
|
||||
|
||||
filterVisibilityOfSubsequentBoardMenus((String) getValue("board"), 1, e);
|
||||
|
||||
onBoardOrPortChange();
|
||||
Sketch.buildSettingChanged();
|
||||
rebuildImportMenu(Editor.importMenu, editor);
|
||||
rebuildExamplesMenu(Editor.examplesMenu);
|
||||
}
|
||||
};
|
||||
selectBoardAction.putValue("package", packageName);
|
||||
selectBoardAction.putValue("platform", platformName);
|
||||
selectBoardAction.putValue("board", boardID);
|
||||
selectBoardAction.putValue("board_container", boardContainer);
|
||||
|
||||
if (boardContainer != null) {
|
||||
findOrCreateBoardContainerMenu(boardsMenu, boardsButtonGroup, boardContainer, filterCPUTypeMenuAction);
|
||||
|
||||
JMenuItem item = new JRadioButtonMenuItem(selectBoardAction);
|
||||
cpuTypesButtonGroup.add(item);
|
||||
cpuTypeMenu.add(item);
|
||||
} else {
|
||||
AbstractAction selectBoardWithoutContainerAction = new AbstractAction(boardAttributes.get("name")) {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
cpuTypeMenu.setEnabled(false);
|
||||
Preferences.unset("board_container");
|
||||
selectBoardAction.actionPerformed(e);
|
||||
};
|
||||
action.putValue("properties", boardAttributes);
|
||||
action.putValue("board", boardID);
|
||||
action.putValue("package", packageName);
|
||||
action.putValue("platform", platformName);
|
||||
|
||||
JRadioButtonMenuItem item = new JRadioButtonMenuItem(action);
|
||||
boardsMenu.add(item);
|
||||
boardsButtonGroup.add(item);
|
||||
|
||||
if (selBoard.equals(action.getValue("board")) && selPackage.equals(action.getValue("package"))
|
||||
&& selPlatform.equals(action.getValue("platform"))) {
|
||||
menuItemsToClickAfterStartup.add(item);
|
||||
}
|
||||
|
||||
if (targetPlatform.getCustomMenus() != null) {
|
||||
List<String> customMenuIDs = new LinkedList<String>(targetPlatform.getCustomMenus().getKeys());
|
||||
for (int i = 0; i < customMenuIDs.size(); i++) {
|
||||
final String customMenuID = customMenuIDs.get(i);
|
||||
JMenu menu = makeOrGetBoardMenu(toolsMenu, _(targetPlatform.getCustomMenus().getValueOf(customMenuID)));
|
||||
MapWithSubkeys customMenu = targetPlatform.getCustomMenus().get(customMenuID);
|
||||
if (customMenu.getKeys().contains(boardID)) {
|
||||
MapWithSubkeys boardCustomMenu = customMenu.get(boardID);
|
||||
final int currentIndex = i + 1 + 1; //plus 1 to skip the first board menu, plus 1 to keep the custom menu next to this one
|
||||
for (final String customMenuOption : boardCustomMenu.getKeys()) {
|
||||
action = new AbstractAction(_(boardCustomMenu.getValueOf(customMenuOption))) {
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Preferences.set("target_package", (String) getValue("package"));
|
||||
Preferences.set("target_platform", (String) getValue("platform"));
|
||||
Preferences.set("board", (String) getValue("board"));
|
||||
Preferences.set("custom_" + customMenuID, boardID + "_" + (String) getValue("custom_menu_option"));
|
||||
|
||||
filterVisibilityOfSubsequentBoardMenus((String) getValue("board"), currentIndex, e);
|
||||
|
||||
onBoardOrPortChange();
|
||||
Sketch.buildSettingChanged();
|
||||
rebuildImportMenu(Editor.importMenu, editor);
|
||||
rebuildExamplesMenu(Editor.examplesMenu);
|
||||
}
|
||||
};
|
||||
action.putValue("properties", boardCustomMenu.getValues());
|
||||
action.putValue("board", boardID);
|
||||
action.putValue("custom_menu_option", customMenuOption);
|
||||
action.putValue("package", packageName);
|
||||
action.putValue("platform", platformName);
|
||||
|
||||
if (!buttonGroupsMap.containsKey(customMenuID)) {
|
||||
buttonGroupsMap.put(customMenuID, new ButtonGroup());
|
||||
}
|
||||
|
||||
item = new JRadioButtonMenuItem(action);
|
||||
menu.add(item);
|
||||
buttonGroupsMap.get(customMenuID).add(item);
|
||||
|
||||
String selectedCustomMenuEntry = Preferences.get("custom_" + customMenuID);
|
||||
if (selBoard.equals(boardID) && (boardID + "_" + customMenuOption).equals(selectedCustomMenuEntry)) {
|
||||
menuItemsToClickAfterStartup.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue(String key) {
|
||||
return selectBoardAction.getValue(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void putValue(String key, Object newValue) {
|
||||
selectBoardAction.putValue(key, newValue);
|
||||
}
|
||||
};
|
||||
JMenuItem item = new JRadioButtonMenuItem(selectBoardWithoutContainerAction);
|
||||
boardsButtonGroup.add(item);
|
||||
boardsMenu.add(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JMenuItem selectedBoardMenu = selectMenuItemByBoardContainer(boardsMenu, selBoardContainer);
|
||||
if (selectedBoardMenu == null) {
|
||||
selectedBoardMenu = selectMenuItemByBoardPackagePlatform(boardsMenu, selBoard, selPackage, selPlatform);
|
||||
if (selectedBoardMenu == null) {
|
||||
selectedBoardMenu = selectFirstEnabledMenuItem(boardsMenu);
|
||||
|
||||
if (menuItemsToClickAfterStartup.isEmpty()) {
|
||||
menuItemsToClickAfterStartup.add(selectFirstEnabledMenuItem(boardsMenu));
|
||||
}
|
||||
|
||||
for (JMenuItem menuItemToClick : menuItemsToClickAfterStartup) {
|
||||
menuItemToClick.setSelected(true);
|
||||
menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, ""));
|
||||
}
|
||||
}
|
||||
selectedBoardMenu.doClick();
|
||||
}
|
||||
|
||||
if (cpuTypeMenu.isEnabled()) {
|
||||
JMenuItem selectedCPUTypeMenu;
|
||||
if (selBoard == null) {
|
||||
selectedCPUTypeMenu = selectFirstEnabledMenuItem(cpuTypeMenu);
|
||||
} else {
|
||||
selectedCPUTypeMenu = selectMenuItemByBoardPackagePlatform(cpuTypeMenu, selBoard, selPackage, selPlatform);
|
||||
if (selectedCPUTypeMenu == null) {
|
||||
selectedCPUTypeMenu = selectFirstEnabledMenuItem(cpuTypeMenu);
|
||||
private static void filterVisibilityOfSubsequentBoardMenus(String boardID, int fromIndex, ActionEvent originatingEvent) {
|
||||
for (int i = fromIndex; i < Editor.boardsMenus.size(); i++) {
|
||||
JMenu menu = Editor.boardsMenus.get(i);
|
||||
for (int m = 0; m < menu.getItemCount(); m++) {
|
||||
JMenuItem menuItem = menu.getItem(m);
|
||||
menuItem.setVisible(menuItem.getAction().getValue("board").equals(boardID));
|
||||
}
|
||||
menu.setEnabled(ifThereAreVisibleItemsOn(menu));
|
||||
|
||||
if (menu.isEnabled()) {
|
||||
JMenuItem visibleSelectedOrFirstMenuItem = selectVisibleSelectedOrFirstMenuItem(menu);
|
||||
if (!visibleSelectedOrFirstMenuItem.isSelected()) {
|
||||
visibleSelectedOrFirstMenuItem.setSelected(true);
|
||||
visibleSelectedOrFirstMenuItem.getAction().actionPerformed(originatingEvent);
|
||||
}
|
||||
}
|
||||
selectedCPUTypeMenu.doClick();
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean ifThereAreVisibleItemsOn(JMenu menu) {
|
||||
for (int i = 0; i < menu.getItemCount(); i++) {
|
||||
if (menu.getItem(i).isVisible()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private JMenu makeOrGetBoardMenu(JMenu toolsMenu, String label) {
|
||||
String i18nLabel = _(label);
|
||||
for (JMenu menu : Editor.boardsMenus) {
|
||||
if (i18nLabel.equals(menu.getText())) {
|
||||
return menu;
|
||||
}
|
||||
}
|
||||
JMenu menu = new JMenu(i18nLabel);
|
||||
Editor.boardsMenus.add(menu);
|
||||
toolsMenu.add(menu);
|
||||
return menu;
|
||||
}
|
||||
|
||||
private static JMenuItem selectVisibleSelectedOrFirstMenuItem(JMenu menu) {
|
||||
JMenuItem firstVisible = null;
|
||||
@ -1283,45 +1331,6 @@ public class Base {
|
||||
throw new IllegalStateException("Menu has no enabled items");
|
||||
}
|
||||
|
||||
private static JMenuItem selectMenuItemByBoardContainer(JMenu menu, String boardContainer) {
|
||||
if (boardContainer == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
for (int i = 0; i < menu.getItemCount(); i++) {
|
||||
JMenuItem item = menu.getItem(i);
|
||||
if (item != null && item.getAction() != null && boardContainer.equals(item.getAction().getValue("board_container"))) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static JMenuItem selectMenuItemByBoardPackagePlatform(JMenu menu, String selBoard, String selPackage, String selPlatform) {
|
||||
for (int i = 0; i < menu.getItemCount(); i++) {
|
||||
JMenuItem item = menu.getItem(i);
|
||||
if (item != null && item.getAction() != null && selBoard.equals(item.getAction().getValue("board"))
|
||||
&& selPackage.equals(item.getAction().getValue("package")) && selPlatform.equals(item.getAction().getValue("platform"))) {
|
||||
return item;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private JMenuItem findOrCreateBoardContainerMenu(JMenu boardsMenu, ButtonGroup boardsButtonGroup, String boardContainerName, AbstractAction boardMenuAction) {
|
||||
for (int i = 0; i < boardsMenu.getItemCount(); i++ ) {
|
||||
JMenuItem boardContainer = boardsMenu.getItem(i);
|
||||
if (boardContainer != null && boardContainerName.equals(boardContainer.getText())) {
|
||||
return boardContainer;
|
||||
}
|
||||
}
|
||||
JMenuItem item = new JRadioButtonMenuItem(boardMenuAction);
|
||||
item.setText(boardContainerName);
|
||||
boardsButtonGroup.add(item);
|
||||
boardsMenu.add(item);
|
||||
return item;
|
||||
}
|
||||
|
||||
public void rebuildProgrammerMenu(JMenu menu) {
|
||||
menu.removeAll();
|
||||
ButtonGroup group = new ButtonGroup();
|
||||
@ -1809,10 +1818,22 @@ public class Base {
|
||||
return getTargetPlatform(pack, Preferences.get("target_platform"));
|
||||
}
|
||||
|
||||
static public PreferencesMap getBoardPreferences() {
|
||||
static public Map<String, String> getBoardPreferences() {
|
||||
TargetPlatform target = getTargetPlatform();
|
||||
String board = Preferences.get("board");
|
||||
return target.getBoards().get(board);
|
||||
Map<String, String> boardPreferences = Maps.merge(target.getBoards().get(board), new LinkedHashMap<String, String>());
|
||||
if (target.getCustomMenus() != null) {
|
||||
for (String customMenuID : target.getCustomMenus().getKeys()) {
|
||||
MapWithSubkeys boardCustomMenu = target.getCustomMenus().get(customMenuID).get(board);
|
||||
String selectedCustomMenuEntry = Preferences.get("custom_" + customMenuID);
|
||||
if (boardCustomMenu != null && selectedCustomMenuEntry != null && selectedCustomMenuEntry.startsWith(board)) {
|
||||
String menuEntryId = selectedCustomMenuEntry.substring(selectedCustomMenuEntry.indexOf("_") + 1);
|
||||
Maps.merge(boardCustomMenu.get(menuEntryId).getValues(), boardPreferences);
|
||||
boardPreferences.put("name", boardPreferences.get("name") + ", " + boardCustomMenu.getValueOf(menuEntryId));
|
||||
}
|
||||
}
|
||||
}
|
||||
return boardPreferences;
|
||||
}
|
||||
|
||||
static public File getSketchbookFolder() {
|
||||
|
@ -35,6 +35,7 @@ import java.awt.print.*;
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.zip.*;
|
||||
|
||||
import javax.swing.*;
|
||||
@ -95,9 +96,8 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// 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)
|
||||
static JMenu boardsMenu;
|
||||
static List<JMenu> boardsMenus;
|
||||
static JMenu serialMenu;
|
||||
static JMenu cpuTypeMenu;
|
||||
|
||||
static SerialMenuListener serialMenuListener;
|
||||
static SerialMonitor serialMonitor;
|
||||
@ -178,10 +178,13 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// re-add the sub-menus that are shared by all windows
|
||||
fileMenu.insert(sketchbookMenu, 2);
|
||||
fileMenu.insert(examplesMenu, 3);
|
||||
//sketchMenu.insert(importMenu, 4);
|
||||
toolsMenu.insert(boardsMenu, numTools);
|
||||
toolsMenu.insert(cpuTypeMenu, numTools + 1);
|
||||
toolsMenu.insert(serialMenu, numTools + 2);
|
||||
sketchMenu.insert(importMenu, 4);
|
||||
int offset = 0;
|
||||
for (JMenu menu : boardsMenus) {
|
||||
toolsMenu.insert(menu, numTools + offset);
|
||||
offset++;
|
||||
}
|
||||
toolsMenu.insert(serialMenu, numTools + offset);
|
||||
}
|
||||
|
||||
// added for 1.0.5
|
||||
@ -190,9 +193,10 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// System.err.println("deactivate"); // not coming through
|
||||
fileMenu.remove(sketchbookMenu);
|
||||
fileMenu.remove(examplesMenu);
|
||||
//sketchMenu.remove(importMenu);
|
||||
toolsMenu.remove(boardsMenu);
|
||||
toolsMenu.remove(cpuTypeMenu);
|
||||
sketchMenu.remove(importMenu);
|
||||
for (JMenu menu : boardsMenus) {
|
||||
toolsMenu.remove(menu);
|
||||
}
|
||||
toolsMenu.remove(serialMenu);
|
||||
}
|
||||
});
|
||||
@ -681,16 +685,13 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// XXX: DAM: these should probably be implemented using the Tools plugin
|
||||
// API, if possible (i.e. if it supports custom actions, etc.)
|
||||
|
||||
if (boardsMenu == null) {
|
||||
boardsMenu = new JMenu(_("Board"));
|
||||
cpuTypeMenu = new JMenu(_("Processor"));
|
||||
base.rebuildBoardsMenu(boardsMenu, cpuTypeMenu, this);
|
||||
if (boardsMenus == null) {
|
||||
boardsMenus = new LinkedList<JMenu>();
|
||||
base.rebuildBoardsMenu(toolsMenu, this);
|
||||
//Debug: rebuild imports
|
||||
importMenu.removeAll();
|
||||
base.rebuildImportMenu(importMenu, this);
|
||||
}
|
||||
menu.add(boardsMenu);
|
||||
menu.add(cpuTypeMenu);
|
||||
|
||||
if (serialMenuListener == null)
|
||||
serialMenuListener = new SerialMenuListener();
|
||||
@ -2660,7 +2661,7 @@ public class Editor extends JFrame implements RunnerListener {
|
||||
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
|
||||
|
||||
protected void onBoardOrPortChange() {
|
||||
Map<String, String> boardPreferences = Base.getBoardPreferences();
|
||||
Map<String, String> boardPreferences = Base.getBoardPreferences();
|
||||
lineStatus.setBoardName(boardPreferences.get("name"));
|
||||
lineStatus.setSerialPort(Preferences.get("serial.port"));
|
||||
lineStatus.repaint();
|
||||
|
@ -30,6 +30,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import processing.app.helpers.PreferencesMap;
|
||||
import processing.app.tools.MapWithSubkeys;
|
||||
import processing.core.PApplet;
|
||||
|
||||
public class TargetPlatform {
|
||||
@ -39,6 +40,7 @@ public class TargetPlatform {
|
||||
private List<String> boardsOrder;
|
||||
private Map<String, PreferencesMap> programmers;
|
||||
private PreferencesMap preferences;
|
||||
private MapWithSubkeys customMenus;
|
||||
|
||||
public TargetPlatform(String _name, File _folder) {
|
||||
System.out.println("TargetPlatform: constructor start, name: " + _name);
|
||||
@ -55,9 +57,12 @@ public class TargetPlatform {
|
||||
PreferencesMap boardPreferences = new PreferencesMap();
|
||||
boardPreferences.load(boardsFile);
|
||||
boards = boardPreferences.createFirstLevelMap();
|
||||
customMenus = MapWithSubkeys.createFrom(boards.get("menu"));
|
||||
boards.remove("menu");
|
||||
boardsOrder = readBoardsOrder(boardsFile);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
System.err.println("Error loading boards from boards.txt: " + e);
|
||||
}
|
||||
|
||||
@ -119,7 +124,11 @@ public class TargetPlatform {
|
||||
public Map<String, PreferencesMap> getBoards() {
|
||||
return boards;
|
||||
}
|
||||
|
||||
|
||||
public MapWithSubkeys getCustomMenus() {
|
||||
return customMenus;
|
||||
}
|
||||
|
||||
public List<String> getOrderedBoards() {
|
||||
return boardsOrder;
|
||||
}
|
||||
|
15
app/src/processing/app/helpers/Maps.java
Normal file
15
app/src/processing/app/helpers/Maps.java
Normal file
@ -0,0 +1,15 @@
|
||||
package processing.app.helpers;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class Maps {
|
||||
|
||||
public static <K, V> Map<K, V> merge(Map<K, V> input, Map<K, V> target) {
|
||||
for (Entry<K, V> entry : input.entrySet()) {
|
||||
target.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
}
|
66
app/src/processing/app/tools/MapWithSubkeys.java
Normal file
66
app/src/processing/app/tools/MapWithSubkeys.java
Normal file
@ -0,0 +1,66 @@
|
||||
package processing.app.tools;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
public class MapWithSubkeys {
|
||||
|
||||
public static MapWithSubkeys createFrom(Map<String, String> input) {
|
||||
if (input == null) {
|
||||
return null;
|
||||
}
|
||||
MapWithSubkeys target = new MapWithSubkeys();
|
||||
for (Entry<String, String> entry : input.entrySet()) {
|
||||
String[] entryParts = entry.getKey().split("\\.");
|
||||
if (entryParts.length == 1) {
|
||||
target.put(entryParts[0], entry.getValue());
|
||||
} else if (entryParts.length == 3) {
|
||||
target.get(entryParts[0]).get(entryParts[1]).put(entryParts[2], entry.getValue());
|
||||
} else if (entryParts.length > 3) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 3; i < entryParts.length; i++) {
|
||||
sb.append(entryParts[i]).append(".");
|
||||
}
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
String key = sb.toString();
|
||||
target.get(entryParts[0]).get(entryParts[1]).get(entryParts[2]).put(key, entry.getValue());
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
private final Map<String, String> values;
|
||||
private final Map<String, MapWithSubkeys> maps;
|
||||
|
||||
public MapWithSubkeys() {
|
||||
this.values = new HashMap<String, String>();
|
||||
this.maps = new HashMap<String, MapWithSubkeys>();
|
||||
}
|
||||
|
||||
public Collection<String> getKeys() {
|
||||
return values.keySet();
|
||||
}
|
||||
|
||||
public Map<String, String> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public String getValueOf(String key) {
|
||||
return values.get(key);
|
||||
}
|
||||
|
||||
public MapWithSubkeys get(String key) {
|
||||
if (!maps.containsKey(key)) {
|
||||
put(key, null);
|
||||
maps.put(key, new MapWithSubkeys());
|
||||
}
|
||||
return maps.get(key);
|
||||
}
|
||||
|
||||
public void put(String key, String value) {
|
||||
values.put(key, value);
|
||||
}
|
||||
|
||||
}
|
59
app/test/processing/app/tools/MapWithSubkeysTest.java
Normal file
59
app/test/processing/app/tools/MapWithSubkeysTest.java
Normal file
@ -0,0 +1,59 @@
|
||||
package processing.app.tools;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MapWithSubkeysTest {
|
||||
|
||||
private MapWithSubkeys map;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
Map<String, String> input = new HashMap<String, String>();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(MapWithSubkeysTest.class.getResourceAsStream("test_partial_boards.txt")));
|
||||
String line = null;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
String[] lineParts = line.split("=");
|
||||
input.put(lineParts[0], lineParts[1]);
|
||||
}
|
||||
map = MapWithSubkeys.createFrom(input);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldListCustomMenusIDs() {
|
||||
Collection<String> menusIDs = map.getKeys();
|
||||
|
||||
assertEquals(2, menusIDs.size());
|
||||
assertTrue(menusIDs.contains("cpu"));
|
||||
assertTrue(menusIDs.contains("speed"));
|
||||
|
||||
assertEquals("Processor", map.getValueOf("cpu"));
|
||||
|
||||
MapWithSubkeys cpu = map.get("cpu");
|
||||
|
||||
Collection<String> boards = cpu.getKeys();
|
||||
assertEquals(1, boards.size());
|
||||
assertTrue(boards.contains("nano"));
|
||||
|
||||
Collection<String> cpuNanoProcessors = cpu.get("nano").getKeys();
|
||||
assertEquals(2, cpuNanoProcessors.size());
|
||||
assertTrue(cpuNanoProcessors.contains("atmega168"));
|
||||
assertTrue(cpuNanoProcessors.contains("atmega328"));
|
||||
assertEquals("ATmega168", cpu.get("nano").getValueOf("atmega168"));
|
||||
assertEquals("ATmega328", cpu.get("nano").getValueOf("atmega328"));
|
||||
|
||||
MapWithSubkeys atmega168Properties = cpu.get("nano").get("atmega168");
|
||||
assertEquals(9, atmega168Properties.getKeys().size());
|
||||
assertTrue(atmega168Properties.getKeys().contains("bootloader.high_fuses"));
|
||||
}
|
||||
|
||||
}
|
26
app/test/processing/app/tools/test_partial_boards.txt
Normal file
26
app/test/processing/app/tools/test_partial_boards.txt
Normal file
@ -0,0 +1,26 @@
|
||||
cpu=Processor
|
||||
cpu.nano.atmega328=ATmega328
|
||||
cpu.nano.atmega328.upload.maximum_size=30720
|
||||
cpu.nano.atmega328.upload.speed=57600
|
||||
cpu.nano.atmega328.bootloader.low_fuses=0xFF
|
||||
cpu.nano.atmega328.bootloader.high_fuses=0xDA
|
||||
cpu.nano.atmega328.bootloader.extended_fuses=0x05
|
||||
cpu.nano.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
|
||||
cpu.nano.atmega328.bootloader.unlock_bits=0x3F
|
||||
cpu.nano.atmega328.bootloader.lock_bits=0x0F
|
||||
cpu.nano.atmega328.build.mcu=atmega328p
|
||||
cpu.nano.atmega168=ATmega168
|
||||
cpu.nano.atmega168.upload.maximum_size=14336
|
||||
cpu.nano.atmega168.upload.speed=19200
|
||||
cpu.nano.atmega168.bootloader.low_fuses=0xff
|
||||
cpu.nano.atmega168.bootloader.high_fuses=0xdd
|
||||
cpu.nano.atmega168.bootloader.extended_fuses=0x00
|
||||
cpu.nano.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex
|
||||
cpu.nano.atmega168.bootloader.unlock_bits=0x3F
|
||||
cpu.nano.atmega168.bootloader.lock_bits=0x0F
|
||||
cpu.nano.atmega168.build.mcu=atmega168
|
||||
speed=Speed
|
||||
speed.nano.16=16 MHz
|
||||
speed.nano.16.build.f_cpu=16000000L
|
||||
speed.nano.8=8 MHz
|
||||
speed.nano.8.build.f_cpu=8000000L
|
@ -1,5 +1,9 @@
|
||||
# See: http://code.google.com/p/arduino/wiki/Platforms
|
||||
|
||||
menu.cpu=Processor
|
||||
#FIXME
|
||||
menu.speed=Speed
|
||||
|
||||
##############################################################
|
||||
|
||||
uno.name=Arduino Uno
|
||||
@ -67,52 +71,45 @@ diecimila.build.variant=standard
|
||||
|
||||
##############################################################
|
||||
|
||||
nano328.name=Arduino Nano w/ ATmega328
|
||||
nano328.cpu=ATmega328
|
||||
nano328.container=Arduino Nano
|
||||
|
||||
nano328.upload.tool=avrdude
|
||||
nano328.upload.protocol=arduino
|
||||
nano328.upload.maximum_size=30720
|
||||
nano328.upload.speed=57600
|
||||
|
||||
nano328.bootloader.tool=avrdude
|
||||
nano328.bootloader.low_fuses=0xFF
|
||||
nano328.bootloader.high_fuses=0xDA
|
||||
nano328.bootloader.extended_fuses=0x05
|
||||
nano328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
|
||||
nano328.bootloader.unlock_bits=0x3F
|
||||
nano328.bootloader.lock_bits=0x0F
|
||||
|
||||
nano328.build.mcu=atmega328p
|
||||
nano328.build.f_cpu=16000000L
|
||||
nano328.build.core=arduino
|
||||
nano328.build.variant=eightanaloginputs
|
||||
|
||||
##############################################################
|
||||
|
||||
nano.name=Arduino Nano w/ ATmega168
|
||||
nano.cpu=ATmega168
|
||||
nano.container=Arduino Nano
|
||||
nano.name=Arduino Nano
|
||||
|
||||
nano.upload.tool=avrdude
|
||||
nano.upload.protocol=arduino
|
||||
nano.upload.maximum_size=14336
|
||||
nano.upload.speed=19200
|
||||
|
||||
nano.bootloader.tool=avrdude
|
||||
nano.bootloader.low_fuses=0xff
|
||||
nano.bootloader.high_fuses=0xdd
|
||||
nano.bootloader.extended_fuses=0x00
|
||||
nano.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex
|
||||
nano.bootloader.unlock_bits=0x3F
|
||||
nano.bootloader.lock_bits=0x0F
|
||||
|
||||
nano.build.mcu=atmega168
|
||||
nano.build.f_cpu=16000000L
|
||||
nano.build.core=arduino
|
||||
nano.build.variant=eightanaloginputs
|
||||
|
||||
#Arduino Nano w/ ATmega328
|
||||
menu.cpu.nano.atmega328=ATmega328
|
||||
menu.cpu.nano.atmega328.upload.maximum_size=30720
|
||||
menu.cpu.nano.atmega328.upload.speed=57600
|
||||
|
||||
menu.cpu.nano.atmega328.bootloader.low_fuses=0xFF
|
||||
menu.cpu.nano.atmega328.bootloader.high_fuses=0xDA
|
||||
menu.cpu.nano.atmega328.bootloader.extended_fuses=0x05
|
||||
menu.cpu.nano.atmega328.bootloader.file=atmega/ATmegaBOOT_168_atmega328.hex
|
||||
menu.cpu.nano.atmega328.bootloader.unlock_bits=0x3F
|
||||
menu.cpu.nano.atmega328.bootloader.lock_bits=0x0F
|
||||
|
||||
menu.cpu.nano.atmega328.build.mcu=atmega328p
|
||||
|
||||
#Arduino Nano w/ ATmega168
|
||||
menu.cpu.nano.atmega168=ATmega168
|
||||
menu.cpu.nano.atmega168.upload.maximum_size=14336
|
||||
menu.cpu.nano.atmega168.upload.speed=19200
|
||||
|
||||
menu.cpu.nano.atmega168.bootloader.low_fuses=0xff
|
||||
menu.cpu.nano.atmega168.bootloader.high_fuses=0xdd
|
||||
menu.cpu.nano.atmega168.bootloader.extended_fuses=0x00
|
||||
menu.cpu.nano.atmega168.bootloader.file=atmega/ATmegaBOOT_168_diecimila.hex
|
||||
menu.cpu.nano.atmega168.bootloader.unlock_bits=0x3F
|
||||
menu.cpu.nano.atmega168.bootloader.lock_bits=0x0F
|
||||
|
||||
menu.cpu.nano.atmega168.build.mcu=atmega168
|
||||
|
||||
##############################################################
|
||||
|
||||
mega2560.name=Arduino Mega 2560 or Mega ADK
|
||||
@ -190,52 +187,50 @@ leonardo.build.extra_flags=-DUSB_VID={build.vid} -DUSB_PID={build.pid}
|
||||
|
||||
##############################################################
|
||||
|
||||
mini328.name=Arduino Mini w/ ATmega328
|
||||
mini328.cpu=ATmega328
|
||||
mini328.container=Arduino Mini
|
||||
|
||||
mini328.upload.tool=avrdude
|
||||
mini328.upload.protocol=arduino
|
||||
mini328.upload.maximum_size=28672
|
||||
mini328.upload.speed=115200
|
||||
|
||||
mini328.bootloader.tool=avrdude
|
||||
mini328.bootloader.low_fuses=0xff
|
||||
mini328.bootloader.high_fuses=0xd8
|
||||
mini328.bootloader.extended_fuses=0x05
|
||||
mini328.bootloader.file=optiboot/optiboot_atmega328-Mini.hex
|
||||
mini328.bootloader.unlock_bits=0x3F
|
||||
mini328.bootloader.lock_bits=0x0F
|
||||
|
||||
mini328.build.mcu=atmega328p
|
||||
mini328.build.f_cpu=16000000L
|
||||
mini328.build.core=arduino
|
||||
mini328.build.variant=eightanaloginputs
|
||||
|
||||
##############################################################
|
||||
|
||||
mini.name=Arduino Mini w/ ATmega168
|
||||
mini.cpu=ATmega168
|
||||
mini.container=Arduino Mini
|
||||
mini.name=Arduino Mini
|
||||
|
||||
mini.upload.tool=avrdude
|
||||
mini.upload.protocol=arduino
|
||||
mini.upload.maximum_size=14336
|
||||
mini.upload.speed=19200
|
||||
|
||||
mini.bootloader.tool=avrdude
|
||||
mini.bootloader.low_fuses=0xff
|
||||
mini.bootloader.high_fuses=0xdd
|
||||
mini.bootloader.extended_fuses=0x00
|
||||
mini.bootloader.file=atmega/ATmegaBOOT_168_ng.hex
|
||||
mini.bootloader.unlock_bits=0x3F
|
||||
mini.bootloader.lock_bits=0x0F
|
||||
|
||||
mini.build.mcu=atmega168
|
||||
mini.build.f_cpu=16000000L
|
||||
mini.build.core=arduino
|
||||
mini.build.variant=eightanaloginputs
|
||||
|
||||
#Arduino Mini w/ ATmega328
|
||||
menu.cpu.mini.atmega328=ATmega328
|
||||
|
||||
menu.cpu.mini.atmega328.upload.maximum_size=28672
|
||||
menu.cpu.mini.atmega328.upload.speed=115200
|
||||
|
||||
menu.cpu.mini.atmega328.bootloader.high_fuses=0xd8
|
||||
menu.cpu.mini.atmega328.bootloader.extended_fuses=0x05
|
||||
menu.cpu.mini.atmega328.bootloader.file=optiboot/optiboot_atmega328-Mini.hex
|
||||
|
||||
menu.cpu.mini.atmega328.build.mcu=atmega328p
|
||||
|
||||
#Arduino Mini w/ ATmega168
|
||||
menu.cpu.mini.atmega168=ATmega168
|
||||
|
||||
menu.cpu.mini.atmega168.upload.maximum_size=14336
|
||||
menu.cpu.mini.atmega168.upload.speed=19200
|
||||
|
||||
menu.cpu.mini.atmega168.bootloader.high_fuses=0xdd
|
||||
menu.cpu.mini.atmega168.bootloader.extended_fuses=0x00
|
||||
menu.cpu.mini.atmega168.bootloader.file=atmega/ATmegaBOOT_168_ng.hex
|
||||
|
||||
menu.cpu.mini.atmega168.build.mcu=atmega168
|
||||
|
||||
#FIXME
|
||||
menu.speed.mini.16=16 MHz
|
||||
menu.speed.mini.16.build.f_cpu=16000000L
|
||||
menu.speed.mini.8=8 MHz
|
||||
menu.speed.mini.8.build.f_cpu=8000000L
|
||||
|
||||
##############################################################
|
||||
|
||||
ethernet.name=Arduino Ethernet
|
||||
|
Loading…
x
Reference in New Issue
Block a user