Added File > Recent menu: shows last 5 opened sketches, sorted in reverse chronological order

This commit is contained in:
Federico Fissore 2015-06-01 17:08:10 +02:00
parent e375571945
commit b0cb2c4e52
3 changed files with 121 additions and 33 deletions

View File

@ -86,6 +86,8 @@ public class Base {
} }
}; };
private static final int RECENT_SKETCHES_MAX_SIZE = 5;
private static boolean commandLine; private static boolean commandLine;
public static volatile Base INSTANCE; public static volatile Base INSTANCE;
@ -117,6 +119,7 @@ public class Base {
private volatile Action openBoardsManager; private volatile Action openBoardsManager;
private final PdeKeywords pdeKeywords; private final PdeKeywords pdeKeywords;
private final List<JMenuItem> recentSketchesMenuItems;
static public void main(String args[]) throws Exception { static public void main(String args[]) throws Exception {
System.setProperty("awt.useSystemAAFontSettings", "on"); System.setProperty("awt.useSystemAAFontSettings", "on");
@ -269,6 +272,7 @@ public class Base {
public Base(String[] args) throws Exception { public Base(String[] args) throws Exception {
BaseNoGui.notifier = new GUIUserNotifier(this); BaseNoGui.notifier = new GUIUserNotifier(this);
this.recentSketchesMenuItems = new LinkedList<JMenuItem>();
String sketchbookPath = BaseNoGui.getSketchbookPath(); String sketchbookPath = BaseNoGui.getSketchbookPath();
@ -316,7 +320,7 @@ public class Base {
boolean showEditor = parser.isGuiMode(); boolean showEditor = parser.isGuiMode();
if (!parser.isForceSavePrefs()) if (!parser.isForceSavePrefs())
PreferencesData.setDoSave(showEditor); PreferencesData.setDoSave(showEditor);
if (handleOpen(file, nextEditorLocation(), showEditor) == null) { if (handleOpen(file, nextEditorLocation(), showEditor, false) == null) {
String mess = I18n.format(_("Failed to open sketch: \"{0}\""), path); String mess = I18n.format(_("Failed to open sketch: \"{0}\""), path);
// Open failure is fatal in upload/verify mode // Open failure is fatal in upload/verify mode
if (parser.isVerifyOrUploadMode()) if (parser.isVerifyOrUploadMode())
@ -547,7 +551,7 @@ public class Base {
location = nextEditorLocation(); location = nextEditorLocation();
} }
// If file did not exist, null will be returned for the Editor // If file did not exist, null will be returned for the Editor
if (handleOpen(new File(path), location, true, false) != null) { if (handleOpen(new File(path), location, true, false, false) != null) {
opened++; opened++;
} }
} }
@ -594,12 +598,25 @@ public class Base {
PreferencesData.setInteger("last.sketch.count", index); PreferencesData.setInteger("last.sketch.count", index);
} }
protected void storeRecentSketches(Sketch sketch) {
if (sketch.isUntitled()) {
return;
}
Set<String> sketches = new LinkedHashSet<String>();
sketches.add(sketch.getMainFilePath());
sketches.addAll(PreferencesData.getCollection("recent.sketches"));
PreferencesData.setCollection("recent.sketches", sketches);
}
// Because of variations in native windowing systems, no guarantees about // Because of variations in native windowing systems, no guarantees about
// changes to the focused and active Windows can be made. Developers must // changes to the focused and active Windows can be made. Developers must
// never assume that this Window is the focused or active Window until this // never assume that this Window is the focused or active Window until this
// Window receives a WINDOW_GAINED_FOCUS or WINDOW_ACTIVATED event. // Window receives a WINDOW_GAINED_FOCUS or WINDOW_ACTIVATED event.
protected void handleActivated(Editor whichEditor) { protected void handleActivated(Editor whichEditor) {
activeEditor = whichEditor; activeEditor = whichEditor;
activeEditor.rebuildRecentSketchesMenu();
// set the current window to be the console that's getting output // set the current window to be the console that's getting output
EditorConsoleStream.setCurrent(activeEditor.console); EditorConsoleStream.setCurrent(activeEditor.console);
@ -728,8 +745,7 @@ public class Base {
try { try {
File file = createNewUntitled(); File file = createNewUntitled();
if (file != null) { if (file != null) {
Editor editor = handleOpen(file); Editor editor = handleOpen(file, true);
editor.untitled = true;
} }
} catch (IOException e) { } catch (IOException e) {
@ -837,14 +853,18 @@ public class Base {
* @throws Exception * @throws Exception
*/ */
public Editor handleOpen(File file) throws Exception { public Editor handleOpen(File file) throws Exception {
return handleOpen(file, nextEditorLocation(), true); return handleOpen(file, false);
} }
protected Editor handleOpen(File file, int[] location, boolean showEditor) throws Exception { public Editor handleOpen(File file, boolean untitled) throws Exception {
return handleOpen(file, location, showEditor, true); return handleOpen(file, nextEditorLocation(), true, untitled);
} }
protected Editor handleOpen(File file, int[] location, boolean showEditor, boolean storeOpenedSketches) throws Exception { protected Editor handleOpen(File file, int[] location, boolean showEditor, boolean untitled) throws Exception {
return handleOpen(file, location, showEditor, true, untitled);
}
protected Editor handleOpen(File file, int[] location, boolean showEditor, boolean storeOpenedSketches, boolean untitled) throws Exception {
if (!file.exists()) return null; if (!file.exists()) return null;
// Cycle through open windows to make sure that it's not already open. // Cycle through open windows to make sure that it's not already open.
@ -863,12 +883,16 @@ public class Base {
return null; // Just walk away quietly return null; // Just walk away quietly
} }
editor.untitled = untitled;
editors.add(editor); editors.add(editor);
if (storeOpenedSketches) { if (storeOpenedSketches) {
// Store information on who's open and running // Store information on who's open and running
// (in case there's a crash or something that can't be recovered) // (in case there's a crash or something that can't be recovered)
storeSketches(); storeSketches();
storeRecentSketches(editor.getSketch());
rebuildRecentSketchesMenuItems();
PreferencesData.save(); PreferencesData.save();
} }
@ -886,6 +910,42 @@ public class Base {
return editor; return editor;
} }
protected void rebuildRecentSketchesMenuItems() {
Set<File> recentSketches = new LinkedHashSet<File>() {
@Override
public boolean add(File file) {
if (size() >= RECENT_SKETCHES_MAX_SIZE) {
return false;
}
return super.add(file);
}
};
for (String path : PreferencesData.getCollection("recent.sketches")) {
File file = new File(path);
if (file.exists()) {
recentSketches.add(file);
}
}
recentSketchesMenuItems.clear();
for (final File recentSketch : recentSketches) {
JMenuItem recentSketchMenuItem = new JMenuItem(recentSketch.getParentFile().getName());
recentSketchMenuItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent actionEvent) {
try {
handleOpen(recentSketch);
} catch (Exception e) {
e.printStackTrace();
}
}
});
recentSketchesMenuItems.add(recentSketchMenuItem);
}
}
/** /**
* Close a sketch as specified by its editor window. * Close a sketch as specified by its editor window.
@ -912,6 +972,7 @@ public class Base {
//ignore //ignore
} }
storeSketches(); storeSketches();
rebuildRecentSketchesMenuItems();
// Save out the current prefs state // Save out the current prefs state
PreferencesData.save(); PreferencesData.save();
@ -2463,4 +2524,8 @@ public class Base {
public PdeKeywords getPdeKeywords() { public PdeKeywords getPdeKeywords() {
return pdeKeywords; return pdeKeywords;
} }
public List<JMenuItem> getRecentSketchesMenuItems() {
return recentSketchesMenuItems;
}
} }

View File

@ -71,6 +71,7 @@ import cc.arduino.packages.uploaders.SerialUploader;
public class Editor extends JFrame implements RunnerListener { public class Editor extends JFrame implements RunnerListener {
private final Platform platform; private final Platform platform;
private JMenu recentSketchesMenu;
private static class ShouldSaveIfModified implements Predicate<Sketch> { private static class ShouldSaveIfModified implements Predicate<Sketch> {
@ -523,10 +524,10 @@ public class Editor extends JFrame implements RunnerListener {
public void menuSelected(MenuEvent e) { public void menuSelected(MenuEvent e) {
List<Component> components = Arrays.asList(fileMenu.getComponents()); List<Component> components = Arrays.asList(fileMenu.getComponents());
if (!components.contains(sketchbookMenu)) { if (!components.contains(sketchbookMenu)) {
fileMenu.insert(sketchbookMenu, 2); fileMenu.insert(sketchbookMenu, 3);
} }
if (!components.contains(sketchbookMenu)) { if (!components.contains(sketchbookMenu)) {
fileMenu.insert(examplesMenu, 3); fileMenu.insert(examplesMenu, 4);
} }
fileMenu.revalidate(); fileMenu.revalidate();
validate(); validate();
@ -603,6 +604,16 @@ public class Editor extends JFrame implements RunnerListener {
}); });
fileMenu.add(item); fileMenu.add(item);
base.rebuildRecentSketchesMenuItems();
recentSketchesMenu = new JMenu(_("Recent"));
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
rebuildRecentSketchesMenu();
}
});
fileMenu.add(recentSketchesMenu);
if (sketchbookMenu == null) { if (sketchbookMenu == null) {
sketchbookMenu = new JMenu(_("Sketchbook")); sketchbookMenu = new JMenu(_("Sketchbook"));
MenuScroller.setScrollerFor(sketchbookMenu); MenuScroller.setScrollerFor(sketchbookMenu);
@ -684,6 +695,12 @@ public class Editor extends JFrame implements RunnerListener {
return fileMenu; return fileMenu;
} }
public void rebuildRecentSketchesMenu() {
recentSketchesMenu.removeAll();
for (JMenuItem recentSketchMenuItem : base.getRecentSketchesMenuItems()) {
recentSketchesMenu.add(recentSketchMenuItem);
}
}
protected void buildSketchMenu(JMenu sketchMenu) { protected void buildSketchMenu(JMenu sketchMenu) {
sketchMenu.removeAll(); sketchMenu.removeAll();

View File

@ -1,24 +1,23 @@
package processing.app; package processing.app;
import static processing.app.I18n._; import com.google.common.base.Joiner;
import java.awt.*;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Iterator;
import java.util.MissingResourceException;
import org.apache.commons.compress.utils.IOUtils; import org.apache.commons.compress.utils.IOUtils;
import processing.app.helpers.PreferencesHelper; import processing.app.helpers.PreferencesHelper;
import processing.app.helpers.PreferencesMap; import processing.app.helpers.PreferencesMap;
import processing.app.legacy.PApplet; import processing.app.legacy.PApplet;
import processing.app.legacy.PConstants; import processing.app.legacy.PConstants;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.MissingResourceException;
import static processing.app.I18n._;
public class PreferencesData { public class PreferencesData {
@ -197,8 +196,7 @@ public class PreferencesData {
} }
// get a copy of the Preferences // get a copy of the Preferences
static public PreferencesMap getMap() static public PreferencesMap getMap() {
{
return new PreferencesMap(prefs); return new PreferencesMap(prefs);
} }
@ -211,8 +209,7 @@ public class PreferencesData {
// Decide wether changed preferences will be saved. When value is // Decide wether changed preferences will be saved. When value is
// false, Preferences.save becomes a no-op. // false, Preferences.save becomes a no-op.
static public void setDoSave(boolean value) static public void setDoSave(boolean value) {
{
doSave = value; doSave = value;
} }
@ -225,4 +222,13 @@ public class PreferencesData {
} }
return font; return font;
} }
public static Collection<String> getCollection(String key) {
return Arrays.asList(get(key, "").split(","));
}
public static void setCollection(String key, Collection<String> values) {
String value = Joiner.on(',').join(values);
set(key, value);
}
} }