diff --git a/.gitignore b/.gitignore index 0ff213c4047..5f5d747e730 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,7 @@ app/pde.jar build/macosx/work/ arduino-core/bin/ arduino-core/arduino-core.jar +lib/* hardware/arduino/bootloaders/caterina_LUFA/Descriptors.o hardware/arduino/bootloaders/caterina_LUFA/Descriptors.lst hardware/arduino/bootloaders/caterina_LUFA/Caterina.sym diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 1e4819bba34..b0648173c70 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -510,7 +510,10 @@ public Base(String[] args) throws Exception { contributionsSelfCheck = new ContributionsSelfCheck(this, new UpdatableBoardsLibsFakeURLsHandler(this), contributionInstaller, libraryInstaller); new Timer(false).schedule(contributionsSelfCheck, Constants.BOARDS_LIBS_UPDATABLE_CHECK_START_PERIOD); } - + // Load the build settings + for(Editor editor: editors){ + editor.findTab(editor.sketch.getPrimaryFile()).loadBuildSettings(this); + } } else if (parser.isNoOpMode()) { // Do nothing (intended for only changing preferences) System.exit(0); @@ -715,10 +718,8 @@ protected int[] nextEditorLocation() { } } - // ................................................................. - boolean breakTime = false; String[] months = { "jan", "feb", "mar", "apr", "may", "jun", diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 2ec29c498cb..9581c2d8d94 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -110,6 +110,34 @@ import processing.app.tools.MenuScroller; import processing.app.tools.Tool; +import javax.swing.*; +import javax.swing.event.*; +import javax.swing.text.BadLocationException; +import java.awt.*; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.event.*; +import java.awt.print.PageFormat; +import java.awt.print.PrinterException; +import java.awt.print.PrinterJob; +import java.io.File; +import java.io.FileFilter; +import java.io.FilenameFilter; +import java.io.IOException; +import java.net.ConnectException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.*; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.ArrayList; + +import static processing.app.I18n.tr; +import static processing.app.Theme.scale; + /** * Main editor panel for the Processing Development Environment. */ @@ -748,6 +776,10 @@ private JMenu buildToolsMenu() { item = new JMenuItem(tr("Get Board Info")); item.addActionListener(e -> handleBoardInfo()); toolsMenu.add(item); + + item = new JMenuItem(tr("Add build settings to .INO file")); + item.addActionListener(e -> handleAddBuildSettings()); + toolsMenu.add(item); toolsMenu.addSeparator(); base.rebuildProgrammerMenu(); @@ -2369,6 +2401,21 @@ public void handlePlotter() { } + public void handleAddBuildSettings(){ + final LinkedHashMap settingsMap = base.getBoardsCustomMenus().stream().filter(JMenu::isVisible).map((e)->{ + String setting = e.getText().substring(0, e.getText().indexOf(":")); + String value = e.getText().replace(setting + ":", "").replace("\"", "").trim(); + return new String[]{setting, value}; + }).collect(LinkedHashMap::new, (map, menu) -> map.put(menu[0], menu[1]), LinkedHashMap::putAll); + handleSave(true); + Optional optionalEditorTab = tabs.stream().filter(tab -> tab.getSketch().getSketch().equals(sketch)).findFirst(); + if(optionalEditorTab.isPresent()){ + optionalEditorTab.get().setText(sketch.setBuildSettings(sketch, settingsMap)); + handleSave(true); + System.out.println("Build settings header should be added"); + } + } + private void handleBurnBootloader() { console.clear(); EditorConsole.setCurrentEditorConsole(this.console); diff --git a/app/src/processing/app/EditorTab.java b/app/src/processing/app/EditorTab.java index 5e8f3e4bfcf..b79de0b99c6 100644 --- a/app/src/processing/app/EditorTab.java +++ b/app/src/processing/app/EditorTab.java @@ -33,13 +33,12 @@ import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.io.IOException; +import java.lang.annotation.Target; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.Optional; -import javax.swing.Action; -import javax.swing.BorderFactory; -import javax.swing.JMenuItem; -import javax.swing.JPanel; -import javax.swing.JPopupMenu; -import javax.swing.ToolTipManager; +import javax.swing.*; import javax.swing.border.MatteBorder; import javax.swing.event.PopupMenuEvent; import javax.swing.event.PopupMenuListener; @@ -57,6 +56,8 @@ import org.fife.ui.rtextarea.RTextScrollPane; import cc.arduino.UpdatableBoardsLibsFakeURLsHandler; +import processing.app.debug.TargetBoard; +import processing.app.debug.TargetPackage; import processing.app.helpers.DocumentTextChangeListener; import processing.app.syntax.ArduinoTokenMakerFactory; import processing.app.syntax.PdeKeywords; @@ -447,6 +448,42 @@ public void setText(String what) { textarea.setLineWrap(textarea.getLineWrap()); } + + /** + * This method loads the build settings from the main .INO file and sets the Arduino IDE accordingly + */ + public void loadBuildSettings(Base base){ + + LinkedHashMap buildSettings = getSketch().getSketch().getBuildSettingsFromProgram(getText()); + + Optional optionalTargetBoard = BaseNoGui.getTargetPlatform().getBoards().values().stream().filter(board -> board.getPreferences().get("name","").equals("Node32s")).findFirst(); + + TargetBoard targetBoard; + if(optionalTargetBoard.isPresent()){ + targetBoard = optionalTargetBoard.get(); + }else{ + return; + } + + for(String readableName : buildSettings.values()){ + base.getBoardsCustomMenus().forEach(menuItem -> { + Optional optionalBoardMenuItem = Arrays.stream(menuItem.getMenuComponents()).filter(subItem->{ + return subItem instanceof JRadioButtonMenuItem && ((JRadioButtonMenuItem)subItem).getText().equals(readableName) && (((JRadioButtonMenuItem) subItem).getAction().getValue("board") == null || (((JRadioButtonMenuItem) subItem).getAction().getValue("board").equals(targetBoard))); + } + ).map(subItem-> { + return subItem instanceof JRadioButtonMenuItem ? (JRadioButtonMenuItem)subItem : new JRadioButtonMenuItem(); + }).findFirst(); + if(optionalBoardMenuItem.isPresent()){ + optionalBoardMenuItem.get().setSelected(true); + optionalBoardMenuItem.get().getAction().actionPerformed(new ActionEvent(this, -1, "")); + }else{ + // TODO Ask the user which value should replace the current value + + } + }); + } + } + /** * Is the text modified since the last save / load? */ diff --git a/arduino-core/src/processing/app/Sketch.java b/arduino-core/src/processing/app/Sketch.java index 6c417403ec9..c9c42bc7f59 100644 --- a/arduino-core/src/processing/app/Sketch.java +++ b/arduino-core/src/processing/app/Sketch.java @@ -139,6 +139,111 @@ public void save() throws IOException { } } + private final String buildToolsHeader = "\n/** Arduino IDE Board Tool details\n"; + private final String buildToolsHeaderEnd = "*/"; + + /** + * Checks the code for a valid build tool header + * @param program The code to scan for the build tools + * @return True if the build tool header was found ONE time. Returns false if found MORE than one time, or not found at all. + */ + private boolean containsBuildSettings(String program){ + return program.contains(buildToolsHeader) && (program.indexOf(buildToolsHeader) == program.lastIndexOf(buildToolsHeader)); + } + + /** + * This function returns the index of the Nth occurrence of the substring in the specified string (http://programming.guide/java/nth-occurrence-in-string.html) + * @param str The string to find the Nth occurrence in + * @param substr The string to find + * @param n The occurrence number you'd like to find + * @return + */ + private static int ordinalIndexOf(String str, String substr, int n) { + int pos = str.indexOf(substr); + while (--n > 0 && pos != -1) + pos = str.indexOf(substr, pos + 1); + return pos; + } + + private String removeBuildSettingsHeader(Sketch sketch){ + if(sketch.getPrimaryFile().getProgram().contains(buildToolsHeader)) { + int headerStartIndex = sketch.getPrimaryFile().getProgram().indexOf(buildToolsHeader); + int headerStopIndex = sketch.getPrimaryFile().getProgram().indexOf(buildToolsHeaderEnd); + if (headerStartIndex > headerStopIndex) { + System.err.println("The build tool header is not the first comment block in your file! Please fix this."); + for (int i = 0; i < sketch.getPrimaryFile().getProgram().length(); i++) { + if (headerStartIndex < ordinalIndexOf(sketch.getPrimaryFile().getProgram(), buildToolsHeaderEnd, i)) { + headerStopIndex = ordinalIndexOf(sketch.getPrimaryFile().getProgram(), buildToolsHeaderEnd, i); + break; + } + } + } + String header = sketch.getPrimaryFile().getProgram().substring(headerStartIndex, headerStopIndex + buildToolsHeaderEnd.length()); + return sketch.getPrimaryFile().getProgram().replace(header, ""); + } + return sketch.getPrimaryFile().getProgram(); + } + + /** + * This checks the program code for a valid build tool settings header and returns the LinkedHashMap with the setting name and the value. + * The build tools header should not be changed or manipulated by the pre-processor as the pre-processors output may depend on the build tools. + * @param program The program code + * @return The {@code LinkedHashMap} with the settings and their values of the first header that was found in the program code + */ + public LinkedHashMap getBuildSettingsFromProgram(String program){ + LinkedHashMap buildSettings = new LinkedHashMap<>(); + if(containsBuildSettings(program)){ + int headerStartIndex = program.indexOf(buildToolsHeader); + int headerStopIndex = program.indexOf(buildToolsHeaderEnd); + if(headerStartIndex > headerStopIndex){ + System.err.println("The build tool header is not the first comment block in your file! Please fix this."); + for(int i = 0; i < program.length(); i++){ + if(headerStartIndex < ordinalIndexOf(program, buildToolsHeaderEnd, i)){ + headerStopIndex = ordinalIndexOf(program, buildToolsHeaderEnd, i); + break; + } + } + } + String header = program.substring(headerStartIndex + buildToolsHeader.length(), headerStopIndex); + + String[] headerLines = header.split("\n"); + + for(int line = 0; line < headerLines.length; line++){ + String[] setting = headerLines[line].replace("*","").trim().split(": "); + if(headerLines[line].indexOf(": ") != (headerLines[line].length() -1)){ + // The value of the setting is not empty + buildSettings.put(setting[0].trim(), setting[1].trim()); + }else{ + buildSettings.put(setting[0], ""); + } + } + }else{ + if(!program.contains(buildToolsHeader)){ + // There are multiple headers, remove them + // TODO Create a dialog asking the user to add a build header to the file + } + } + + return buildSettings; + } + + private boolean isBuildSettingsEqual(LinkedHashMap first, LinkedHashMap second){ + return first.keySet().containsAll(second.keySet()) && first.values().containsAll(second.values()); + } + + public String setBuildSettings(Sketch sketch, LinkedHashMap buildSettings){ + if(sketch != this){ + return ""; + } + + String customBoardSettingsHeader = buildSettings.entrySet().stream().map(entry-> String.format(" * %s: %s\n", entry.getKey(), entry.getValue())).collect(Collectors.joining("", buildToolsHeader, "*/")); + if(!isBuildSettingsEqual(getBuildSettingsFromProgram(sketch.getPrimaryFile().getProgram()),buildSettings)){ + String headerLessProgram = removeBuildSettingsHeader(sketch); + return customBoardSettingsHeader + ((headerLessProgram.charAt(0) == '\n') ? "" : "\n") + headerLessProgram; + } + return ""; + } + public int getCodeCount() { return files.size(); } diff --git a/build/shared/examples/01.Basics/BareMinimum/BareMinimum.ino b/build/shared/examples/01.Basics/BareMinimum/BareMinimum.ino index 95c2b6eb0a8..6586e6e69ab 100644 --- a/build/shared/examples/01.Basics/BareMinimum/BareMinimum.ino +++ b/build/shared/examples/01.Basics/BareMinimum/BareMinimum.ino @@ -1,3 +1,7 @@ +/** Arduino IDE Board Tool details + * Board: Arduino/Genuino Uno +*/ + void setup() { // put your setup code here, to run once: @@ -6,4 +10,4 @@ void setup() { void loop() { // put your main code here, to run repeatedly: -} +} \ No newline at end of file pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy