Skip to content

Commit 02447a0

Browse files
Shigeru KANEMOTOffissore
Shigeru KANEMOTO
authored andcommitted
Portable Arduino
Use Arduino on USB flash stick and without affecting anything on your PC. To use this feature, simply make a folder named "portable" in the application root folder where there are "hardware", "examples", "lib" and others. In this mode, file association setting is disabled in the preferences dialog. The sketch book folder is inside the "portable" folder. This may be confusing especially for Mac OSX "Arduino.app" folder.
1 parent c596edd commit 02447a0

File tree

4 files changed

+150
-5
lines changed

4 files changed

+150
-5
lines changed

app/src/processing/app/Base.java

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ public class Base {
111111
List<Editor> editors = Collections.synchronizedList(new ArrayList<Editor>());
112112
Editor activeEditor;
113113

114+
static File portableFolder = null;
115+
static final String portableSketchbookFolder = "sketchbook";
116+
114117

115118
static public void main(String args[]) throws Exception {
116119
initPlatform();
@@ -156,6 +159,13 @@ static public void main(String args[]) throws Exception {
156159
}
157160
*/
158161

162+
initPlatform();
163+
164+
// Portable folder
165+
portableFolder = getContentFile("portable");
166+
if (!portableFolder.exists())
167+
portableFolder = null;
168+
159169
// // Set the look and feel before opening the window
160170
// try {
161171
// platform.setLookAndFeel();
@@ -249,8 +259,12 @@ public Base(String[] args) throws Exception {
249259
// If a value is at least set, first check to see if the folder exists.
250260
// If it doesn't, warn the user that the sketchbook folder is being reset.
251261
if (sketchbookPath != null) {
252-
File skechbookFolder = new File(sketchbookPath);
253-
if (!skechbookFolder.exists()) {
262+
File sketchbookFolder;
263+
if (portableFolder != null)
264+
sketchbookFolder = new File(portableFolder, sketchbookPath);
265+
else
266+
sketchbookFolder = new File(sketchbookPath);
267+
if (!sketchbookFolder.exists()) {
254268
Base.showWarning(_("Sketchbook folder disappeared"),
255269
_("The sketchbook folder no longer exists.\n" +
256270
"Arduino will switch to the default sketchbook\n" +
@@ -264,7 +278,10 @@ public Base(String[] args) throws Exception {
264278
// If no path is set, get the default sketchbook folder for this platform
265279
if (sketchbookPath == null) {
266280
File defaultFolder = getDefaultSketchbookFolder();
267-
Preferences.set("sketchbook.path", defaultFolder.getAbsolutePath());
281+
if (portableFolder != null)
282+
Preferences.set("sketchbook.path", portableSketchbookFolder);
283+
else
284+
Preferences.set("sketchbook.path", defaultFolder.getAbsolutePath());
268285
if (!defaultFolder.exists()) {
269286
defaultFolder.mkdirs();
270287
}
@@ -422,6 +439,15 @@ protected boolean restoreSketches() {
422439
int opened = 0;
423440
for (int i = 0; i < count; i++) {
424441
String path = Preferences.get("last.sketch" + i + ".path");
442+
if (portableFolder != null) {
443+
File absolute = new File(portableFolder, path);
444+
try {
445+
path = absolute.getCanonicalPath();
446+
}
447+
catch (IOException e) {
448+
// path unchanged.
449+
}
450+
}
425451
int[] location;
426452
if (windowPositionValid) {
427453
String locationStr = Preferences.get("last.sketch" + i + ".location");
@@ -460,6 +486,11 @@ protected void storeSketches() {
460486
!editor.getSketch().isModified()) {
461487
continue;
462488
}
489+
if (portableFolder != null) {
490+
path = RelativePath.relativePath(portableFolder.toString(), path);
491+
if (path == null)
492+
continue;
493+
}
463494
Preferences.set("last.sketch" + index + ".path", path);
464495

465496
int[] location = editor.getPlacement();
@@ -478,6 +509,11 @@ protected void storeSketchPath(Editor editor, int index) {
478509
String untitledPath = untitledFolder.getAbsolutePath();
479510
if (path.startsWith(untitledPath)) {
480511
path = "";
512+
} else
513+
if (portableFolder != null) {
514+
path = RelativePath.relativePath(portableFolder.toString(), path);
515+
if (path == null)
516+
path = "";
481517
}
482518
Preferences.set("last.sketch" + index + ".path", path);
483519
}
@@ -1759,6 +1795,9 @@ static public boolean isLinux() {
17591795

17601796

17611797
static public File getSettingsFolder() {
1798+
if (portableFolder != null)
1799+
return portableFolder;
1800+
17621801
File settingsFolder = null;
17631802

17641803
String preferencesPath = Preferences.get("settings.path");
@@ -1938,7 +1977,19 @@ static public Map<String, String> getBoardPreferences() {
19381977
return boardPreferences;
19391978
}
19401979

1980+
static public File getPortableFolder() {
1981+
return portableFolder;
1982+
}
1983+
1984+
1985+
static public String getPortableSketchbookFolder() {
1986+
return portableSketchbookFolder;
1987+
}
1988+
1989+
19411990
static public File getSketchbookFolder() {
1991+
if (portableFolder != null)
1992+
return new File(portableFolder, Preferences.get("sketchbook.path"));
19421993
return new File(Preferences.get("sketchbook.path"));
19431994
}
19441995

@@ -1971,6 +2022,9 @@ static public File getSketchbookHardwareFolder() {
19712022

19722023

19732024
protected File getDefaultSketchbookFolder() {
2025+
if (portableFolder != null)
2026+
return new File(portableFolder, portableSketchbookFolder);
2027+
19742028
File sketchbookFolder = null;
19752029
try {
19762030
sketchbookFolder = platform.getDefaultSketchbookFolder();

app/src/processing/app/Preferences.java

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,14 @@ public void actionPerformed(ActionEvent e) {
326326
File file =
327327
Base.selectFolder(_("Select new sketchbook location"), dflt, dialog);
328328
if (file != null) {
329-
sketchbookLocationField.setText(file.getAbsolutePath());
329+
String path = file.getAbsolutePath();
330+
if (Base.getPortableFolder() != null) {
331+
path = RelativePath.relativePath(Base.getPortableFolder().toString(), path);
332+
if (path == null) {
333+
path = Base.getPortableSketchbookFolder();
334+
}
335+
}
336+
sketchbookLocationField.setText(path);
330337
}
331338
}
332339
});
@@ -439,6 +446,10 @@ public void actionPerformed(ActionEvent e) {
439446
autoAssociateBox.setBounds(left, top, d.width + 10, d.height);
440447
right = Math.max(right, left + d.width);
441448
top += d.height + GUI_BETWEEN;
449+
450+
// If using portable mode, it's bad manner to change PC setting.
451+
if (Base.getPortableFolder() != null)
452+
autoAssociateBox.setEnabled(false);
442453
}
443454

444455
// More preferences are in the ...
@@ -591,6 +602,12 @@ protected void applyFrame() {
591602
// if the sketchbook path has changed, rebuild the menus
592603
String oldPath = get("sketchbook.path");
593604
String newPath = sketchbookLocationField.getText();
605+
if (newPath.isEmpty()) {
606+
if (Base.getPortableFolder() == null)
607+
newPath = editor.base.getDefaultSketchbookFolder().toString();
608+
else
609+
newPath = Base.getPortableSketchbookFolder();
610+
}
594611
if (!newPath.equals(oldPath)) {
595612
editor.base.rebuildSketchbookMenus();
596613
set("sketchbook.path", newPath);
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
/*
2+
* by Shigeru KANEMOTO at SWITCHSCIENCE.
3+
*/
4+
5+
package processing.app;
6+
7+
import java.io.File;
8+
import java.io.IOException;
9+
10+
class RelativePath {
11+
//
12+
// Compute relative path to "target" from a directory "origin".
13+
//
14+
// If "origin" is not absolute, it is relative from the current directory.
15+
// If "target" is not absolute, it is relative from "origin".
16+
//
17+
public static String relativePath(String origin, String target) {
18+
try {
19+
origin = (new File(origin)).getCanonicalPath();
20+
File targetFile = new File(target);
21+
if (targetFile.isAbsolute())
22+
target = targetFile.getCanonicalPath();
23+
else
24+
target = (new File(origin, target)).getCanonicalPath();
25+
}
26+
catch (IOException e) {
27+
return null;
28+
}
29+
30+
if (origin.equals(target)) {
31+
// origin and target is identical.
32+
return ".";
33+
}
34+
35+
if (origin.equals(File.separator)) {
36+
// origin is root.
37+
return "." + target;
38+
}
39+
40+
String prefix = "";
41+
String root = File.separator;
42+
43+
if (System.getProperty("os.name").indexOf("Windows") != -1) {
44+
if (origin.startsWith("\\\\") || target.startsWith("\\\\")) {
45+
// Windows UNC path not supported.
46+
return null;
47+
}
48+
49+
char originLetter = origin.charAt(0);
50+
char targetLetter = target.charAt(0);
51+
if (Character.isLetter(originLetter) && Character.isLetter(targetLetter)) {
52+
// Windows only
53+
if (originLetter != targetLetter) {
54+
// Drive letters differ
55+
return null;
56+
}
57+
}
58+
59+
prefix = "" + originLetter + ':';
60+
root = prefix + File.separator;
61+
}
62+
63+
String relative = "";
64+
while (!target.startsWith(origin + File.separator)) {
65+
origin = (new File(origin)).getParent();
66+
if (origin.equals(root))
67+
origin = prefix;
68+
relative += "..";
69+
relative += File.separator;
70+
}
71+
72+
return relative + target.substring(origin.length() + 1);
73+
}
74+
}

app/src/processing/app/Sketch.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -826,7 +826,7 @@ protected boolean saveAs() throws IOException {
826826
FileDialog.SAVE);
827827
if (isReadOnly() || isUntitled()) {
828828
// default to the sketchbook folder
829-
fd.setDirectory(Preferences.get("sketchbook.path"));
829+
fd.setDirectory(Base.getSketchbookFolder().getAbsolutePath());
830830
} else {
831831
// default to the parent folder of where this was
832832
fd.setDirectory(folder.getParent());

0 commit comments

Comments
 (0)