diff --git a/app/src/processing/app/Base.java b/app/src/processing/app/Base.java index 0e78015ca..fc0573266 100644 --- a/app/src/processing/app/Base.java +++ b/app/src/processing/app/Base.java @@ -2354,11 +2354,19 @@ public class Base { // } + /** + * Return a File from inside the Processing 'lib' folder. + */ + static public File getLibFile(String filename) throws IOException { + return new File(getContentFile("lib"), filename); + } + + /** * Return an InputStream for a file inside the Processing lib folder. */ static public InputStream getLibStream(String filename) throws IOException { - return new FileInputStream(new File(getContentFile("lib"), filename)); + return new FileInputStream(getLibFile(filename)); } diff --git a/app/src/processing/app/Language.java b/app/src/processing/app/Language.java index 72af6723f..4c9476729 100644 --- a/app/src/processing/app/Language.java +++ b/app/src/processing/app/Language.java @@ -22,53 +22,46 @@ package processing.app; import java.io.*; -import java.net.MalformedURLException; -import java.net.URL; -import java.net.URLClassLoader; -import java.net.URLConnection; import java.util.*; +import processing.core.PApplet; + /** * Internationalization (i18n) */ -public class Language { - /** - * Store the language information in a file separate from the preferences, - * because preferences need the language on load time. - */ - static private final String LANG_FILE = "language.properties"; - - /** Directory of available languages */ - static private final String LANG_FILES = "languages"; +public class Language { +// static private final String FILE = "processing.app.languages.PDE"; + //static private final String LISTING = "processing/app/languages/languages.txt"; - /** Definition of package for fallback */ - //static private final String LANG_PACKAGE = "processing.app.languages"; - static private final String LANG_BASE_NAME = "PDE"; - - static private Properties props; - static private File propsFile; - - /** Language */ - private String language; - - /** Available languages */ - private HashMap languages; - - /** Define the location of language files */ - static private File langFiles = Base.getSettingsFile(LANG_FILES); - - /** Set version of current PDE */ - static private final String version = Base.getVersionName(); - static private ResourceBundle bundle; + // Store the language information in a file separate from the preferences, + // because preferences need the language on load time. + static protected final String PREF_FILE = "language.txt"; + static protected final File prefFile = Base.getSettingsFile(PREF_FILE); /** Single instance of this Language class */ static private volatile Language instance; - + /** The system language */ + private String language; + + /** Available languages */ + private HashMap languages; + + //private ResourceBundle bundle; + //private Settings bundle; + private LanguageBundle bundle; + + private Language() { - // Set default language - language = "en"; + String systemLanguage = Locale.getDefault().getLanguage(); + language = loadLanguage(); + boolean writePrefs = false; + + if (language == null) { + language = systemLanguage; + writePrefs = true; + } // Set available languages languages = new HashMap(); @@ -76,95 +69,22 @@ public class Language { languages.put(code, Locale.forLanguageTag(code).getDisplayLanguage(Locale.forLanguageTag(code))); } - boolean copiedLangFiles = false; - - if(loadProps()){ + // Set default language + if (!languages.containsKey(language)) { + language = "en"; + writePrefs = true; + } - boolean updateProps = false; - boolean updateLangFiles = false; - - // Define and check version - if(props.containsKey("version") && langFiles.exists()){ - if(!props.getProperty("version").equals(version)){ - updateLangFiles = true; - } - } else { - updateLangFiles = true; - } - - // Copy new language properties - if(updateLangFiles){ - if(copiedLangFiles = updateLangFiles()){ - props.setProperty("version", version); - updateProps = true; - } - } - - // Define language - if(props.containsKey("language")){ - language = props.getProperty("language"); - } else { - if (!languages.containsKey(Locale.getDefault().getLanguage())) { - language = Locale.getDefault().getLanguage(); - } - props.setProperty("language", language); - updateProps = true; - } - - // Save changes - if(updateProps){ - updateProps(); - } - - } else { - // Fallback: No access to the property file - copiedLangFiles = updateLangFiles(); + if (writePrefs) { + saveLanguage(language); } - - // Developing - if (Base.DEBUG && copiedLangFiles == false) { - updateLangFiles(); - } - + + // Get bundle with translations (processing.app.language.PDE) + //bundle = ResourceBundle.getBundle(Language.FILE, new Locale(this.language), new UTF8Control()); try { - URL[] paths = { langFiles.toURI().toURL() }; - bundle = ResourceBundle.getBundle( - Language.LANG_BASE_NAME, - new Locale(language), - new URLClassLoader(paths), - new UTF8Control() - ); - } catch (MalformedURLException e) { - // Fallback: Does we need a fallback? -// bundle = ResourceBundle.getBundle( -// Language.LANG_PACKAGE+"."+Language.LANG_BASE_NAME, -// new Locale(this.language), -// new UTF8Control() -// ); - } - } - - - private static boolean updateLangFiles() { - // Delete old languages - if(langFiles.exists()){ - File[] lang = langFiles.listFiles(); - for (int i = 0; i < lang.length; i++) { - lang[i].delete(); - } - langFiles.delete(); - } - // Copy new languages - String javaPath = new File(Base.class.getProtectionDomain().getCodeSource().getLocation().getFile()).getParentFile().getAbsolutePath(); - try { - Base.copyDir( - new File(javaPath+"/lib/languages"), // from shared library folder - langFiles // to editable settings folder - ); - return true; + bundle = new LanguageBundle(language); } catch (IOException e) { e.printStackTrace(); - return false; } } @@ -185,7 +105,6 @@ public class Language { "tr", // Turkish "zh" // Chinese }; - Arrays.sort(SUPPORTED); return SUPPORTED; /* @@ -205,58 +124,21 @@ public class Language { */ } - - /** Load properties of language.properties */ - static private boolean loadProps(){ - if (props == null) { - props = new Properties(); - } - propsFile = Base.getSettingsFile(LANG_FILE); - if(!propsFile.exists()){ - try { - Base.saveFile("", propsFile); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - InputStream is = null; + + /** Read the saved language */ + static private String loadLanguage() { try { - is = new FileInputStream(propsFile); + if (prefFile.exists()) { + String language = PApplet.loadStrings(prefFile)[0]; + language = language.trim().toLowerCase(); + if (!language.equals("")) { + return language; + } + } } catch (Exception e) { - return false; - } - try { - props.load(is); - } catch (IOException e) { e.printStackTrace(); - return false; } - try { - is.close(); - } catch (IOException e) { - e.printStackTrace(); - return false; - } - return true; - } - - - /** Save changes in language.properties */ - static private boolean updateProps(){ - if (props != null) { - try { - OutputStream out = new FileOutputStream(propsFile); - props.store(out, "language preferences"); - } catch (FileNotFoundException e) { - e.printStackTrace(); - return false; - } catch (IOException e) { - e.printStackTrace(); - return false; - } - } - return true; + return null; } @@ -265,19 +147,19 @@ public class Language { * 'set' because a language change requires a restart of Processing. */ static public void saveLanguage(String language) { - if (loadProps()) { - props.setProperty("language", language); - if (updateProps()) { - Base.getPlatform().saveLanguage(language); - } + try { + Base.saveFile(language, prefFile); + } catch (Exception e) { + e.printStackTrace(); } + Base.getPlatform().saveLanguage(language); } /** Singleton constructor */ static public Language init() { if (instance == null) { - synchronized (Language.class) { + synchronized(Language.class) { if (instance == null) { instance = new Language(); } @@ -286,51 +168,70 @@ public class Language { return instance; } - + /** Get translation from bundles. */ static public String text(String text) { - init(); +// ResourceBundle bundle = init().bundle; + LanguageBundle bundle = init().bundle; + try { return bundle.getString(text); } catch (MissingResourceException e) { return text; } } - + static public String interpolate(String text, Object... arguments) { - init(); - return String.format(bundle.getString(text), arguments); +// return String.format(init().bundle.getString(text), arguments); + return String.format(init().bundle.getString(text), arguments); } static public String pluralize(String text, int count) { - init(); +// ResourceBundle bundle = init().bundle; + LanguageBundle bundle = init().bundle; + String fmt = text + ".%s"; - if (bundle.containsKey(String.format(fmt, count))) { - return interpolate(String.format(fmt, count), count); + String key = String.format(fmt, count); + if (bundle.containsKey(key)) { + return interpolate(key, count); } return interpolate(String.format(fmt, "n"), count); } - + /** Get all available languages */ static public Map getLanguages() { return init().languages; } - + /** Get current language */ static public String getLanguage() { return init().language; } +// /** Set new language (called by Preferences) */ +// static public void setLanguage(String language) { +// this.language = language; +// +// try { +// File file = Base.getContentFile("lib/language.txt"); +// Base.saveFile(language, file); +// } catch (Exception e) { +// e.printStackTrace(); +// } +// } + + /** * Custom 'Control' class for consistent encoding. * http://stackoverflow.com/questions/4659929/how-to-use-utf-8-in-resource-properties-with-resourcebundle */ - static private class UTF8Control extends ResourceBundle.Control { + /* + static class UTF8Control extends ResourceBundle.Control { public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload) throws IllegalAccessException, InstantiationException,IOException { // The below is a copy of the default implementation. String bundleName = toBundleName(baseName, locale); @@ -360,4 +261,61 @@ public class Language { return bundle; } } + */ + + + static class LanguageBundle { + Map table; + + LanguageBundle(String language) throws IOException { + table = new HashMap(); + + String baseFilename = "languages/PDE.properties"; + String langFilename = "languages/PDE_" + language + ".properties"; + + File baseFile = Base.getLibFile(baseFilename); + File userBaseFile = new File(Base.getSketchbookFolder(), baseFilename); + if (userBaseFile.exists()) { + baseFile = userBaseFile; + } + + File langFile = Base.getLibFile(langFilename); + File userLangFile = new File(Base.getSketchbookFolder(), langFilename); + if (userLangFile.exists()) { + langFile = userLangFile; + } + + read(baseFile); + read(langFile); + } + + void read(File additions) { + String[] lines = PApplet.loadStrings(additions); + for (String line : lines) { + if ((line.length() == 0) || + (line.charAt(0) == '#')) continue; + + // this won't properly handle = signs being in the text + int equals = line.indexOf('='); + if (equals != -1) { + String key = line.substring(0, equals).trim(); + String value = line.substring(equals + 1).trim(); + + // fix \n and \' + value = value.replaceAll("\\\\n", "\n"); + value = value.replaceAll("\\\\'", "'"); + + table.put(key, value); + } + } + } + + String getString(String key) { + return table.get(key); + } + + boolean containsKey(String key) { + return table.containsKey(key); + } + } } diff --git a/build/build.xml b/build/build.xml index ca4ebccd2..0e98bff88 100755 --- a/build/build.xml +++ b/build/build.xml @@ -34,13 +34,25 @@ + + + + + + - + - + + + + + @@ -154,13 +166,13 @@ - - + + message="JDK ${jdk.stuff} required.${line.separator}To build on OS X, you must install Oracle's JDK ${jdk.stuff} from${line.separator}http://www.oracle.com/technetwork/java/javase/downloads${line.separator}or http://download.processing.org/java/${jdk.file}${line.separator}Note that only ${jdk.stuff} (not a later or earlier version) will work. ${line.separator}And it must be the JDK, not the JRE. And do not try to defy me again." /> - + @@ -488,7 +500,7 @@ - + @@ -543,7 +555,7 @@ - + @@ -649,12 +661,7 @@ - - - @@ -687,10 +694,10 @@ - + - + @@ -820,7 +827,7 @@ - @@ -833,7 +840,8 @@ dest="windows/work" src="windows/jre.tgz" overwrite="false" /> - + diff --git a/build/shared/lib/languages/PDE.properties b/build/shared/lib/languages/PDE.properties index 95984604f..ab3f4caf9 100644 --- a/build/shared/lib/languages/PDE.properties +++ b/build/shared/lib/languages/PDE.properties @@ -281,7 +281,7 @@ editor.header.delete = Delete editor.header.previous_tab = Previous Tab editor.header.next_tab = Next Tab editor.header.delete.warning.title = Yeah, no. -editor.header.delete.warning.text = You can't delete the last tab of the last open sketch. +editor.header.delete.warning.text = You cannot delete the last tab of the last open sketch. # Tabs editor.tab.new = New Name @@ -316,14 +316,14 @@ editor.footer.console = Console # New handler new.messages.is_read_only = Sketch is Read-Only -new.messages.is_read_only.description = Some files are marked \"read-only\", so you'll\nneed to re-save the sketch in another location,\nand try again. +new.messages.is_read_only.description = Some files are marked \"read-only\", so you will\nneed to re-save the sketch in another location,\nand try again. # Rename handler rename.messages.is_untitled = Sketch is Untitled rename.messages.is_untitled.description = How about saving the sketch first\nbefore trying to rename it? rename.messages.is_modified = Please save the sketch before renaming. rename.messages.is_read_only = Sketch is Read-Only -rename.messages.is_read_only.description = Some files are marked \"read-only\", so you'll\nneed to re-save the sketch in another location,\nand try again. +rename.messages.is_read_only.description = Some files are marked \"read-only\", so you will\nneed to re-save the sketch in another location,\nand try again. # Delete handler delete.messages.cannot_delete = Cannot Delete @@ -331,7 +331,7 @@ delete.messages.cannot_delete.description = You can't delete a sketch that has n delete.messages.cannot_delete.file = Couldn't do it delete.messages.cannot_delete.file.description = Could not delete delete.messages.is_read_only = Sketch is Read-Only -delete.messages.is_read_only.description = Some files are marked \"read-only\", so you'll\nneed to re-save the sketch in another location,\nand try again. +delete.messages.is_read_only.description = Some files are marked \"read-only\", so you will\nneed to re-save the sketch in another location,\nand try again. # --------------------------------------- @@ -360,7 +360,7 @@ contrib.errors.list_download = Could not download the list of available contribu contrib.errors.list_download.timeout = Connection timed out while downloading the contribution list. contrib.errors.download_and_install = Error during download and install of %s. contrib.errors.description_unavailable = Description unavailable. -contrib.errors.malformed_url = The link fetched from Processing.org is not valid.\nYou can still install this library manually by visiting\nthe library's website. +contrib.errors.malformed_url = The link fetched from Processing.org is not valid.\nYou can still install this library manually by visiting\nthe library\'s website. contrib.errors.needs_repackage = %s needs to be repackaged according to the %s guidelines. contrib.errors.no_contribution_found = Could not find a %s in the downloaded file. contrib.errors.overwriting_properties = Error overwriting .properties file. @@ -368,7 +368,7 @@ contrib.errors.install_failed = Install failed. contrib.errors.update_on_restart_failed = Update on restart of %s failed. contrib.errors.temporary_directory = Could not write to temporary directory. contrib.errors.contrib_download.timeout = Connection timed out while downloading %s. -contrib.errors.no_internet_connection = You don't seem to be connected to the Internet. +contrib.errors.no_internet_connection = You do not seem to be connected to the Internet. contrib.status.downloading_list = Downloading contribution list... contrib.status.done = Done. contrib.all = All @@ -379,7 +379,7 @@ contrib.progress.installing = Installing contrib.progress.starting = Starting contrib.progress.downloading = Downloading contrib.download_error = An error occured while downloading the contribution. -contrib.unsupported_operating_system = Your operating system doesn't appear to be supported. You should visit the %s's library for more info. +contrib.unsupported_operating_system = Your operating system does not appear to be supported. You should visit the %s\'s library for more info. # --------------------------------------- diff --git a/core/src/processing/core/PApplet.java b/core/src/processing/core/PApplet.java index 2023da85c..fac2aef5f 100644 --- a/core/src/processing/core/PApplet.java +++ b/core/src/processing/core/PApplet.java @@ -147,7 +147,40 @@ public class PApplet implements PConstants { /** The PGraphics renderer associated with this PApplet */ public PGraphics g; + /** + * ( begin auto-generated from displayWidth.xml ) + * + * System variable which stores the width of the computer screen. For + * example, if the current screen resolution is 1024x768, + * displayWidth is 1024 and displayHeight is 768. These + * dimensions are useful when exporting full-screen applications. + *

+ * To ensure that the sketch takes over the entire screen, use "Present" + * instead of "Run". Otherwise the window will still have a frame border + * around it and not be placed in the upper corner of the screen. On Mac OS + * X, the menu bar will remain present unless "Present" mode is used. + * + * ( end auto-generated ) + * @webref environment + */ public int displayWidth; + + /** + * ( begin auto-generated from displayHeight.xml ) + * + * System variable that stores the height of the computer screen. For + * example, if the current screen resolution is 1024x768, + * displayWidth is 1024 and displayHeight is 768. These + * dimensions are useful when exporting full-screen applications. + *

+ * To ensure that the sketch takes over the entire screen, use "Present" + * instead of "Run". Otherwise the window will still have a frame border + * around it and not be placed in the upper corner of the screen. On Mac OS + * X, the menu bar will remain present unless "Present" mode is used. + * + * ( end auto-generated ) + * @webref environment + */ public int displayHeight; /** A leech graphics object that is echoing all events. */ @@ -3020,6 +3053,7 @@ public class PApplet implements PConstants { * * @webref structure * @usage Application + * @param name name of the function to be executed in a separate thread * @see PApplet#setup() * @see PApplet#draw() * @see PApplet#loop() diff --git a/core/todo.txt b/core/todo.txt index 340d0c500..3f4072f98 100644 --- a/core/todo.txt +++ b/core/todo.txt @@ -2,20 +2,6 @@ X detect CMYK JPEG images and return null X https://community.oracle.com/thread/1272045?start=0&tstart=0 -_ remove sketch path hack from PApplet - -python has to use launch() instead of open() -map() is bad for Python (and JavaScript?) - -_ args[] should be null if none passed (otherwise args == null checks are weird) -_ size(640,360 , P3D) doesn't work properly -_ https://github.com/processing/processing/issues/2924 -_ why doesn't p5 punt when loadFont() is used on an otf? -_ is this a GL problem? - -_ show warning when display spanning is turned off -_ defaults read com.apple.spaces spans-displays - data X fix XML.getString() with a default when no attrs are present at all X was causing a NullPointerException @@ -25,23 +11,12 @@ X add optional second param X fixed for FloatDict and IntDict X StringDict won't throw an exception, but optional second param added X add insert() with a single item to StringList, IntList, FloatList -_ add fromOrder() and others? otherwise need temp object: -_ categoryIndexLookup = new StringList(flavors).getOrder(); table X fix how nulls are handled with Table.replace() X add (simple) ODS writer to Table X add addRows(Table) method (more efficient, one resize) X support "header" option with ODS files -_ handling of 'missing' values in Table needs serious work - -graphics -X roll back full screen changes -X https://github.com/processing/processing/issues/2641 -X remove isGL(), is2D(), is3D(), displayable() from PApplet -X these were auto-imported from PGraphics -X remove pause variable from PApplet (was not documented) -X added copy() to PImage (to work like get(), ala PVector) pulls X Fix check in loadShader() @@ -83,6 +58,30 @@ A Exceptions in P3D / P2D not showing up properly A https://github.com/processing/processing/issues/2930 +0233 (3.0a6) + +graphics +X roll back full screen changes +X https://github.com/processing/processing/issues/2641 +X remove isGL(), is2D(), is3D(), displayable() from PApplet +X these were auto-imported from PGraphics +X remove pause variable from PApplet (was not documented) +X added copy() to PImage (to work like get(), ala PVector) + +_ remove sketch path hack from PApplet + +python has to use launch() instead of open() +map() is bad for Python (and JavaScript?) + +_ args[] should be null if none passed (otherwise args == null checks are weird) +_ size(640,360 , P3D) doesn't work properly +_ https://github.com/processing/processing/issues/2924 +_ why doesn't p5 punt when loadFont() is used on an otf? +_ is this a GL problem? + +_ show warning when display spanning is turned off +_ defaults read com.apple.spaces spans-displays + applet/component _ remove Applet as base class _ performance issues on OS X (might be threading due to Applet) @@ -97,8 +96,9 @@ _ make sure it works with retina/canvas/strategy as well processing.data -_ lots of 'data' changes down below -_ need a better method for "missing" data in Table +_ add fromOrder() and others? otherwise need temp object: +_ categoryIndexLookup = new StringList(flavors).getOrder(); +_ handling of 'missing' values in Table needs serious work _ if missing int is zero, can't just remove those values from saving a table _ but for NaN values, it's a necessity _ get() methods in List/Dict shouldn't allow you to get bad values diff --git a/pdex/src/processing/mode/experimental/ASTGenerator.java b/pdex/src/processing/mode/experimental/ASTGenerator.java index d65c4d900..23d37464e 100644 --- a/pdex/src/processing/mode/experimental/ASTGenerator.java +++ b/pdex/src/processing/mode/experimental/ASTGenerator.java @@ -980,18 +980,18 @@ public class ASTGenerator { String[] resources = classPath.findResources("", regExpResourceFilter); for (String matchedClass2 : resources) { - matchedClass2 = matchedClass2.replace('/', '.'); + matchedClass2 = matchedClass2.replace('/', '.'); //package name String matchedClass = matchedClass2.substring(0, matchedClass2 .length() - 6); int d = matchedClass.lastIndexOf('.'); if (ignorableImport(matchedClass2,matchedClass.substring(d + 1))) continue; - matchedClass = matchedClass.substring(d + 1); - candidates - .add(new CompletionCandidate(matchedClass, matchedClass - + " : " + matchedClass2.substring(0, d), matchedClass, - CompletionCandidate.PREDEF_CLASS)); + matchedClass = matchedClass.substring(d + 1); //class name + candidates.add(new CompletionCandidate(matchedClass, "" + + matchedClass + " : " + "" + + matchedClass2.substring(0, d) + "", matchedClass + + "", CompletionCandidate.PREDEF_CLASS)); // display package name in grey //log("-> " + className); } } @@ -3307,6 +3307,68 @@ public class ASTGenerator { } return null; } + + public String[] getSuggestImports(final String className){ + if(ignoredImportSuggestions == null) { + ignoredImportSuggestions = new TreeSet(); + } else { + if(ignoredImportSuggestions.contains(className)) { + log("Ignoring import suggestions for " + className); + return null; + } + } + + log("Looking for class " + className); + RegExpResourceFilter regf = new RegExpResourceFilter( + Pattern.compile(".*"), + Pattern + .compile(className + + ".class", + Pattern.CASE_INSENSITIVE)); + String[] resources = classPath + .findResources("", regf); + ArrayList candidates = new ArrayList(); + for (String res : resources) { + candidates.add(res); + } + + // log("Couldn't find import for class " + className); + + for (Library lib : editor.dmode.contribLibraries) { + ClassPath cp = factory.createFromPath(lib.getClassPath()); + resources = cp.findResources("", regf); + for (String res : resources) { + candidates.add(res); + log("Res: " + res); + } + } + + if (editor.getSketch().hasCodeFolder()) { + File codeFolder = editor.getSketch().getCodeFolder(); + // get a list of .jar files in the "code" folder + // (class files in subfolders should also be picked up) + ClassPath cp = factory.createFromPath(Base + .contentsToClassPath(codeFolder)); + resources = cp.findResources("", regf); + for (String res : resources) { + candidates.add(res); + log("Res: " + res); + } + } + + resources = new String[candidates.size()]; + for (int i = 0; i < resources.length; i++) { + resources[i] = candidates.get(i).replace('/', '.') + .substring(0, candidates.get(i).length() - 6); + } + +// ArrayList ans = new ArrayList(); +// for (int i = 0; i < resources.length; i++) { +// ans.add(resources[i]); +// } + + return resources; + } protected JFrame frmImportSuggest; private TreeSet ignoredImportSuggestions; diff --git a/pdex/src/processing/mode/experimental/ErrorCheckerService.java b/pdex/src/processing/mode/experimental/ErrorCheckerService.java index 1ab2ddae6..753f8066a 100644 --- a/pdex/src/processing/mode/experimental/ErrorCheckerService.java +++ b/pdex/src/processing/mode/experimental/ErrorCheckerService.java @@ -404,7 +404,7 @@ public class ErrorCheckerService implements Runnable{ if (args.length > 0) { String missingClass = args[0]; log("Will suggest for type:" + missingClass); - astGenerator.suggestImports(missingClass); + //astGenerator.suggestImports(missingClass); } } } @@ -1006,6 +1006,30 @@ public class ErrorCheckerService implements Runnable{ if (tempErrorLog.size() < 200) tempErrorLog.put(problemsList.get(i).getMessage(), problemsList .get(i).getIProblem()); + + if(!ExperimentalMode.importSuggestEnabled) continue; + Problem p = problemsList.get(i); + if(p.getIProblem().getID() == IProblem.UndefinedType) { + String args[] = p.getIProblem().getArguments(); + if (args.length > 0) { + String missingClass = args[0]; +// log("Will suggest for type:" + missingClass); + //astGenerator.suggestImports(missingClass); + String[] si = astGenerator.getSuggestImports(missingClass); + if(si != null && si.length > 0){ +// log("Suggested imps"); +// for (int j = 0; j < si.length; j++) { +// log(si[j]); +// } + p.setImportSuggestions(si); + errorData[i][0] = "" + + problemsList.get(i).getMessage() + + " (Import Suggestions available)"; + } + + } + } + } DefaultTableModel tm = new DefaultTableModel(errorData, diff --git a/pdex/src/processing/mode/experimental/ErrorMessageSimplifier.java b/pdex/src/processing/mode/experimental/ErrorMessageSimplifier.java index 177d5d629..7ad7909b2 100644 --- a/pdex/src/processing/mode/experimental/ErrorMessageSimplifier.java +++ b/pdex/src/processing/mode/experimental/ErrorMessageSimplifier.java @@ -83,14 +83,14 @@ public class ErrorMessageSimplifier { + "\" should go here"; } else { - result = "Code error on \"" + args[0] + result = "Error on \"" + args[0] + "\""; } } break; case IProblem.ParsingErrorDeleteToken: if (args.length > 0) { - result = "Code error on \"" + args[0] + "\""; + result = "Error on \"" + args[0] + "\""; } break; case IProblem.ParsingErrorInsertToComplete: @@ -115,7 +115,7 @@ public class ErrorMessageSimplifier { result = "\"color\" and \"int\" are reserved words & can't be used as variable names"; } else { - result = "Code error on \"" + args[0] + "\""; + result = "Error on \"" + args[0] + "\""; } } } diff --git a/pdex/src/processing/mode/experimental/Problem.java b/pdex/src/processing/mode/experimental/Problem.java index 6fa029188..2cae43ce7 100644 --- a/pdex/src/processing/mode/experimental/Problem.java +++ b/pdex/src/processing/mode/experimental/Problem.java @@ -22,6 +22,7 @@ package processing.mode.experimental; +import java.util.ArrayList; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -63,6 +64,11 @@ public class Problem { * The type of error - WARNING or ERROR. */ private int type; + + /** + * If the error is a 'cannot find type' contains the list of suggested imports + */ + private String[] importSuggestions; public static final int ERROR = 1, WARNING = 2; @@ -147,6 +153,14 @@ public class Problem { type = WARNING; else throw new IllegalArgumentException("Illegal Problem type passed to Problem.setType(int)"); } + + public String[] getImportSuggestions() { + return importSuggestions; + } + + public void setImportSuggestions(String[] a) { + importSuggestions = a; + } private static Pattern pattern; private static Matcher matcher; diff --git a/pdex/src/processing/mode/experimental/XQErrorTable.java b/pdex/src/processing/mode/experimental/XQErrorTable.java index b3609c897..25a3be894 100755 --- a/pdex/src/processing/mode/experimental/XQErrorTable.java +++ b/pdex/src/processing/mode/experimental/XQErrorTable.java @@ -22,15 +22,31 @@ package processing.mode.experimental; Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +import java.awt.Color; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionListener; +import java.awt.event.WindowEvent; +import java.awt.event.WindowFocusListener; +import javax.swing.BoxLayout; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JList; +import javax.swing.JPanel; import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.SwingConstants; import javax.swing.SwingWorker; +import javax.swing.ToolTipManager; +import javax.swing.event.ListSelectionEvent; +import javax.swing.event.ListSelectionListener; import javax.swing.table.JTableHeader; import javax.swing.table.TableModel; +import javax.swing.text.BadLocationException; import processing.app.Language; +import static processing.mode.experimental.ExperimentalMode.log; /** * Custom JTable implementation for XQMode. Minor tweaks and addtions. @@ -76,7 +92,7 @@ public class XQErrorTable extends JTable { this.addMouseListener(new MouseAdapter() { @Override - synchronized public void mouseReleased(MouseEvent e) { + synchronized public void mouseClicked(MouseEvent e) { try { errorCheckerService.scrollToErrorLine(((XQErrorTable) e .getSource()).getSelectedRow()); @@ -87,7 +103,66 @@ public class XQErrorTable extends JTable { + e); } } + +// public void mouseMoved(MouseEvent evt) { +// log(evt); +//// String tip = null; +//// java.awt.Point p = evt.getPoint(); +// int rowIndex = rowAtPoint(evt.getPoint()); +// int colIndex = columnAtPoint(evt.getPoint()); +// synchronized (errorCheckerService.problemsList) { +// if (rowIndex < errorCheckerService.problemsList.size()) { +// Problem p = errorCheckerService.problemsList.get(rowIndex); +// if (p.getImportSuggestions() != null +// && p.getImportSuggestions().length > 0) { +// log("Import Suggestions available"); +// } +// } +// } +//// return super.getToolTipText(evt); +// } }); + + final XQErrorTable thisTable = this; + + this.addMouseMotionListener(new MouseMotionListener() { + + @Override + public void mouseMoved(MouseEvent evt) { +// log(evt); +// String tip = null; +// java.awt.Point p = evt.getPoint(); + int rowIndex = rowAtPoint(evt.getPoint()); + int colIndex = columnAtPoint(evt.getPoint()); + synchronized (errorCheckerService.problemsList) { + if (rowIndex < errorCheckerService.problemsList.size()) { + + Problem p = errorCheckerService.problemsList.get(rowIndex); + if (p.getImportSuggestions() != null + && p.getImportSuggestions().length > 0) { + String t = p.getMessage() + "(Import Suggestions available)"; + int x1 = thisTable.getFontMetrics(thisTable.getFont()) + .stringWidth(p.getMessage()), x2 = thisTable + .getFontMetrics(thisTable.getFont()).stringWidth(t); + if(evt.getX() < x1 || evt.getX() > x2) return; + String[] list = p.getImportSuggestions(); + String className = list[0].substring(list[0].lastIndexOf('.') + 1); + String[] temp = new String[list.length]; + for (int i = 0; i < list.length; i++) { + temp[i] = "Import '" + className + "' (" + list[i] + ")"; + } + showImportSuggestion(temp, evt.getXOnScreen(), evt.getYOnScreen() - 3 * thisTable.getFont().getSize()); + } + } + + } + } + + @Override + public void mouseDragged(MouseEvent e) { + + } + }); // Handles the resizing of columns. When mouse press is detected on // table header, Stop updating the table, store new values of column @@ -111,8 +186,9 @@ public class XQErrorTable extends JTable { } } }); + + ToolTipManager.sharedInstance().registerComponent(this); } - /** * Updates table contents with new data @@ -163,5 +239,79 @@ public class XQErrorTable extends JTable { } return true; } + JFrame frmImportSuggest; + private void showImportSuggestion(String list[], int x, int y){ + if(frmImportSuggest != null) { +// frmImportSuggest.setVisible(false); +// frmImportSuggest = null; + return; + } + final JList classList = new JList(list); + classList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); + frmImportSuggest = new JFrame(); + + frmImportSuggest.setUndecorated(true); + frmImportSuggest.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + JPanel panel = new JPanel(); + panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS)); + panel.setBackground(Color.WHITE); + frmImportSuggest.setBackground(Color.WHITE); + panel.add(classList); + JLabel label = new JLabel("

(Click to insert)
"); + label.setBackground(Color.WHITE); + label.setHorizontalTextPosition(SwingConstants.LEFT); + panel.add(label); + panel.validate(); + frmImportSuggest.getContentPane().add(panel); + frmImportSuggest.pack(); + + final DebugEditor editor = errorCheckerService.getEditor(); + classList.addListSelectionListener(new ListSelectionListener() { + + @Override + public void valueChanged(ListSelectionEvent e) { + if (classList.getSelectedValue() != null) { + try { + String t = classList.getSelectedValue().trim(); + log(t); + int x = t.indexOf('('); + String impString = "import " + t.substring(x + 1, t.indexOf(')')) + ";\n"; + int ct = editor.getSketch().getCurrentCodeIndex(); + editor.getSketch().setCurrentCode(0); + editor.textArea().getDocument().insertString(0, impString, null); + editor.getSketch().setCurrentCode(ct); + } catch (BadLocationException ble) { + log("Failed to insert import"); + ble.printStackTrace(); + } + } + frmImportSuggest.setVisible(false); + frmImportSuggest.dispose(); + frmImportSuggest = null; + } + }); + + frmImportSuggest.addWindowFocusListener(new WindowFocusListener() { + + @Override + public void windowLostFocus(WindowEvent e) { + if (frmImportSuggest != null) { + frmImportSuggest.dispose(); + frmImportSuggest = null; + } + } + + @Override + public void windowGainedFocus(WindowEvent e) { + + } + }); + frmImportSuggest.setLocation(x, y); + frmImportSuggest.setBounds(x, y, 250, 100); + frmImportSuggest.pack(); + frmImportSuggest.setVisible(true); + + } + } diff --git a/todo.txt b/todo.txt index 98cce7130..5cb26bcc6 100644 --- a/todo.txt +++ b/todo.txt @@ -7,16 +7,13 @@ X remove sound library, have it installed separately like video X Fix the shortcut keybindings in editor tab popup menu X https://github.com/processing/processing/issues/179 X https://github.com/processing/processing/pull/2821 - -_ any problems with new code signing crap? -_ issues raised around the symlink (just replace with a copy of the binary?) -_ https://developer.apple.com/library/prerelease/mac/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG205 - -deb questions: https://github.com/processing/processing/issues/114 -better Linux packaging... -http://askubuntu.com/questions/396857/how-can-i-add-processing-to-the-unity-launcher - -_ add script to download JRE and JDK from Oracle +X answer deb questions +X https://github.com/processing/processing/issues/114 +X change how languages are loaded +X add local override (needs documentation) +X figure out copyDir() problems before pull +o moving window to a new location is broken due to the pull +X update to use new 7u72 version of JRE (and JDK) stuff manindra X ToolTipManager error @@ -66,6 +63,21 @@ X Implement the active() method for Serial and Server X https://github.com/processing/processing/issues/2364 X https://github.com/processing/processing/pull/2588 + +0233 (3.0a6) + +_ any problems with new code signing crap? +_ issues raised around the symlink (just replace with a copy of the binary?) +_ https://developer.apple.com/library/prerelease/mac/technotes/tn2206/_index.html#//apple_ref/doc/uid/DTS40007919-CH1-TNTAG205 + +_ add script to download JRE and JDK from Oracle + +_ post a note about the "help" stuff +_ https://github.com/processing/processing/labels/help + +_ finish Ant task to download JRE and JDK from Oracle +_ add method to prompt user to download the JDK update + _ Add support for localizing contributions _ https://github.com/processing/processing/pull/2833 _ check on pull for mnemonics