From 8bc394814aa6eb8e8547e4e68a9c498677fc5592 Mon Sep 17 00:00:00 2001 From: Patrick Vares Date: Sun, 18 Jan 2015 01:14:00 -0500 Subject: [PATCH 1/4] i have no clue what i'm doing --- app/.classpath | 2 +- app/src/processing/app/ChangeDetector.java | 161 +++++++++++++++++++++ app/src/processing/app/Editor.java | 153 ++------------------ app/src/processing/app/EditorHeader.java | 2 - core/src/processing/core/PSurfaceAWT.java | 5 +- 5 files changed, 174 insertions(+), 149 deletions(-) create mode 100644 app/src/processing/app/ChangeDetector.java diff --git a/app/.classpath b/app/.classpath index e12f72e7e..00411841a 100644 --- a/app/.classpath +++ b/app/.classpath @@ -6,7 +6,6 @@ - @@ -19,5 +18,6 @@ + diff --git a/app/src/processing/app/ChangeDetector.java b/app/src/processing/app/ChangeDetector.java new file mode 100644 index 000000000..0d18574d4 --- /dev/null +++ b/app/src/processing/app/ChangeDetector.java @@ -0,0 +1,161 @@ +package processing.app; + +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import java.io.File; +import java.io.FilenameFilter; +import java.io.IOException; + +public class ChangeDetector implements WindowFocusListener { + private Sketch sketch; + + private Editor editor; + + private boolean enabled = true; + + private boolean skip = false; + + public ChangeDetector(Editor editor) { + this.sketch = editor.sketch; + this.editor = editor; + } + + @Override + public void windowGainedFocus(WindowEvent e) { + //remove the detector from main if it is disabled during runtime (due to an error?) + if (!enabled || !Preferences.getBoolean("editor.watcher")) { + editor.removeWindowFocusListener(this); + return; + } + //if they selected no, skip the next focus event + if (skip) { + skip = false; + return; + } + checkFileChange(); + } + + private void checkFileChange() { + //check that the content of each of the files in sketch matches what is in memory + if (sketch == null) { + return; + } + + //check file count first + File sketchFolder = sketch.getFolder(); + int fileCount = sketchFolder.list(new FilenameFilter() { + //return true if the file is a code file for this mode + @Override + public boolean accept(File dir, String name) { + for (String s : editor.getMode().getExtensions()) { + if (name.endsWith(s)) { + return true; + } + } + return false; + } + }).length; + + if (fileCount != sketch.getCodeCount()) { + reloadSketch(null); + if (fileCount < 1) { + try { + //make a blank file + sketch.getMainFile().createNewFile(); + } catch (Exception e1) { + //if that didn't work, tell them it's un-recoverable + Base.showError("Reload failed", "The sketch contains no code files.", + e1); + //don't try to reload again after the double fail + //this editor is probably trashed by this point, but a save-as might be possible + skip = true; + return; + } + //it's okay to do this without confirmation, because they already confirmed to deleting the unsaved changes above + sketch.reload(); + editor.header.rebuild(); + Base + .showWarning("Modified Reload", + "You cannot delete the last code file in a sketch.\n" + + "A new blank sketch file has been generated for you."); + + } + return; + } + + SketchCode[] codes = sketch.getCode(); + for (SketchCode sc : codes) { + String inMemory = sc.getProgram(); + String onDisk = null; + File sketchFile = sc.getFile(); + if (!sketchFile.exists()) { + //if a file in the sketch was not found, then it must have been deleted externally + //so reload the sketch + reloadSketch(sc); + return; + } + try { + onDisk = Base.loadFile(sketchFile); + } catch (IOException e1) { + Base + .showWarningTiered("File Change Detection Failed", + "Checking for changed files for this sketch has failed.", + "The file change detector will be disabled.", e1); + enabled = false; + return; + } + if (onDisk == null) { + //failed + } else if (!inMemory.equals(onDisk)) { + reloadSketch(sc); + return; + } + } + } + + private void setSketchCodeModified(SketchCode sc) { + sc.setModified(true); + sketch.setModified(true); + } + + //returns true if the files in the sketch have been reloaded + private void reloadSketch(SketchCode changed) { + int response = Base + .showYesNoQuestion(editor, + "File Modified", + "Your sketch has been modified externally.
Would you like to reload the sketch?", + "If you reload the sketch, any unsaved changes will be lost!"); + if (response == 0) { + //reload the sketch + + sketch.reload(); + editor.header.rebuild(); + + } else { + //they said no, make it possible for them to stop the errors by saving + if (changed != null) { + //set it to be modified so that it will actually save to disk when the user saves from inside processing + setSketchCodeModified(changed); + } else { + //the number of files changed, so they may be working with a file that doesn't exist any more + //find the files that are missing, and mark them as modified + for (SketchCode sc : sketch.getCode()) { + if (!sc.getFile().exists()) { + setSketchCodeModified(sc); + } + } + //if files were simply added, then nothing needs done + } + editor.header.rebuild(); + skip = true; + return; + } + return; + } + + @Override + public void windowLostFocus(WindowEvent e) { + //shouldn't need to do anything here + } + +} diff --git a/app/src/processing/app/Editor.java b/app/src/processing/app/Editor.java index 1b22f95cb..9b706a202 100644 --- a/app/src/processing/app/Editor.java +++ b/app/src/processing/app/Editor.java @@ -33,7 +33,8 @@ import java.awt.datatransfer.*; import java.awt.event.*; import java.awt.print.*; import java.io.*; -import java.nio.file.*; +//REMOVE +//import java.nio.file.*; import java.util.*; import java.util.List; import java.util.Timer; @@ -286,6 +287,12 @@ public abstract class Editor extends JFrame implements RunnerListener { if (!loaded) { sketch = null; } + + //add a window listener to watch for changes to the files in the sketch + if (Preferences.getBoolean("editor.watcher")) { + addWindowFocusListener(new ChangeDetector(this)); + } + } @@ -2459,10 +2466,6 @@ public abstract class Editor extends JFrame implements RunnerListener { Base.showWarning("Error", "Could not create the sketch.", e); return false; } - // Disabling for 3.0a4 - if (false && Preferences.getBoolean("editor.watcher")) { - initFileChangeListener(); - } header.rebuild(); updateTitle(); @@ -2483,134 +2486,6 @@ public abstract class Editor extends JFrame implements RunnerListener { // return false; // } } - - //used to prevent the fileChangeListener from asking for reloads after internal changes - public void setWatcherSave() { - watcherSave = true; - } - - //set to true when the sketch is saved from inside processing - private boolean watcherSave; - - //the key which is being used to poll the fs for changes - private WatchKey watcherKey = null; - - private void initFileChangeListener() { - try { - WatchService watchService = FileSystems.getDefault().newWatchService(); - Path sp = sketch.getFolder().toPath(); - watcherKey = sp.register(watchService, - StandardWatchEventKinds.ENTRY_CREATE, - StandardWatchEventKinds.ENTRY_DELETE, - StandardWatchEventKinds.ENTRY_MODIFY); - } catch (IOException e) { - e.printStackTrace(); - } - - final WatchKey finKey = watcherKey; - - //if the key is null for some reason, don't bother attaching a listener to it - if (finKey != null) { - // the key can now be polled for changes in the files - addWindowFocusListener(new WindowFocusListener() { - @Override - public void windowGainedFocus(WindowEvent arg0) { - //we switched locations (saveAs), ignore old things - if (watcherKey != finKey) { - return; - } - // check preference here for enabled or not? - - //if the directory was deleted, then don't scan - if (finKey.isValid()) { - List> events = finKey.pollEvents(); - if (!watcherSave) { - processFileEvents(events); - } - } - - List> events = finKey.pollEvents(); - if (!watcherSave) - processFileEvents(events); - } - - @Override - public void windowLostFocus(WindowEvent arg0) { - //we switched locations (saveAs), ignore old things - if (watcherKey != finKey) { - return; - } - List> events = finKey.pollEvents(); - //don't ask to reload a file we saved - if (!watcherSave) { - processFileEvents(events); - } - watcherSave = false; - } - }); - } - } - - - /** - * Called when a file is changed. - * @param events the list of events that have occured in the sketch folder - */ - private void processFileEvents(List> events) { - for (WatchEvent e : events) { - boolean sketchFile = false; - Path file = ((Path) e.context()).getFileName(); - System.out.println(file); - for (String s : getMode().getExtensions()) { - // if it is a change to a file with a known extension - if (file.toString().endsWith(s)) { - sketchFile = true; - break; - } - } - //if the file is not a known type, then go the the next event - if (!sketchFile) { - continue; - } - - int response = - Base.showYesNoQuestion(Editor.this, - "File Modified", - "Your sketch has been modified externally", - "Would you like to reload the sketch?"); - if (response == 0) { - //grab the 'main' code in case this reload tries to delete everything - File sc = sketch.getMainFile(); - //reload the sketch - try { - sketch.reload(); - header.rebuild(); - } catch (Exception f) { - if (sketch.getCodeCount() < 1) { - Base.showWarning("Canceling Reload", - "You cannot delete the last code file in a sketch."); - //if they deleted the last file, re-save the SketchCode - try { - //make a blank file - sc.createNewFile(); - } catch (IOException e1) { - //if that didn't work, tell them it's un-recoverable - Base.showError("Reload failed", "The sketch contains no code files", e1); - //don't try to reload again after the double fail - //this editor is probably trashed by this point, but a save-as might be possible - break; - } - //don't ask for another reload after this save - watcherSave = true; - return; - } - } - //now that we've reloaded once, don't try to reload again - break; - } - } - watcherSave = false; - } /** * Set the title of the PDE window based on the current sketch, i.e. @@ -2641,8 +2516,7 @@ public abstract class Editor extends JFrame implements RunnerListener { */ public boolean handleSave(boolean immediately) { // handleStop(); // 0136 - - setWatcherSave(); + if (sketch.isUntitled()) { return handleSaveAs(); // need to get the name, user might also cancel here @@ -2686,13 +2560,6 @@ public abstract class Editor extends JFrame implements RunnerListener { statusNotice(Language.text("editor.status.saving")); try { if (sketch.saveAs()) { - // Disabling for 3.0a4 - if (false && Preferences.getBoolean("editor.watcher")) { - // "Save As" moves where the files are, so a listener must be - // attached to the new location. - // TODO shouldn't this remove the old listener? - initFileChangeListener(); - } // statusNotice("Done Saving."); // status is now printed from Sketch so that "Done Saving." // is only printed after Save As when progress bar is shown. @@ -3040,7 +2907,7 @@ public abstract class Editor extends JFrame implements RunnerListener { cutItem.setEnabled(active); copyItem.setEnabled(active); discourseItem.setEnabled(active); - + referenceItem.setEnabled(referenceCheck(false) != null); super.show(component, x, y); } diff --git a/app/src/processing/app/EditorHeader.java b/app/src/processing/app/EditorHeader.java index 94e7c50f7..3b4183195 100644 --- a/app/src/processing/app/EditorHeader.java +++ b/app/src/processing/app/EditorHeader.java @@ -516,7 +516,6 @@ public class EditorHeader extends JComponent { @Override public void actionPerformed(ActionEvent e) { editor.getSketch().handleNewCode(); - editor.setWatcherSave(); } }; mapKey = "editor.header.new_tab"; @@ -554,7 +553,6 @@ public class EditorHeader extends JComponent { Language.text("editor.header.delete.warning.text"), null); } else { editor.getSketch().handleDeleteCode(); - editor.setWatcherSave(); } } }; diff --git a/core/src/processing/core/PSurfaceAWT.java b/core/src/processing/core/PSurfaceAWT.java index 35c405b07..c5c6c0c23 100644 --- a/core/src/processing/core/PSurfaceAWT.java +++ b/core/src/processing/core/PSurfaceAWT.java @@ -831,10 +831,9 @@ public class PSurfaceAWT implements PSurface { // canvas.setSize(wide, high); // frame.setSize(wide, high); - if (frame != null) { // canvas only - setFrameSize(); //wide, high); - } + setFrameSize(); //wide, high); setCanvasSize(); + frame.setLocationRelativeTo(null); // if (frame != null) { // frame.setLocationRelativeTo(null); // } From 89ec6f1d27fb06dcd859eb4f3da32d3373ba8890 Mon Sep 17 00:00:00 2001 From: pvrs12 Date: Wed, 21 Jan 2015 09:22:30 -0500 Subject: [PATCH 2/4] FloatList exceptions added --- core/src/processing/data/FloatList.java | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/core/src/processing/data/FloatList.java b/core/src/processing/data/FloatList.java index 700d25b3b..88c575a0a 100644 --- a/core/src/processing/data/FloatList.java +++ b/core/src/processing/data/FloatList.java @@ -428,7 +428,11 @@ public class FloatList implements Iterable { * @brief Add to a value */ public void add(int index, float amount) { - data[index] += amount; + if (index < count) { + data[index] += amount; + } else { + throw new IndexOutOfBoundsException(); + } } @@ -437,7 +441,11 @@ public class FloatList implements Iterable { * @brief Subtract from a value */ public void sub(int index, float amount) { - data[index] -= amount; + if (index < count) { + data[index] -= amount; + } else { + throw new IndexOutOfBoundsException(); + } } @@ -446,7 +454,11 @@ public class FloatList implements Iterable { * @brief Multiply a value */ public void mult(int index, float amount) { - data[index] *= amount; + if (index < count) { + data[index] *= amount; + } else { + throw new IndexOutOfBoundsException(); + } } @@ -455,7 +467,11 @@ public class FloatList implements Iterable { * @brief Divide a value */ public void div(int index, float amount) { - data[index] /= amount; + if (index < count) { + data[index] /= amount; + } else { + throw new IndexOutOfBoundsException(); + } } From aee68cdf2938285fed05e6849ad2812c10bb7c05 Mon Sep 17 00:00:00 2001 From: Patrick Vares Date: Wed, 21 Jan 2015 10:23:11 -0500 Subject: [PATCH 3/4] IntList exceptions added --- core/src/processing/data/IntList.java | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/core/src/processing/data/IntList.java b/core/src/processing/data/IntList.java index 091129b88..78b5d5c5a 100644 --- a/core/src/processing/data/IntList.java +++ b/core/src/processing/data/IntList.java @@ -412,7 +412,11 @@ public class IntList implements Iterable { * @brief Add to a value */ public void add(int index, int amount) { - data[index] += amount; + if( index < count) { + data[index] += amount; + } else { + throw new IndexOutOfBoundsException(); + } } /** @@ -420,7 +424,11 @@ public class IntList implements Iterable { * @brief Subtract from a value */ public void sub(int index, int amount) { - data[index] -= amount; + if( index < count) { + data[index] -= amount; + } else { + throw new IndexOutOfBoundsException(); + } } /** @@ -428,7 +436,11 @@ public class IntList implements Iterable { * @brief Multiply a value */ public void mult(int index, int amount) { - data[index] *= amount; + if( index < count) { + data[index] *= amount; + } else { + throw new IndexOutOfBoundsException(); + } } /** @@ -436,7 +448,11 @@ public class IntList implements Iterable { * @brief Divide a value */ public void div(int index, int amount) { - data[index] /= amount; + if( index < count) { + data[index] /= amount; + } else { + throw new IndexOutOfBoundsException(); + } } From faf989a5b914d53e5066f3b4fb119a6f54642d3e Mon Sep 17 00:00:00 2001 From: Patrick Vares Date: Wed, 21 Jan 2015 15:26:24 -0500 Subject: [PATCH 4/4] Added text to the exceptions for FloatList and IntList Fixed formatting of IntList --- core/src/processing/data/FloatList.java | 12 ++++++--- core/src/processing/data/IntList.java | 36 ++++++++++++++----------- 2 files changed, 28 insertions(+), 20 deletions(-) diff --git a/core/src/processing/data/FloatList.java b/core/src/processing/data/FloatList.java index 88c575a0a..1d06b772a 100644 --- a/core/src/processing/data/FloatList.java +++ b/core/src/processing/data/FloatList.java @@ -423,6 +423,10 @@ public class FloatList implements Iterable { } + private String exceptionText(int count, int index, String method){ + return "The list size is "+count+". Trying to "+method+" the element at "+index+" which does not exist."; + } + /** * @webref floatlist:method * @brief Add to a value @@ -431,7 +435,7 @@ public class FloatList implements Iterable { if (index < count) { data[index] += amount; } else { - throw new IndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException(exceptionText(count, index, "add")); } } @@ -444,7 +448,7 @@ public class FloatList implements Iterable { if (index < count) { data[index] -= amount; } else { - throw new IndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException(exceptionText(count, index, "sub")); } } @@ -457,7 +461,7 @@ public class FloatList implements Iterable { if (index < count) { data[index] *= amount; } else { - throw new IndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException(exceptionText(count, index, "mult")); } } @@ -470,7 +474,7 @@ public class FloatList implements Iterable { if (index < count) { data[index] /= amount; } else { - throw new IndexOutOfBoundsException(); + throw new ArrayIndexOutOfBoundsException(exceptionText(count, index, "div")); } } diff --git a/core/src/processing/data/IntList.java b/core/src/processing/data/IntList.java index 78b5d5c5a..0cf5f207b 100644 --- a/core/src/processing/data/IntList.java +++ b/core/src/processing/data/IntList.java @@ -407,16 +407,20 @@ public class IntList implements Iterable { data[index]++; } + private String exceptionText(int count, int index, String method){ + return "The list size is "+count+". Trying to "+method+" the element at "+index+" which does not exist."; + } + /** * @webref intlist:method * @brief Add to a value */ public void add(int index, int amount) { - if( index < count) { - data[index] += amount; + if (index < count) { + data[index] += amount; } else { - throw new IndexOutOfBoundsException(); - } + throw new IndexOutOfBoundsException(exceptionText(count, index, "add")); + } } /** @@ -424,11 +428,11 @@ public class IntList implements Iterable { * @brief Subtract from a value */ public void sub(int index, int amount) { - if( index < count) { - data[index] -= amount; + if (index < count) { + data[index] -= amount; } else { - throw new IndexOutOfBoundsException(); - } + throw new IndexOutOfBoundsException(exceptionText(count, index, "sub")); + } } /** @@ -436,11 +440,11 @@ public class IntList implements Iterable { * @brief Multiply a value */ public void mult(int index, int amount) { - if( index < count) { - data[index] *= amount; + if (index < count) { + data[index] *= amount; } else { - throw new IndexOutOfBoundsException(); - } + throw new IndexOutOfBoundsException(exceptionText(count, index, "mult")); + } } /** @@ -448,11 +452,11 @@ public class IntList implements Iterable { * @brief Divide a value */ public void div(int index, int amount) { - if( index < count) { - data[index] /= amount; + if (index < count) { + data[index] /= amount; } else { - throw new IndexOutOfBoundsException(); - } + throw new IndexOutOfBoundsException(exceptionText(count, index, "div")); + } }