From e09f7d117b0957eebec94f5270507447ee57f6a7 Mon Sep 17 00:00:00 2001 From: Ben Fry Date: Wed, 4 Aug 2021 22:05:01 -0400 Subject: [PATCH] initial support for reading sketches from a zipped file --- app/src/processing/app/Base.java | 176 +++++++++++++++++-------------- build/build.xml | 12 +++ todo.txt | 99 +++++++++-------- 3 files changed, 163 insertions(+), 124 deletions(-) diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 3938fbb2f..47c3bbd66 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -46,7 +46,7 @@ import processing.data.StringList; * The base class for the main processing application. * Primary role of this class is for platform identification and * general interaction with the system (launching URLs, loading - * files and images, etc) that comes from that. + * files and images, etc.) that comes from that. */ public class Base { // Added accessors for 0218 because the UpdateCheck class was not properly @@ -55,6 +55,9 @@ public class Base { /** This might be replaced by main() if there's a lib/version.txt file. */ static private String VERSION_NAME = "1276"; //$NON-NLS-1$ + static final String SKETCH_BUNDLE_EXT = ".pskz"; + static final String CONTRIB_BUNDLE_EXT = ".pcbz"; + /** * True if heavy debugging error/log messages are enabled. Set to true * if an empty file named 'debug' is found in the settings folder. @@ -168,7 +171,7 @@ public class Base { DEBUG = true; } - // Use native popups so they don't look so crappy on OS X + // Use native popups so they don't look crappy on macOS JPopupMenu.setDefaultLightWeightPopupEnabled(false); // Don't put anything above this line that might make GUI, @@ -285,7 +288,7 @@ public class Base { } - // Remove this code in a couple months [fry 170211] + // Remove this code in a couple of months [fry 170211] // https://github.com/processing/processing/issues/4853 // Or maybe not, if NVIDIA keeps doing this [fry 170423] // https://github.com/processing/processing/issues/4997 @@ -1302,6 +1305,41 @@ public class Base { * Open a sketch from the path specified. Do not use for untitled sketches. */ public Editor handleOpen(String path) { + if (path.endsWith(SKETCH_BUNDLE_EXT)) { + File zipFile = new File(path); + try { + File destFolder = File.createTempFile("zip", "tmp", untitledFolder); + if (!destFolder.delete() || !destFolder.mkdirs()) { + // Hard to imagine why this would happen, but... + System.err.println("Could not create temporary folder " + destFolder); + return null; + } + Util.unzip(zipFile, destFolder); + File[] fileList = destFolder.listFiles(File::isDirectory); + if (fileList != null) { + if (fileList.length == 1) { + File sketchFile = checkSketchFolder(fileList[0]); + if (sketchFile != null) { + return handleOpen(sketchFile.getAbsolutePath(), true); + } + } else { + System.err.println("Expecting one folder inside " + + SKETCH_BUNDLE_EXT + " file, found " + fileList.length + "."); + } + } else { + System.err.println("Could not read " + destFolder); + } + } catch (IOException e) { + e.printStackTrace(); + } + return null; // no luck + + } else if (path.endsWith(CONTRIB_BUNDLE_EXT)) { + // TODO Install a contrib here + return null; + + } + return handleOpen(path, false); } @@ -1645,35 +1683,6 @@ public class Base { } - /* - public JMenu getRecentMenu() { - return recent.getMenu(); - } - - - public JMenu getToolbarRecentMenu() { - return recent.getToolbarMenu(); - } - - - public void handleRecent(Editor editor) { - recent.handle(editor); - } - - - public void handleRecentRename(Editor editor, String oldPath) { - recent.handleRename(editor, oldPath); - } - - - // Called before a sketch is renamed so that its old name is - // no longer in the menu. - public void removeRecent(Editor editor) { - recent.remove(editor); - } - */ - - /** * Scan a folder recursively, and add any sketches found to the menu * specified. Set the openReplaces parameter to true when opening the sketch @@ -1711,12 +1720,6 @@ public class Base { ActionListener listener = e -> { String path = e.getActionCommand(); if (new File(path).exists()) { - /* - boolean replace = replaceExisting; - if ((e.getModifiers() & ActionEvent.SHIFT_MASK) != 0) { - replace = !replace; - } - */ handleOpen(path); } else { Messages.showWarning("Sketch Disappeared", @@ -1730,34 +1733,40 @@ public class Base { boolean found = false; -// for (int i = 0; i < list.length; i++) { -// if ((list[i].charAt(0) == '.') || -// list[i].equals("CVS")) continue; for (String name : list) { if (name.charAt(0) == '.') { continue; } - File subfolder = new File(folder, name); - if (subfolder.isDirectory()) { - File entry = checkSketchFolder(subfolder, name); - if (entry != null) { + // TODO Is this necessary any longer? This seems gross [fry 210804] + if (name.equals("old")) { // Don't add old contributions + continue; + } - JMenuItem item = new JMenuItem(name); - item.addActionListener(listener); - item.setActionCommand(entry.getAbsolutePath()); - menu.add(item); + File entry = new File(folder, name); + File sketchFile = null; + if (entry.isDirectory()) { + sketchFile = checkSketchFolder(entry); + } else if (name.toLowerCase().endsWith(SKETCH_BUNDLE_EXT)) { + name = name.substring(0, name.length() - SKETCH_BUNDLE_EXT.length()); + sketchFile = entry; + } + + if (sketchFile != null) { + JMenuItem item = new JMenuItem(name); + item.addActionListener(listener); + item.setActionCommand(sketchFile.getAbsolutePath()); + menu.add(item); + found = true; + + } else if (entry.isDirectory()) { + // not a sketch folder, but may be a subfolder containing sketches + JMenu submenu = new JMenu(name); + // needs to be separate var otherwise would set found to false + boolean anything = addSketches(submenu, entry); + if (anything) { + menu.add(submenu); found = true; - - } else { - // not a sketch folder, but maybe a subfolder containing sketches - JMenu submenu = new JMenu(name); - // needs to be separate var otherwise would set found to false - boolean anything = addSketches(submenu, subfolder); - if (anything && !name.equals("old")) { //Don't add old contributions - menu.add(submenu); - found = true; - } } } } @@ -1765,6 +1774,10 @@ public class Base { } + /** + * Mostly identical to the JMenu version above, however the rules are + * slightly different for how examples are handled, etc. + */ public boolean addSketches(DefaultMutableTreeNode node, File folder, boolean examples) throws IOException { // skip .DS_Store files, etc (this shouldn't actually be necessary) @@ -1809,25 +1822,30 @@ public class Base { continue; } - File subfolder = new File(folder, name); - if (subfolder.isDirectory()) { - File entry = checkSketchFolder(subfolder, name); - if (entry != null) { - DefaultMutableTreeNode item = - new DefaultMutableTreeNode(new SketchReference(name, entry)); + File entry = new File(folder, name); + File sketchFile = null; + if (entry.isDirectory()) { + sketchFile = checkSketchFolder(entry); + } else if (name.toLowerCase().endsWith(SKETCH_BUNDLE_EXT)) { + name = name.substring(0, name.length() - SKETCH_BUNDLE_EXT.length()); + sketchFile = entry; + } - node.add(item); + if (sketchFile != null) { + DefaultMutableTreeNode item = + new DefaultMutableTreeNode(new SketchReference(name, sketchFile)); + + node.add(item); + found = true; + + } else if (entry.isDirectory()) { + // not a sketch folder, but maybe a subfolder containing sketches + DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(name); + // needs to be separate var otherwise would set found to false + boolean anything = addSketches(subNode, entry, examples); + if (anything) { + node.add(subNode); found = true; - - } else { - // not a sketch folder, but maybe a subfolder containing sketches - DefaultMutableTreeNode subNode = new DefaultMutableTreeNode(name); - // needs to be separate var otherwise would set found to false - boolean anything = addSketches(subNode, subfolder, examples); - if (anything) { - node.add(subNode); - found = true; - } } } } @@ -1840,10 +1858,10 @@ public class Base { * Because the default mode will be the first in the list, this will always * prefer that one over the others. */ - File checkSketchFolder(File subfolder, String item) { + private File checkSketchFolder(File folder) { for (Mode mode : getModeList()) { - File entry = new File(subfolder, item + "." + mode.getDefaultExtension()); //$NON-NLS-1$ - // if a .pde file of the same prefix as the folder exists.. + // Test whether a .pde file of the same name as its parent folder exists. + File entry = new File(folder, folder.getName() + "." + mode.getDefaultExtension()); //$NON-NLS-1$ if (entry.exists()) { return entry; } diff --git a/build/build.xml b/build/build.xml index d6d57f151..ee757a231 100644 --- a/build/build.xml +++ b/build/build.xml @@ -548,6 +548,18 @@ role="Editor"> + + + + + + diff --git a/todo.txt b/todo.txt index 85d91345f..a3d87b0a0 100755 --- a/todo.txt +++ b/todo.txt @@ -20,16 +20,57 @@ X change Messages.loge() to Messages.err() X only call errorTable.updateTheme() if it's not null X update EditorFooter.updateMode() to EditorFooter.updateTheme() X add it to the code called by Editor.updateTheme() +_ update to latest JDK 11 Sam updates X can we get rid of pdexEnabled? does the current code work w/ java tabs? X https://github.com/processing/processing4/issues/157 X https://github.com/processing/processing4/pull/230 +cleaning +o look into LCD rendering problems w/ Java (see if Lion still a problem) +o fonts were showing up with very different fatness +o put stdout/stderr into ~/Library/Logs +o and have a .log extension so it can be browsed properly +o need to make sure that it's ok to write to logs dir.. +o probably being removed from future OS X versions + before release _ update the README for alpha 6 (and this release too, when ready) +_ don't allow "Show Sketch Folder" for untitled sketches + +sketch/launching +_ should it be pskz, pcbz? psk for the sketch file to double-click? +_ pdez as a sketch bundle? +_ launch/psk files/import from web editor (more details below) +_ cleaning up the temp file handling +_ 'show sketch folder' weird when in temp folder +_ ask to save first (sketch has not been saved yet) +_ or make the temp folder part of the sketchbook +_ same with adding files to an unsaved sketch, do we block that? +_ what to double-click when opening p5 projects +_ lack of a project file makes this a little bit of a headache +_ dropping a sketch folder onto the PDE should also be implemented +_ some type of sketch archive format for posting examples (.psk?) +_ would be nice to open a sketch directly from a zip file +_ https://github.com/processing/processing/issues/73 +_ maybe just open from a zip file, since psk doesn't help anything +_ also have a means of importing sketches +_ https://github.com/processing/processing/issues/3987 +_ also see several notes below re: examples +_ add means to import .zip files from file/url into sketchbook, library, etc. +_ super easy given current code implementation, might help usability +_ put the reference (and examples?) into .zip files +_ unzipping the app takes forever +_ see the 'examples' section below +_ how are file associations handled in Linux? (for .pde, .psk) +_ when adding a new library, its examples aren't added to the list until restart +_ refresh option for sketchbook (bottom of window) +_ import option for sketchbook (button to select files/folders/etc) + + _ dealing with reference.zip and web server _ web server confirmed to be working, but should check w/ new docs _ psk files, doing that for examples @@ -165,20 +206,8 @@ _ detach sketch name and folder name (use sketch.properties) _ better for git, etc _ single file thing is long gone _ introduce the idea of 'scraps' (ala gist) that are just single page blobs -_ launch/psk files/import from web editor (more details below) -_ cleaning up the temp file handling -_ 'show sketch folder' weird when in temp folder -_ ask to save first (sketch has not been saved yet) -_ or make the temp folder part of the sketchbook -_ same with adding files to an unsaved sketch, do we block that? -macos -_ disable "notifications" prompt on startup for macOS -_ we're not posting any, can we suppress the "allow notifications" message? -_ https://developer.apple.com/documentation/usernotifications -_ https://developer.apple.com/documentation/usernotifications/asking_permission_to_use_notifications - windows _ go back to including a .bat file? @@ -201,28 +230,6 @@ _ sign releases on Windows to avoid SmartScreen warnings/errors _ https://github.com/processing/processing4/issues/25 -sketch/launching -_ what to double-click when opening p5 projects -_ lack of a project file makes this a little bit of a headache -_ dropping a sketch folder onto the PDE should also be implemented -_ some type of sketch archive format for posting examples (.psk?) -_ would be nice to open a sketch directly from a zip file -_ https://github.com/processing/processing/issues/73 -_ maybe just open from a zip file, since psk doesn't help anything -_ also have a means of importing sketches -_ https://github.com/processing/processing/issues/3987 -_ also see several notes below re: examples -_ add means to import .zip files from file/url into sketchbook, library, etc. -_ super easy given current code implementation, might help usability -_ put the reference (and examples?) into .zip files -_ unzipping the app takes forever -_ see the 'examples' section below -_ how are file associations handled in Linux? (for .pde, .psk) -_ when adding a new library, its examples aren't added to the list until restart -_ refresh option for sketchbook (bottom of window) -_ import option for sketchbook - - web/docs _ create a processing4-docs repo _ check with Casey re: shallow clone or approach @@ -1092,11 +1099,24 @@ _ this may already work with SingleInstance stuff DIST / macOS +appbundler _ update appbundler? https://github.com/TheInfiniteKind/appbundler _ might be broken though https://github.com/TheInfiniteKind/appbundler/issues/70 _ symlink https://github.com/TheInfiniteKind/appbundler/issues/1 _ startup chatter (from appbundler?) _ Processing[25059:13082813] int launch(char *, int, char **) Launchpath +_ Find a long-term solution for OS X bundler to address signing/symlink issues +_ https://github.com/processing/processing/issues/2967 +_ appbundler improvements +_ don't re-copy JRE into work folder if already exists +_ implement a splash screen + +others +_ disable "notifications" prompt on startup for macOS +_ https://github.com/processing/processing4/issues/234 +_ we're not posting any, can we suppress the "allow notifications" message? +_ https://developer.apple.com/documentation/usernotifications +_ https://developer.apple.com/documentation/usernotifications/asking_permission_to_use_notifications _ Help Menu disabled on OS X (looks like a JVM bug) _ https://github.com/processing/processing/issues/4353#issuecomment-237715947 _ still broken in 11.0.8 @@ -1107,11 +1127,6 @@ _ https://developer.apple.com/library/mac/technotes/tn2007/tn2196.html _ built-in images: http://nadeausoftware.com/articles/2008/12/mac_java_tip_how_access_mac_specific_nsimage_icons _ Update QuickLook plugin for Processing 3 _ https://github.com/processing/processing/issues/3261 -_ Find a long-term solution for OS X bundler to address signing/symlink issues -_ https://github.com/processing/processing/issues/2967 -_ appbundler improvements -_ don't re-copy JRE into work folder if already exists -_ implement a splash screen _ more OS X-specific hackery for improved appearance _ https://developer.apple.com/library/mac/technotes/tn2007/tn2196.html _ possible better option for doing retina? @@ -1121,17 +1136,11 @@ _ http://lwjgl.org/forum/index.php/topic,4711.225.html _ change cmd line for OS X to use symlink? _ otherwise updates are going to require reinstall.. _ or that it's gonna need to parse and say "update command line?" -_ look into LCD rendering problems w/ Java (see if Lion still a problem) -_ fonts were showing up with very different fatness _ we're breaking some mac human interface guidelines _ should be using a menu factory to create menubar for all sub-windows _ http://developer.apple.com/technotes/tn/tn2042.html _ and the general warning dialogs are just ass ugly _ (i.e. we really need those replacements for JOptionPane) -_ put stdout/stderr into ~/Library/Logs -_ and have a .log extension so it can be browsed properly -_ need to make sure that it's ok to write to logs dir.. -_ probably being removed from future OS X versions _ Exiting a sketch with Command-Q or File > Quit doesn't call stop() on OS X _ https://github.com/processing/processing/issues/186