Skip to content

Commit 7893654

Browse files
championswimmerFederico Fissore
authored andcommitted
update Sketch menu, add Save hex option
* Moving Upload options from "File" menu to "Sketch" menu as those are sketch actions more than file actions. Signed-off-by: Arnav Gupta <championswimmer@gmail.com>
1 parent 11327bb commit 7893654

File tree

6 files changed

+154
-41
lines changed

6 files changed

+154
-41
lines changed

app/src/processing/app/Editor.java

Lines changed: 92 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ public class Editor extends JFrame implements RunnerListener {
152152

153153
Runnable runHandler;
154154
Runnable presentHandler;
155+
Runnable runAndSaveHandler;
156+
Runnable presentAndSaveHandler;
155157
Runnable stopHandler;
156158
Runnable exportHandler;
157159
Runnable exportAppHandler;
@@ -563,22 +565,6 @@ public void actionPerformed(ActionEvent e) {
563565
});
564566
fileMenu.add(saveAsMenuItem);
565567

566-
item = newJMenuItem(_("Upload"), 'U');
567-
item.addActionListener(new ActionListener() {
568-
public void actionPerformed(ActionEvent e) {
569-
handleExport(false);
570-
}
571-
});
572-
fileMenu.add(item);
573-
574-
item = newJMenuItemShift(_("Upload Using Programmer"), 'U');
575-
item.addActionListener(new ActionListener() {
576-
public void actionPerformed(ActionEvent e) {
577-
handleExport(true);
578-
}
579-
});
580-
fileMenu.add(item);
581-
582568
fileMenu.addSeparator();
583569

584570
item = newJMenuItemShift(_("Page Setup"), 'P');
@@ -637,14 +623,31 @@ public void actionPerformed(ActionEvent e) {
637623
}
638624
});
639625
sketchMenu.add(item);
626+
627+
item = newJMenuItem(_("Upload"), 'U');
628+
item.addActionListener(new ActionListener() {
629+
public void actionPerformed(ActionEvent e) {
630+
handleExport(false);
631+
}
632+
});
633+
sketchMenu.add(item);
634+
635+
item = newJMenuItemShift(_("Upload Using Programmer"), 'U');
636+
item.addActionListener(new ActionListener() {
637+
public void actionPerformed(ActionEvent e) {
638+
handleExport(true);
639+
}
640+
});
641+
sketchMenu.add(item);
640642

641-
// item = newJMenuItemShift("Verify / Compile (verbose)", 'R');
642-
// item.addActionListener(new ActionListener() {
643-
// public void actionPerformed(ActionEvent e) {
644-
// handleRun(true);
645-
// }
646-
// });
647-
// sketchMenu.add(item);
643+
644+
item = newJMenuItemAlt("Export compiled Binary", 'S');
645+
item.addActionListener(new ActionListener() {
646+
public void actionPerformed(ActionEvent e) {
647+
handleRunAndSave(true);
648+
}
649+
});
650+
sketchMenu.add(item);
648651

649652
// item = new JMenuItem("Stop");
650653
// item.addActionListener(new ActionListener() {
@@ -1508,11 +1511,17 @@ protected void updateRedoState() {
15081511
// abstract from the editor in this fashion.
15091512

15101513

1511-
public void setHandlers(Runnable runHandler, Runnable presentHandler,
1514+
public void setHandlers(Runnable runHandler,
1515+
Runnable presentHandler,
1516+
Runnable runAndSaveHandler,
1517+
Runnable presentAndSaveHandler,
15121518
Runnable stopHandler,
1513-
Runnable exportHandler, Runnable exportAppHandler) {
1519+
Runnable exportHandler,
1520+
Runnable exportAppHandler) {
15141521
this.runHandler = runHandler;
15151522
this.presentHandler = presentHandler;
1523+
this.runAndSaveHandler = runAndSaveHandler;
1524+
this.presentAndSaveHandler = presentAndSaveHandler;
15161525
this.stopHandler = stopHandler;
15171526
this.exportHandler = exportHandler;
15181527
this.exportAppHandler = exportAppHandler;
@@ -1522,6 +1531,8 @@ public void setHandlers(Runnable runHandler, Runnable presentHandler,
15221531
public void resetHandlers() {
15231532
runHandler = new BuildHandler();
15241533
presentHandler = new BuildHandler(true);
1534+
runAndSaveHandler = new BuildAndSaveHandler();
1535+
presentAndSaveHandler = new BuildAndSaveHandler(true);
15251536
stopHandler = new DefaultStopHandler();
15261537
exportHandler = new DefaultExportHandler();
15271538
exportAppHandler = new DefaultExportAppHandler();
@@ -2012,6 +2023,29 @@ public void handleRun(final boolean verbose) {
20122023
// placed on the event thread and causes a hang--bad idea all around.
20132024
new Thread(verbose ? presentHandler : runHandler).start();
20142025
}
2026+
2027+
/**
2028+
* Implements Sketch &rarr; Run and Save.
2029+
* @param verbose Set true to run with verbose output.
2030+
*/
2031+
public void handleRunAndSave(final boolean verbose) {
2032+
internalCloseRunner();
2033+
running = true;
2034+
toolbar.activate(EditorToolbar.RUN);
2035+
status.progress(_("Compiling sketch..."));
2036+
2037+
// do this to advance/clear the terminal window / dos prompt / etc
2038+
for (int i = 0; i < 10; i++) System.out.println();
2039+
2040+
// clear the console on each run, unless the user doesn't want to
2041+
if (Preferences.getBoolean("console.auto_clear")) {
2042+
console.clear();
2043+
}
2044+
2045+
// Cannot use invokeLater() here, otherwise it gets
2046+
// placed on the event thread and causes a hang--bad idea all around.
2047+
new Thread(verbose ? presentAndSaveHandler : runAndSaveHandler).start();
2048+
}
20152049

20162050
class BuildHandler implements Runnable {
20172051

@@ -2029,7 +2063,7 @@ public BuildHandler(boolean verbose) {
20292063
public void run() {
20302064
try {
20312065
sketch.prepare();
2032-
sketch.build(verbose);
2066+
sketch.build(verbose, false);
20332067
statusNotice(_("Done compiling."));
20342068
} catch (PreferencesMapException e) {
20352069
statusError(I18n.format(
@@ -2044,6 +2078,38 @@ public void run() {
20442078
toolbar.deactivate(EditorToolbar.RUN);
20452079
}
20462080
}
2081+
2082+
class BuildAndSaveHandler implements Runnable {
2083+
2084+
private final boolean verbose;
2085+
2086+
public BuildAndSaveHandler() {
2087+
this(false);
2088+
}
2089+
2090+
public BuildAndSaveHandler(boolean verbose) {
2091+
this.verbose = verbose;
2092+
}
2093+
2094+
@Override
2095+
public void run() {
2096+
try {
2097+
sketch.prepare();
2098+
sketch.build(verbose, true);
2099+
statusNotice(_("Done compiling."));
2100+
} catch (PreferencesMapException e) {
2101+
statusError(I18n.format(
2102+
_("Error while compiling: missing '{0}' configuration parameter"),
2103+
e.getMessage()));
2104+
} catch (Exception e) {
2105+
status.unprogress();
2106+
statusError(e);
2107+
}
2108+
2109+
status.unprogress();
2110+
toolbar.deactivate(EditorToolbar.RUN);
2111+
}
2112+
}
20472113

20482114
class DefaultStopHandler implements Runnable {
20492115
public void run() {

app/src/processing/app/Sketch.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1133,8 +1133,8 @@ public void prepare() throws IOException {
11331133
* @return null if compilation failed, main class name if not
11341134
* @throws RunnerException
11351135
*/
1136-
public String build(boolean verbose) throws RunnerException, PreferencesMapException {
1137-
return build(tempBuildFolder.getAbsolutePath(), verbose);
1136+
public String build(boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
1137+
return build(tempBuildFolder.getAbsolutePath(), verbose, save);
11381138
}
11391139

11401140
/**
@@ -1146,7 +1146,7 @@ public String build(boolean verbose) throws RunnerException, PreferencesMapExcep
11461146
*
11471147
* @return null if compilation failed, main class name if not
11481148
*/
1149-
public String build(String buildPath, boolean verbose) throws RunnerException, PreferencesMapException {
1149+
public String build(String buildPath, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
11501150
// run the preprocessor
11511151
editor.status.progressUpdate(20);
11521152

@@ -1159,7 +1159,7 @@ public void progress(int percent) {
11591159
}
11601160
};
11611161

1162-
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose);
1162+
return Compiler.build(data, buildPath, tempBuildFolder, pl, verbose, save);
11631163
}
11641164

11651165
protected boolean exportApplet(boolean usingProgrammer) throws Exception {
@@ -1177,7 +1177,7 @@ public boolean exportApplet(String appletPath, boolean usingProgrammer)
11771177

11781178
// build the sketch
11791179
editor.status.progressNotice(_("Compiling sketch..."));
1180-
String foundName = build(appletPath, false);
1180+
String foundName = build(appletPath, false, false);
11811181
// (already reported) error during export, exit this function
11821182
if (foundName == null) return false;
11831183

arduino-core/src/processing/app/BaseNoGui.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ static public void init(String[] args) throws Exception {
496496
// - calls Sketch.build(verbose=false) that calls Sketch.ensureExistence(), set progressListener and calls Compiler.build()
497497
// - calls Sketch.upload() (see later...)
498498
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
499-
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
499+
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
500500
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
501501
showMessage(_("Done compiling"), _("Done compiling"));
502502

@@ -541,7 +541,7 @@ static public void init(String[] args) throws Exception {
541541
// if (!data.getFolder().exists()) showError(...);
542542
// String ... = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, verbose);
543543
if (!data.getFolder().exists()) showError(_("No sketch"), _("Can't find the sketch in the specified path"), null);
544-
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild());
544+
String suggestedClassName = Compiler.build(data, tempBuildFolder.getAbsolutePath(), tempBuildFolder, null, parser.isDoVerboseBuild(), false);
545545
if (suggestedClassName == null) showError(_("Error while verifying"), _("An error occurred while verifying the sketch"), null);
546546
showMessage(_("Done compiling"), _("Done compiling"));
547547
} catch (Exception e) {

arduino-core/src/processing/app/debug/Compiler.java

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ public class Compiler implements MessageConsumer {
6767
private SketchData sketch;
6868
private PreferencesMap prefs;
6969
private boolean verbose;
70+
private boolean saveHex;
7071

7172
private List<File> objectFiles;
7273

@@ -83,7 +84,7 @@ public interface ProgressListener {
8384

8485
private ProgressListener progressListener;
8586

86-
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose) throws RunnerException, PreferencesMapException {
87+
static public String build(SketchData data, String buildPath, File tempBuildFolder, ProgressListener progListener, boolean verbose, boolean save) throws RunnerException, PreferencesMapException {
8788
if (SketchData.checkSketchFile(data.getPrimaryFile()) == null)
8889
BaseNoGui.showError(_("Bad file selected"),
8990
_("Bad sketch primary file or bad sketch directory structure"), null);
@@ -113,7 +114,7 @@ static public String build(SketchData data, String buildPath, File tempBuildFold
113114
// compile the program. errors will happen as a RunnerException
114115
// that will bubble up to whomever called build().
115116
try {
116-
if (compiler.compile(verbose)) {
117+
if (compiler.compile(verbose, save)) {
117118
compiler.size(compiler.getBuildPreferences());
118119
return primaryClassName;
119120
}
@@ -350,10 +351,11 @@ protected void size(PreferencesMap prefs) throws RunnerException {
350351
* @return true if successful.
351352
* @throws RunnerException Only if there's a problem. Only then.
352353
*/
353-
public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapException {
354+
public boolean compile(boolean _verbose, boolean _save) throws RunnerException, PreferencesMapException {
354355
preprocess(prefs.get("build.path"));
355356

356357
verbose = _verbose || PreferencesData.getBoolean("build.verbose");
358+
saveHex = _save;
357359
sketchIsCompiled = false;
358360

359361
// Hook runs at Start of Compilation
@@ -399,26 +401,26 @@ public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapE
399401
}
400402

401403
// 1. compile the sketch (already in the buildPath)
402-
progressListener.progress(30);
404+
progressListener.progress(20);
403405
compileSketch(includeFolders);
404406
sketchIsCompiled = true;
405407

406408
// 2. compile the libraries, outputting .o files to: <buildPath>/<library>/
407409
// Doesn't really use configPreferences
408-
progressListener.progress(40);
410+
progressListener.progress(30);
409411
compileLibraries(includeFolders);
410412

411413
// 3. compile the core, outputting .o files to <buildPath> and then
412414
// collecting them into the core.a library file.
413-
progressListener.progress(50);
415+
progressListener.progress(40);
414416
compileCore();
415417

416418
// 4. link it all together into the .elf file
417-
progressListener.progress(60);
419+
progressListener.progress(50);
418420
compileLink();
419421

420422
// 5. run objcopy to generate output files
421-
progressListener.progress(75);
423+
progressListener.progress(60);
422424
List<String> objcopyPatterns = new ArrayList<String>();
423425
for (String key : prefs.keySet()) {
424426
if (key.startsWith("recipe.objcopy.") && key.endsWith(".pattern"))
@@ -429,6 +431,12 @@ public boolean compile(boolean _verbose) throws RunnerException, PreferencesMapE
429431
runRecipe(recipe);
430432
}
431433

434+
// 7. save the hex file
435+
if (saveHex) {
436+
progressListener.progress(80);
437+
saveHex();
438+
}
439+
432440
progressListener.progress(90);
433441

434442
// Hook runs at End of Compilation
@@ -1144,6 +1152,37 @@ void runRecipe(String recipe) throws RunnerException, PreferencesMapException {
11441152
}
11451153
execAsynchronously(cmdArray);
11461154
}
1155+
1156+
//7. Save the .hex file
1157+
void saveHex() throws RunnerException {
1158+
PreferencesMap dict = new PreferencesMap(prefs);
1159+
dict.put("ide_version", "" + BaseNoGui.REVISION);
1160+
1161+
String[] cmdArray;
1162+
try {
1163+
String tmp_file = prefs.getOrExcept("recipe.hex.tmp_file");
1164+
tmp_file = StringReplacer.replaceFromMapping(tmp_file, dict);
1165+
String save_file = prefs.getOrExcept("recipe.hex.save_file");
1166+
save_file = StringReplacer.replaceFromMapping(save_file, dict);
1167+
1168+
File hexFile = new File(prefs.get("build.path") + "/" + tmp_file);
1169+
File saveFile = new File(sketch.getFolder().getAbsolutePath() + "/" + save_file);
1170+
1171+
FileReader in = new FileReader(hexFile);
1172+
FileWriter out = new FileWriter(saveFile);
1173+
1174+
int c;
1175+
while ((c = in.read()) != -1)
1176+
out.write(c);
1177+
1178+
in.close();
1179+
out.close();
1180+
1181+
} catch (Exception e) {
1182+
throw new RunnerException(e);
1183+
}
1184+
}
1185+
11471186

11481187
private static String prepareIncludes(List<File> includeFolders) {
11491188
String res = "";

hardware/arduino/avr/platform.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,10 @@ recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.f
7171
recipe.objcopy.eep.pattern="{compiler.path}{compiler.objcopy.cmd}" {compiler.objcopy.eep.flags} {compiler.objcopy.eep.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.eep"
7272
recipe.objcopy.hex.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex"
7373

74+
## Save hex
75+
recipe.hex.tmp_file={build.project_name}.hex
76+
recipe.hex.save_file={build.project_name}.{build.variant}.hex
77+
7478
## Compute size
7579
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
7680
recipe.size.regex=^(?:\.text|\.data|\.bootloader)\s+([0-9]+).*

hardware/arduino/sam/platform.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,10 @@ recipe.c.combine.pattern="{compiler.path}{compiler.c.elf.cmd}" {compiler.c.elf.f
7575
## Create output (.bin file)
7676
recipe.objcopy.bin.pattern="{compiler.path}{compiler.elf2hex.cmd}" {compiler.elf2hex.flags} {compiler.elf2hex.extra_flags} "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin"
7777

78+
## Save hex
79+
recipe.hex.tmp_file={build.project_name}.bin
80+
recipe.hex.save_file={build.project_name}.{build.variant}.bin
81+
7882
## Compute size
7983
recipe.size.pattern="{compiler.path}{compiler.size.cmd}" -A "{build.path}/{build.project_name}.elf"
8084
recipe.size.regex=\.text\s+([0-9]+).*

0 commit comments

Comments
 (0)