From ba054dc064bc768257da41df8f7a0596f77bc478 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Sun, 6 Feb 2022 16:26:21 -0500 Subject: [PATCH] working to detach sketch name and main file name, move utils into Sketch --- app/src/processing/app/Base.java | 105 ++---------- app/src/processing/app/Settings.java | 16 ++ app/src/processing/app/Sketch.java | 224 +++++++++++++++++++++----- app/src/processing/app/ui/Editor.java | 39 +++-- 4 files changed, 230 insertions(+), 154 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index a472fa31c..bf4d5c58b 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -1003,14 +1003,14 @@ public class Base { if (mode.canEdit(sketch)) { //final File props = new File(sketch.getFolder(), "sketch.properties"); //saveModeSettings(props, nextMode); - updateSketchProperties(sketch.getFolder(), nextMode); + sketch.updateModeProperties(nextMode, getDefaultMode()); handleClose(activeEditor, true); Editor editor = handleOpen(sketch.getMainFilePath()); if (editor == null) { // the Mode change failed (probably code that's out of date) // re-open the sketch using the mode we were in before //saveModeSettings(props, oldMode); - updateSketchProperties(sketch.getFolder(), oldMode); + sketch.updateModeProperties(oldMode, getDefaultMode()); handleOpen(sketch.getMainFilePath()); return false; } @@ -1208,7 +1208,7 @@ public class Base { // Create sketch properties file if it's not the default mode. if (!nextMode.equals(getDefaultMode())) { - updateSketchProperties(new File(newbieDir, "sketch.properties"), nextMode); + Sketch.updateModeProperties(newbieDir, nextMode, getDefaultMode()); } String path = newbieFile.getAbsolutePath(); @@ -1310,7 +1310,7 @@ public class Base { File[] fileList = destFolder.listFiles(File::isDirectory); if (fileList != null) { if (fileList.length == 1) { - File sketchFile = findSketchMain(fileList[0]); + File sketchFile = Sketch.findMain(fileList[0], getModeList()); if (sketchFile != null) { return handleOpen(sketchFile.getAbsolutePath(), true); } @@ -1414,7 +1414,7 @@ public class Base { try { // read the sketch.properties file if it exists - Settings props = loadSketchProperties(parentFolder); + Settings props = Sketch.loadProperties(parentFolder); if (props != null) { // First check for the Mode, because it may not even be available String modeIdentifier = props.get("mode.id"); @@ -1922,7 +1922,7 @@ public class Base { File entry = new File(folder, name); File sketchFile = null; if (entry.isDirectory()) { - sketchFile = findSketchMain(entry); + sketchFile = Sketch.findMain(entry, getModeList()); } else if (name.toLowerCase().endsWith(SKETCH_BUNDLE_EXT)) { name = name.substring(0, name.length() - SKETCH_BUNDLE_EXT.length()); sketchFile = entry; @@ -2001,7 +2001,7 @@ public class Base { File entry = new File(folder, name); File sketchFile = null; if (entry.isDirectory()) { - sketchFile = findSketchMain(entry); + sketchFile = Sketch.findMain(entry, getModeList()); } else if (name.toLowerCase().endsWith(SKETCH_BUNDLE_EXT)) { name = name.substring(0, name.length() - SKETCH_BUNDLE_EXT.length()); sketchFile = entry; @@ -2029,92 +2029,10 @@ public class Base { } - /** - * Create or modify a sketch.properties file to specify the given Mode. - */ - protected void updateSketchProperties(File folder, Mode mode) { - File propsFile = null; + /* + static private Mode findSketchMode(File folder, List modeList) { try { - // Read the old sketch.properties file if it already exists - propsFile = new File(folder, "sketch.properties"); - Settings settings = new Settings(propsFile); - - // If changing to the default Mode, - // remove those entries from sketch.properties - if (mode == getDefaultMode()) { - Map map = settings.getMap(); - map.remove("mode"); - map.remove("mode.id"); - if (map.isEmpty()) { - if (propsFile.exists()) { - if (!propsFile.delete()) { - System.err.println("Could not remove unnecessary " + propsFile); - } - } - } else { - // Mode wasn't the only thing set, so write the other params - settings.save(); - } - } else { - // Setting to something other than the default Mode, - // write that and any other params already in the file. - settings.set("mode", mode.getTitle()); - settings.set("mode.id", mode.getIdentifier()); - settings.save(); - } - } catch (IOException e) { - System.err.println("Error while writing " + propsFile); - e.printStackTrace(); - } - } - - - protected Settings loadSketchProperties(File folder) throws IOException { - File propsFile = new File(folder, "sketch.properties"); - if (propsFile.exists()) { - return new Settings(propsFile); - } - return null; - } - - - /** - * Check through the various modes and see if this is a legit sketch. - * Because the default mode will be the first in the list, this will always - * prefer that one over the others. - */ - private File findSketchMain(File folder) { - try { - Settings props = loadSketchProperties(folder); - if (props != null) { - String main = props.get("main"); - if (main != null) { - File mainFile = new File(folder, main); - if (!mainFile.exists()) { - System.err.println(main + " does not exist inside " + folder); - // fall through to the code below in case we can recover - //return null; - } - } - } - } catch (IOException e) { - e.printStackTrace(); - } - for (Mode mode : getModeList()) { - // Test whether a .pde file of the same name as its parent folder exists. - String defaultName = folder.getName() + "." + mode.getDefaultExtension(); - File entry = new File(folder, defaultName); - if (entry.exists()) { - return entry; - } - } - return null; - } - - - private Mode findSketchMode(File folder) { - try { - Settings props = loadSketchProperties(folder); + Settings props = Sketch.loadProperties(folder); if (props != null) { String id = props.get("mode.id"); if (id != null) { @@ -2127,7 +2045,7 @@ public class Base { } catch (IOException e) { e.printStackTrace(); } - for (Mode mode : getModeList()) { + for (Mode mode : modeList) { // Test whether a .pde file of the same name as its parent folder exists. String defaultName = folder.getName() + "." + mode.getDefaultExtension(); File entry = new File(folder, defaultName); @@ -2137,6 +2055,7 @@ public class Base { } return null; } + */ // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . diff --git a/app/src/processing/app/Settings.java b/app/src/processing/app/Settings.java index 5f4d32f66..080926d18 100644 --- a/app/src/processing/app/Settings.java +++ b/app/src/processing/app/Settings.java @@ -256,6 +256,22 @@ public class Settings { } + public String remove(String key) { + return table.remove(key); + } + + + public void deleteIfEmpty() { + if (table.isEmpty() && file.exists()) { + file.delete(); + } + } + + public boolean isEmpty() { + return table.isEmpty(); + } + + public Map getMap() { return table; } diff --git a/app/src/processing/app/Sketch.java b/app/src/processing/app/Sketch.java index d6184e003..b83437258 100644 --- a/app/src/processing/app/Sketch.java +++ b/app/src/processing/app/Sketch.java @@ -39,6 +39,7 @@ import java.awt.event.KeyEvent; import java.io.*; import java.util.ArrayList; import java.util.List; +import java.util.Map; import java.util.concurrent.atomic.AtomicBoolean; import javax.swing.*; @@ -580,8 +581,7 @@ public class Sketch { File newFolder = new File(folder.getParentFile(), folderName); if (newFolder.exists()) { Messages.showWarning(Language.text("name.messages.new_folder_exists"), - Language.interpolate("name.messages.new_folder_exists.description", - newName)); + Language.interpolate("name.messages.new_folder_exists.description", newName)); return false; } @@ -614,8 +614,18 @@ public class Sketch { for (int i = 1; i < codeCount; i++) { code[i].setFolder(newFolder); } + // Save the path in case we need to remove it from the Recent menu + String oldPath = getMainFilePath(); + // Update internal state to reflect the new location - updateInternal(newFolder, renamingCode); + updateInternal(newFolder); + + if (renamingCode) { + // Update the Recent menu if a Rename event (but not Save As) + // https://github.com/processing/processing/issues/5902 + Recent.rename(editor, oldPath); + } + return true; } @@ -828,7 +838,7 @@ public class Sketch { @SuppressWarnings("BooleanMethodIsAlwaysInverted") public boolean saveAs() throws IOException { String newParentDir = null; - String newName = null; + String newSketchName = null; final String PROMPT = Language.text("save"); @@ -848,7 +858,7 @@ public class Sketch { fd.setFile(oldFolderName); fd.setVisible(true); newParentDir = fd.getDirectory(); - newName = fd.getFile(); + newSketchName = fd.getFile(); } else { JFileChooser fc = new JFileChooser(); fc.setDialogTitle(PROMPT); @@ -865,32 +875,38 @@ public class Sketch { if (result == JFileChooser.APPROVE_OPTION) { File selection = fc.getSelectedFile(); newParentDir = selection.getParent(); - newName = selection.getName(); + newSketchName = selection.getName(); } } // user canceled selection - if (newName == null) return false; + if (newSketchName == null) return false; + boolean sync = Preferences.getBoolean("sketch.sync_folder_and_filename"); // check on the sanity of the name - String sanitaryName = Sketch.checkName(newName); - File newFolder = new File(newParentDir, sanitaryName); - if (!sanitaryName.equals(newName) && newFolder.exists()) { + //String sanitaryName = Sketch.checkName(newSketchName); + String newCodeName = sanitizeName(newSketchName); + File newFolder = sync ? + new File(newParentDir, newCodeName) : // before 4.0 beta 6 + new File(newParentDir, newSketchName); // sketch folder name can be different + if (!newCodeName.equals(newSketchName) && newFolder.exists()) { Messages.showMessage(Language.text("save_file.messages.sketch_exists"), Language.interpolate("save_file.messages.sketch_exists.description", - sanitaryName)); + newCodeName)); return false; } - newName = sanitaryName; + if (sync) { + newSketchName = newCodeName; + } // make sure there doesn't exist a tab with that name already // but ignore this situation for the first tab, since it's probably being // re-saved (with the same name) to another location/folder. for (int i = 1; i < codeCount; i++) { - if (newName.equalsIgnoreCase(code[i].getPrettyName())) { + if (newSketchName.equalsIgnoreCase(code[i].getPrettyName())) { Messages.showMessage(Language.text("save_file.messages.tab_exists"), Language.interpolate("save_file.messages.tab_exists.description", - newName)); + newSketchName)); return false; } } @@ -925,9 +941,13 @@ public class Sketch { // will instead put you inside the folder, but it happens on OS X a lot. // now make a fresh copy of the folder - newFolder.mkdirs(); - // if this fails, then it probably means the removeDir() failed above, - // or at least left things behind, which could mean badness later. hm. + if (!newFolder.mkdirs()) { + // mkdirs() returns true when the folders are created, which should + // be the case here because we removed any existing 'newFolder' above. + // If this fails, then it probably means the removeDir() failed, + // or at least left things behind, which could mean badness later. + System.err.println("Error creating path " + newFolder); + } // grab the contents of the current tab before saving // first get the contents of the editor text area @@ -963,7 +983,7 @@ public class Sketch { return true; }); - startSaveAsThread(newName, newFolder, copyItems); + startSaveAsThread(newFolder, copyItems); // save the other tabs to their new location (main tab saved below) for (int i = 1; i < codeCount; i++) { @@ -972,14 +992,15 @@ public class Sketch { } // We were removing the old folder from the Recent menu, but folks - // did not like that behavior, so we shut it off in 3.5.4 and 4.x. + // did not like that behavior because they expected to have older + // versions readily available, so we shut it off in 3.5.4 and 4.x. // https://github.com/processing/processing/issues/5902 // save the main tab with its new name - File newFile = new File(newFolder, newName + "." + mode.getDefaultExtension()); + File newFile = new File(newFolder, newCodeName + "." + mode.getDefaultExtension()); code[0].saveAs(newFile); - updateInternal(newFolder, false); + updateInternal(newFolder); // Make sure that it's not an untitled sketch setUntitled(false); @@ -1015,12 +1036,11 @@ public class Sketch { * * 3843 */ - void startSaveAsThread(final String newName, - final File newFolder, final File[] copyItems) { + void startSaveAsThread(final File newFolder, final File[] copyItems) { saving.set(true); EventQueue.invokeLater(() -> { final JFrame frame = - new JFrame("Saving \u201C" + newName + "\u201C\u2026"); + new JFrame("Saving \u201C" + newFolder.getName() + "\u201C\u2026"); frame.setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); Box box = Box.createVerticalBox(); @@ -1181,9 +1201,8 @@ public class Sketch { /** * Update internal state for new sketch name or folder location. */ - protected void updateInternal(File sketchFolder, boolean renaming) { + protected void updateInternal(File sketchFolder) { // reset all the state information for the sketch object - String oldPath = getMainFilePath(); primaryFile = code[0].getFile(); name = sketchFolder.getName(); @@ -1192,14 +1211,131 @@ public class Sketch { codeFolder = new File(folder, "code"); dataFolder = new File(folder, "data"); + updateNameProperties(); + // Name changed, rebuild the sketch menus calcModified(); editor.updateTitle(); editor.getBase().rebuildSketchbook(); - if (renaming) { - // Update the Recent menu if a Rename event (but not Save As) - // https://github.com/processing/processing/issues/5902 - Recent.rename(editor, oldPath); + } + + + protected void updateModeProperties(Mode mode, Mode defaultMode) { + updateModeProperties(folder, mode, defaultMode); + } + + + /** + * Create or modify a sketch.properties file to specify the given Mode. + */ + static protected void updateModeProperties(File folder, Mode mode, Mode defaultMode) { + File propsFile = null; + try { + // Read the old sketch.properties file if it already exists + propsFile = new File(folder, "sketch.properties"); + Settings settings = new Settings(propsFile); + + // If changing to the default Mode, + // remove those entries from sketch.properties + if (mode == defaultMode) { + Map map = settings.getMap(); + map.remove("mode"); + map.remove("mode.id"); + if (map.isEmpty()) { + if (propsFile.exists()) { + if (!propsFile.delete()) { + System.err.println("Could not remove unnecessary " + propsFile); + } + } + } else { + // Mode wasn't the only thing set, so write the other params + settings.save(); + } + } else { + // Setting to something other than the default Mode, + // write that and any other params already in the file. + settings.set("mode", mode.getTitle()); + settings.set("mode.id", mode.getIdentifier()); + settings.save(); + } + } catch (IOException e) { + System.err.println("Error while writing " + propsFile); + e.printStackTrace(); + } + } + + + protected Settings loadProperties() throws IOException { + return loadProperties(folder); + } + + + static protected Settings loadProperties(File folder) throws IOException { + File propsFile = new File(folder, "sketch.properties"); + if (propsFile.exists()) { + return new Settings(propsFile); + } + return null; + } + + + /** + * Check through the various modes and see if this is a legit sketch. + * Because the default mode will be the first in the list, this will always + * prefer that one over the others. + */ + static protected File findMain(File folder, List modeList) { + try { + Settings props = Sketch.loadProperties(folder); + if (props != null) { + String main = props.get("main"); + if (main != null) { + File mainFile = new File(folder, main); + if (!mainFile.exists()) { + System.err.println(main + " does not exist inside " + folder); + // fall through to the code below in case we can recover + //return null; + } + } + } + } catch (IOException e) { + e.printStackTrace(); + } + for (Mode mode : modeList) { + // Test whether a .pde file of the same name as its parent folder exists. + String defaultName = folder.getName() + "." + mode.getDefaultExtension(); + File entry = new File(folder, defaultName); + if (entry.exists()) { + return entry; + } + } + return null; + } + + + private void updateNameProperties() { + // If the main file and the sketch name are not identical, + // update sketch.properties. + String mainName = primaryFile.getName(); + String defaultName = name + "." + mode.getDefaultExtension(); + + File propsFile = null; + try { + // Read the old sketch.properties file if it already exists + propsFile = new File(folder, "sketch.properties"); + Settings settings = new Settings(propsFile); + + if (mainName.equals(defaultName)) { + settings.remove("main"); + settings.deleteIfEmpty(); + } else { + settings.set("main", mainName); + settings.save(); + } + + } catch (IOException e) { + System.err.println("Error while writing " + propsFile); + e.printStackTrace(); } } @@ -1645,20 +1781,20 @@ public class Sketch { // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . - /** - * Convert to sanitized name and alert the user - * if changes were made. - */ - static public String checkName(String origName) { - String newName = sanitizeName(origName); - - if (!newName.equals(origName)) { - String msg = - Language.text("check_name.messages.is_name_modified"); - System.out.println(msg); - } - return newName; - } +// /** +// * Convert to sanitized name and alert the user +// * if changes were made. +// */ +// static public String checkName(String origName) { +// String newName = sanitizeName(origName); +// +// if (!newName.equals(origName)) { +// String msg = +// Language.text("check_name.messages.is_name_modified"); +// System.out.println(msg); +// } +// return newName; +// } /** diff --git a/app/src/processing/app/ui/Editor.java b/app/src/processing/app/ui/Editor.java index a3e38a11d..d6360d2b1 100644 --- a/app/src/processing/app/ui/Editor.java +++ b/app/src/processing/app/ui/Editor.java @@ -23,23 +23,6 @@ package processing.app.ui; -import processing.app.Base; -import processing.app.Formatter; -import processing.app.Language; -import processing.app.Messages; -import processing.app.Mode; -import processing.app.Platform; -import processing.app.Preferences; -import processing.app.Problem; -import processing.app.RunnerListener; -import processing.app.Sketch; -import processing.app.SketchCode; -import processing.app.SketchException; -import processing.app.Util; -import processing.app.contrib.ContributionManager; -import processing.app.syntax.*; -import processing.core.*; - import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; @@ -71,6 +54,22 @@ import javax.swing.text.*; import javax.swing.text.html.*; import javax.swing.undo.*; +import processing.app.Base; +import processing.app.Formatter; +import processing.app.Language; +import processing.app.Messages; +import processing.app.Mode; +import processing.app.Platform; +import processing.app.Preferences; +import processing.app.Problem; +import processing.app.RunnerListener; +import processing.app.Sketch; +import processing.app.SketchCode; +import processing.app.SketchException; +import processing.app.contrib.ContributionManager; +import processing.app.syntax.*; +import processing.core.*; + /** * Main editor panel for the Processing Development Environment. @@ -2171,6 +2170,11 @@ public abstract class Editor extends JFrame implements RunnerListener { * shouldn't rely on any of its variables being initialized already. */ protected void handleOpenInternal(String path) throws EditorException { + // All this logic should be happening back in Base, not here. + // Presumably it lived here so that other Modes could override the + // behavior, but that changes with 4.0 beta 6. [fry 220206] + + /* // check to make sure that this .pde file is // in a folder of the same name final File file = new File(path); @@ -2244,6 +2248,7 @@ public abstract class Editor extends JFrame implements RunnerListener { throw new EditorException(); } } + */ try { sketch = new Sketch(path, this);