new boards menu with custom submenus

https://code.google.com/p/arduino/issues/detail?id=257
This commit is contained in:
Federico Fissore 2012-10-29 16:40:23 +01:00
parent cf4d72c043
commit 9b7f473fae
8 changed files with 398 additions and 206 deletions

View File

@ -34,9 +34,11 @@ import javax.swing.filechooser.FileNameExtensionFilter;
import processing.app.debug.TargetPackage; import processing.app.debug.TargetPackage;
import processing.app.debug.TargetPlatform; import processing.app.debug.TargetPlatform;
import processing.app.helpers.FileUtils; import processing.app.helpers.FileUtils;
import processing.app.helpers.Maps;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import processing.app.helpers.filefilters.OnlyDirs; import processing.app.helpers.filefilters.OnlyDirs;
import processing.app.helpers.filefilters.OnlyFilesWithExtension; import processing.app.helpers.filefilters.OnlyFilesWithExtension;
import processing.app.tools.MapWithSubkeys;
import processing.app.tools.ZipDeflater; import processing.app.tools.ZipDeflater;
import processing.core.*; import processing.core.*;
import static processing.app.I18n._; import static processing.app.I18n._;
@ -1121,18 +1123,19 @@ public class Base {
editor.onBoardOrPortChange(); editor.onBoardOrPortChange();
} }
public void rebuildBoardsMenu(JMenu toolsMenu, final Editor editor) {
public void rebuildBoardsMenu(JMenu boardsMenu, final JMenu cpuTypeMenu, final Editor editor) { JMenu boardsMenu = makeOrGetBoardMenu(toolsMenu, "Board");
String selPackage = Preferences.get("target_package"); String selPackage = Preferences.get("target_package");
String selPlatform = Preferences.get("target_platform"); String selPlatform = Preferences.get("target_platform");
String selBoard = Preferences.get("board"); String selBoard = Preferences.get("board");
String selBoardContainer = Preferences.get("board_container");
boardsMenu.removeAll();
boolean first = true; boolean first = true;
List<JMenuItem> menuItemsToClickAfterStartup = new LinkedList<JMenuItem>();
ButtonGroup boardsButtonGroup = new ButtonGroup(); ButtonGroup boardsButtonGroup = new ButtonGroup();
ButtonGroup cpuTypesButtonGroup = new ButtonGroup(); Map<String, ButtonGroup> buttonGroupsMap = new HashMap<String, ButtonGroup>();
// Cycle through all packages // Cycle through all packages
for (TargetPackage targetPackage : packages.values()) { for (TargetPackage targetPackage : packages.values()) {
@ -1142,115 +1145,160 @@ public class Base {
for (TargetPlatform targetPlatform : targetPackage.platforms()) { for (TargetPlatform targetPlatform : targetPackage.platforms()) {
String platformName = targetPlatform.getName(); String platformName = targetPlatform.getName();
Map<String, PreferencesMap> boards = targetPlatform.getBoards(); Map<String, PreferencesMap> boards = targetPlatform.getBoards();
if (targetPlatform.getPreferences().get("name") == null || targetPlatform.getOrderedBoards().isEmpty()) {
continue;
}
// Add a title for each group of boards // Add a title for each group of boards
if (!first) if (!first) {
boardsMenu.add(new JSeparator()); boardsMenu.add(new JSeparator());
first = false; }
first = false;
JMenuItem separator = new JMenuItem(targetPlatform.getPreferences().get("name")); JMenuItem separator = new JMenuItem(targetPlatform.getPreferences().get("name"));
separator.setEnabled(false); separator.setEnabled(false);
boardsMenu.add(separator); boardsMenu.add(separator);
// For every platform cycle through all boards // For every platform cycle through all boards
for (String boardID : targetPlatform.getOrderedBoards()) { for (final String boardID : targetPlatform.getOrderedBoards()) {
PreferencesMap boardAttributes = boards.get(boardID); PreferencesMap boardAttributes = boards.get(boardID);
final String boardContainer = boardAttributes.get("container");
AbstractAction filterCPUTypeMenuAction = new AbstractAction() { AbstractAction action = new AbstractAction(boardAttributes.get("name")) {
@Override @Override
public void actionPerformed(ActionEvent e) { 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_package", (String) getValue("package"));
Preferences.set("target_platform", (String) getValue("platform")); Preferences.set("target_platform", (String) getValue("platform"));
Preferences.set("board", (String) getValue("board")); Preferences.set("board", (String) getValue("board"));
filterVisibilityOfSubsequentBoardMenus((String) getValue("board"), 1, e);
onBoardOrPortChange(); onBoardOrPortChange();
Sketch.buildSettingChanged(); Sketch.buildSettingChanged();
rebuildImportMenu(Editor.importMenu, editor); rebuildImportMenu(Editor.importMenu, editor);
rebuildExamplesMenu(Editor.examplesMenu); 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); action.putValue("properties", boardAttributes);
cpuTypeMenu.add(item); action.putValue("board", boardID);
} else { action.putValue("package", packageName);
AbstractAction selectBoardWithoutContainerAction = new AbstractAction(boardAttributes.get("name")) { action.putValue("platform", platformName);
@Override JRadioButtonMenuItem item = new JRadioButtonMenuItem(action);
public void actionPerformed(ActionEvent e) { boardsMenu.add(item);
cpuTypeMenu.setEnabled(false); boardsButtonGroup.add(item);
Preferences.unset("board_container");
selectBoardAction.actionPerformed(e); 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);
} }
} }
} }
}
if (menuItemsToClickAfterStartup.isEmpty()) {
JMenuItem selectedBoardMenu = selectMenuItemByBoardContainer(boardsMenu, selBoardContainer); menuItemsToClickAfterStartup.add(selectFirstEnabledMenuItem(boardsMenu));
if (selectedBoardMenu == null) { }
selectedBoardMenu = selectMenuItemByBoardPackagePlatform(boardsMenu, selBoard, selPackage, selPlatform);
if (selectedBoardMenu == null) { for (JMenuItem menuItemToClick : menuItemsToClickAfterStartup) {
selectedBoardMenu = selectFirstEnabledMenuItem(boardsMenu); menuItemToClick.setSelected(true);
menuItemToClick.getAction().actionPerformed(new ActionEvent(this, -1, ""));
} }
} }
selectedBoardMenu.doClick(); }
if (cpuTypeMenu.isEnabled()) { private static void filterVisibilityOfSubsequentBoardMenus(String boardID, int fromIndex, ActionEvent originatingEvent) {
JMenuItem selectedCPUTypeMenu; for (int i = fromIndex; i < Editor.boardsMenus.size(); i++) {
if (selBoard == null) { JMenu menu = Editor.boardsMenus.get(i);
selectedCPUTypeMenu = selectFirstEnabledMenuItem(cpuTypeMenu); for (int m = 0; m < menu.getItemCount(); m++) {
} else { JMenuItem menuItem = menu.getItem(m);
selectedCPUTypeMenu = selectMenuItemByBoardPackagePlatform(cpuTypeMenu, selBoard, selPackage, selPlatform); menuItem.setVisible(menuItem.getAction().getValue("board").equals(boardID));
if (selectedCPUTypeMenu == null) { }
selectedCPUTypeMenu = selectFirstEnabledMenuItem(cpuTypeMenu); 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) { private static JMenuItem selectVisibleSelectedOrFirstMenuItem(JMenu menu) {
JMenuItem firstVisible = null; JMenuItem firstVisible = null;
@ -1283,45 +1331,6 @@ public class Base {
throw new IllegalStateException("Menu has no enabled items"); 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) { public void rebuildProgrammerMenu(JMenu menu) {
menu.removeAll(); menu.removeAll();
ButtonGroup group = new ButtonGroup(); ButtonGroup group = new ButtonGroup();
@ -1809,10 +1818,22 @@ public class Base {
return getTargetPlatform(pack, Preferences.get("target_platform")); return getTargetPlatform(pack, Preferences.get("target_platform"));
} }
static public PreferencesMap getBoardPreferences() { static public Map<String, String> getBoardPreferences() {
TargetPlatform target = getTargetPlatform(); TargetPlatform target = getTargetPlatform();
String board = Preferences.get("board"); 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() { static public File getSketchbookFolder() {

View File

@ -35,6 +35,7 @@ import java.awt.print.*;
import java.io.*; import java.io.*;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import java.util.List;
import java.util.zip.*; import java.util.zip.*;
import javax.swing.*; 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 // 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 // are the same for all windows (since the board and serial port that are
// actually used are determined by the preferences, which are shared) // actually used are determined by the preferences, which are shared)
static JMenu boardsMenu; static List<JMenu> boardsMenus;
static JMenu serialMenu; static JMenu serialMenu;
static JMenu cpuTypeMenu;
static SerialMenuListener serialMenuListener; static SerialMenuListener serialMenuListener;
static SerialMonitor serialMonitor; 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 // re-add the sub-menus that are shared by all windows
fileMenu.insert(sketchbookMenu, 2); fileMenu.insert(sketchbookMenu, 2);
fileMenu.insert(examplesMenu, 3); fileMenu.insert(examplesMenu, 3);
//sketchMenu.insert(importMenu, 4); sketchMenu.insert(importMenu, 4);
toolsMenu.insert(boardsMenu, numTools); int offset = 0;
toolsMenu.insert(cpuTypeMenu, numTools + 1); for (JMenu menu : boardsMenus) {
toolsMenu.insert(serialMenu, numTools + 2); toolsMenu.insert(menu, numTools + offset);
offset++;
}
toolsMenu.insert(serialMenu, numTools + offset);
} }
// added for 1.0.5 // added for 1.0.5
@ -190,9 +193,10 @@ public class Editor extends JFrame implements RunnerListener {
// System.err.println("deactivate"); // not coming through // System.err.println("deactivate"); // not coming through
fileMenu.remove(sketchbookMenu); fileMenu.remove(sketchbookMenu);
fileMenu.remove(examplesMenu); fileMenu.remove(examplesMenu);
//sketchMenu.remove(importMenu); sketchMenu.remove(importMenu);
toolsMenu.remove(boardsMenu); for (JMenu menu : boardsMenus) {
toolsMenu.remove(cpuTypeMenu); toolsMenu.remove(menu);
}
toolsMenu.remove(serialMenu); 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 // XXX: DAM: these should probably be implemented using the Tools plugin
// API, if possible (i.e. if it supports custom actions, etc.) // API, if possible (i.e. if it supports custom actions, etc.)
if (boardsMenu == null) { if (boardsMenus == null) {
boardsMenu = new JMenu(_("Board")); boardsMenus = new LinkedList<JMenu>();
cpuTypeMenu = new JMenu(_("Processor")); base.rebuildBoardsMenu(toolsMenu, this);
base.rebuildBoardsMenu(boardsMenu, cpuTypeMenu, this);
//Debug: rebuild imports //Debug: rebuild imports
importMenu.removeAll(); importMenu.removeAll();
base.rebuildImportMenu(importMenu, this); base.rebuildImportMenu(importMenu, this);
} }
menu.add(boardsMenu);
menu.add(cpuTypeMenu);
if (serialMenuListener == null) if (serialMenuListener == null)
serialMenuListener = new SerialMenuListener(); serialMenuListener = new SerialMenuListener();
@ -2660,7 +2661,7 @@ public class Editor extends JFrame implements RunnerListener {
// . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
protected void onBoardOrPortChange() { protected void onBoardOrPortChange() {
Map<String, String> boardPreferences = Base.getBoardPreferences(); Map<String, String> boardPreferences = Base.getBoardPreferences();
lineStatus.setBoardName(boardPreferences.get("name")); lineStatus.setBoardName(boardPreferences.get("name"));
lineStatus.setSerialPort(Preferences.get("serial.port")); lineStatus.setSerialPort(Preferences.get("serial.port"));
lineStatus.repaint(); lineStatus.repaint();

View File

@ -30,6 +30,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import processing.app.tools.MapWithSubkeys;
import processing.core.PApplet; import processing.core.PApplet;
public class TargetPlatform { public class TargetPlatform {
@ -39,6 +40,7 @@ public class TargetPlatform {
private List<String> boardsOrder; private List<String> boardsOrder;
private Map<String, PreferencesMap> programmers; private Map<String, PreferencesMap> programmers;
private PreferencesMap preferences; private PreferencesMap preferences;
private MapWithSubkeys customMenus;
public TargetPlatform(String _name, File _folder) { public TargetPlatform(String _name, File _folder) {
System.out.println("TargetPlatform: constructor start, name: " + _name); System.out.println("TargetPlatform: constructor start, name: " + _name);
@ -55,9 +57,12 @@ public class TargetPlatform {
PreferencesMap boardPreferences = new PreferencesMap(); PreferencesMap boardPreferences = new PreferencesMap();
boardPreferences.load(boardsFile); boardPreferences.load(boardsFile);
boards = boardPreferences.createFirstLevelMap(); boards = boardPreferences.createFirstLevelMap();
customMenus = MapWithSubkeys.createFrom(boards.get("menu"));
boards.remove("menu");
boardsOrder = readBoardsOrder(boardsFile); boardsOrder = readBoardsOrder(boardsFile);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
System.err.println("Error loading boards from boards.txt: " + e); System.err.println("Error loading boards from boards.txt: " + e);
} }
@ -119,7 +124,11 @@ public class TargetPlatform {
public Map<String, PreferencesMap> getBoards() { public Map<String, PreferencesMap> getBoards() {
return boards; return boards;
} }
public MapWithSubkeys getCustomMenus() {
return customMenus;
}
public List<String> getOrderedBoards() { public List<String> getOrderedBoards() {
return boardsOrder; return boardsOrder;
} }

View 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;
}
}

View 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);
}
}

View 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"));
}
}

View 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

View File

@ -1,5 +1,9 @@
# See: http://code.google.com/p/arduino/wiki/Platforms # See: http://code.google.com/p/arduino/wiki/Platforms
menu.cpu=Processor
#FIXME
menu.speed=Speed
############################################################## ##############################################################
uno.name=Arduino Uno uno.name=Arduino Uno
@ -67,52 +71,45 @@ diecimila.build.variant=standard
############################################################## ##############################################################
nano328.name=Arduino Nano w/ ATmega328 nano.name=Arduino Nano
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.upload.tool=avrdude nano.upload.tool=avrdude
nano.upload.protocol=arduino nano.upload.protocol=arduino
nano.upload.maximum_size=14336
nano.upload.speed=19200
nano.bootloader.tool=avrdude 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.f_cpu=16000000L
nano.build.core=arduino nano.build.core=arduino
nano.build.variant=eightanaloginputs 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 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 mini.name=Arduino Mini
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.upload.tool=avrdude mini.upload.tool=avrdude
mini.upload.protocol=arduino mini.upload.protocol=arduino
mini.upload.maximum_size=14336
mini.upload.speed=19200
mini.bootloader.tool=avrdude mini.bootloader.tool=avrdude
mini.bootloader.low_fuses=0xff 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.unlock_bits=0x3F
mini.bootloader.lock_bits=0x0F mini.bootloader.lock_bits=0x0F
mini.build.mcu=atmega168
mini.build.f_cpu=16000000L mini.build.f_cpu=16000000L
mini.build.core=arduino mini.build.core=arduino
mini.build.variant=eightanaloginputs 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 ethernet.name=Arduino Ethernet