From d9a9fa44c835838c46aefffd7cb1719bf58737dd Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Thu, 31 Jul 2014 12:29:32 -0400 Subject: [PATCH] cleanups for file watching service --- app/src/processing/app/Editor.java | 97 +++++++++++-------------- app/src/processing/app/Preferences.java | 8 +- build/shared/lib/defaults.txt | 5 +- todo.txt | 5 ++ 4 files changed, 57 insertions(+), 58 deletions(-) diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 1b15e824b..6f4e53531 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -2361,7 +2361,9 @@ public abstract class Editor extends JFrame implements RunnerListener { Base.showWarning("Error", "Could not create the sketch.", e); return false; } - initFileChangeListener(); + if (Preferences.getBoolean("editor.watcher")) { + initFileChangeListener(); + } header.rebuild(); updateTitle(); @@ -2370,7 +2372,7 @@ public abstract class Editor extends JFrame implements RunnerListener { // Store information on who's open and running // (in case there's a crash or something that can't be recovered) -// base.storeSketches(); + // TODO this probably need not be here because of the Recent menu, right? Preferences.save(); // opening was successful @@ -2383,107 +2385,94 @@ public abstract class Editor extends JFrame implements RunnerListener { // } } - //set to true when the sketch is saved from inside processing - private boolean saved; - - private boolean didReload; - //TODO set to the appropriate value - private boolean reloadEnabled = true; + //set to true when the sketch is saved from inside processing + private boolean watcherSave; + private boolean watcherReloaded; //the key which is being used to poll the fs for changes - private WatchKey key = null; + private WatchKey watcherKey = null; private void initFileChangeListener() { - if(!reloadEnabled){ - return; - } try { WatchService watchService = FileSystems.getDefault().newWatchService(); - key = sketch.getFolder().toPath() - .register(watchService, -// StandardWatchEventKinds.ENTRY_CREATE, -// StandardWatchEventKinds.ENTRY_DELETE, - StandardWatchEventKinds.ENTRY_MODIFY); + Path folderPath = sketch.getFolder().toPath(); + watcherKey = folderPath.register(watchService, +// StandardWatchEventKinds.ENTRY_CREATE, +// StandardWatchEventKinds.ENTRY_DELETE, + StandardWatchEventKinds.ENTRY_MODIFY); } catch (IOException e) { - //registring the watch failed, ignore it + e.printStackTrace(); } - final WatchKey finKey = key; + final WatchKey finKey = watcherKey; - //if the key is null for some reason, don't bother attaching a listener to it, they can deal without one + // if the key is null for some reason, don't bother attaching + // a listener to it, they can deal without one if (finKey != null) { - WindowFocusListener fl = new WindowFocusListener() { + // the key can now be polled for changes in the files + addWindowFocusListener(new WindowFocusListener() { @Override public void windowGainedFocus(WindowEvent arg0) { - if (!reloadEnabled) { - return; - } + // check preference here for enabled or not? + //if the directory was deleted, then don't scan - if (!finKey.isValid()) { - return; + if (finKey.isValid()) { + List> events = finKey.pollEvents(); + processFileEvents(events); } - - List> events = finKey.pollEvents(); - processFileEvents(events); } @Override public void windowLostFocus(WindowEvent arg0){ List> events = finKey.pollEvents(); //don't ask to reload a file we saved - if(!saved){ + if (!watcherSave) { processFileEvents(events); } - saved = false; + watcherSave = false; } - }; - //the key can now be polled for changes in the files - this.addWindowFocusListener(fl); - + }); } } + /** - * called when a file is changed - * - * @param events - * the list of events that have occured in the registered folder - * (sketch.getFolder()) + * Called when a file is changed. + * @param events the list of events that have occured in the sketch folder */ private void processFileEvents(List> events) { - didReload = false; + watcherReloaded = false; for (WatchEvent e : events) { //the context is the name of the file inside the path //due to some weird shit, if a file was editted in gedit, the context is .goutputstream-XXXXX //this makes things.... complicated - //System.out.println(e.context()); - + //System.out.println(e.context()); //if we already reloaded in this cycle, then don't reload again - if (didReload){ + if (watcherReloaded){ break; } if (e.kind().equals(StandardWatchEventKinds.ENTRY_MODIFY)) { // Path p = (Path) e.context(); // Path root = (Path) key.watchable(); // Path path = root.resolve(p); - int response = Base - .showYesNoQuestion(Editor.this, "File Modified", - "A file has been modified externally", - "Would you like to reload the sketch?"); + int response = + Base.showYesNoQuestion(Editor.this, "File Modified", + "A file has been modified externally", + "Would you like to reload the sketch?"); if (response == 0) { - //reload the sketch + // reload the sketch sketch.reload(); header.rebuild(); - didReload = true; + watcherReloaded = true; } } else { - //called when a file is created or deleted - //for now, do nothing + // called when a file is created or deleted + // for now, do nothing } } - saved = false; + watcherSave = false; } @@ -2517,7 +2506,7 @@ public abstract class Editor extends JFrame implements RunnerListener { public boolean handleSave(boolean immediately) { // handleStop(); // 0136 - saved = true; + watcherSave = true; if (sketch.isUntitled()) { return handleSaveAs(); // need to get the name, user might also cancel here diff --git a/app/src/processing/app/Preferences.java b/app/src/processing/app/Preferences.java index b03a9b991..3f2dcbc0f 100644 --- a/app/src/processing/app/Preferences.java +++ b/app/src/processing/app/Preferences.java @@ -65,6 +65,8 @@ public class Preferences { static final Integer[] FONT_SIZES = { 10, 12, 14, 18, 24, 36, 48 }; // what to call the feller + // had to rename this file because people were editing it + static final String DEFAULTS_FILE = "defaults.txt"; //$NON-NLS-1$ static final String PREFS_FILE = "preferences.txt"; //$NON-NLS-1$ @@ -142,8 +144,8 @@ public class Preferences { // data model - static HashMap defaults; - static HashMap table = new HashMap(); + static HashMap defaults; + static HashMap table = new HashMap(); static File preferencesFile; @@ -154,7 +156,7 @@ public class Preferences { try { // Name changed for 2.1b2 to avoid problems with users modifying or // replacing the file after doing a search for "preferences.txt". - load(Base.getLibStream("defaults.txt")); //$NON-NLS-1$ + load(Base.getLibStream(DEFAULTS_FILE)); } catch (Exception e) { Base.showError(null, "Could not read default settings.\n" + "You'll need to reinstall Processing.", e); diff --git a/build/shared/lib/defaults.txt b/build/shared/lib/defaults.txt index ea9c388d2..a7e5706a8 100644 --- a/build/shared/lib/defaults.txt +++ b/build/shared/lib/defaults.txt @@ -159,6 +159,9 @@ editor.divider.size = 0 # but keeps it from being annoyingly obtrusive editor.divider.size.windows = 2 +# Whether to automatically reload modified tabs +editor.watcher = true + # Hide the background image. Gross because this is a pref that # really lives over in theme.txt but it's split here. buttons.hide.image = false @@ -349,4 +352,4 @@ pdex.ccEnabled=true pdex.dbgOutput=false pdex.errorCheckEnabled=true pdex.warningsEnabled=true -pdex.writeErrorLogs=false \ No newline at end of file +pdex.writeErrorLogs=false diff --git a/todo.txt b/todo.txt index ad47ff5d9..b0075b6dc 100644 --- a/todo.txt +++ b/todo.txt @@ -1,5 +1,10 @@ 0230 pde (3.0a3) +pulls +X Add polling to detect file system changes +X https://github.com/processing/processing/issues/1939 +X https://github.com/processing/processing/pull/2628 + pending _ huge i18n patch