here we go

This commit is contained in:
Ben Fry
2014-11-15 22:28:13 -07:00
parent 670be28df5
commit c9d4b635af
11 changed files with 490 additions and 227 deletions
+9 -1
View File
@@ -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));
}
+138 -185
View File
@@ -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<String, String> 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<String, String> 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<String, String>();
@@ -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<String, String> 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,56 @@ public class Language {
return bundle;
}
}
*/
static class LanguageBundle {
Map<String, String> table;
LanguageBundle(String language) throws IOException {
table = new HashMap<String, String>();
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();
table.put(key, value);
}
}
}
String getString(String key) {
return table.get(key);
}
boolean containsKey(String key) {
return table.containsKey(key);
}
}
}
+26 -18
View File
@@ -34,13 +34,25 @@
<property name="examples.dir"
value="../../processing-docs/content/examples" />
<property name="jdk.version" value="7" />
<property name="jdk.update" value="72" />
<property name="jdk.build" value="14" />
<property name="jdk.stuff" value="${jdk.version}u${jdk.update}" />
<property name="jdk.esoteric" value="1.${jdk.version}.0_${jdk.update}" />
<!-- Figure out the JRE download location for Linux and Windows. -->
<condition property="jre.file" value="jre-7u40-${platform}-i586.tgz">
<condition property="jre.file"
value="jre-${jdk.stuff}-${platform}-i586.tar.gz">
<equals arg1="${sun.arch.data.model}" arg2="32" />
</condition>
<condition property="jre.file" value="jre-7u40-${platform}-x64.tgz">
<condition property="jre.file"
value="jre-${jdk.stuff}-${platform}-x64.tar.gz">
<equals arg1="${sun.arch.data.model}" arg2="64" />
</condition>
<!-- JDK location for Mac OS X -->
<condition property="jdk.file" value="jdk-${jdk.stuff}-macosx-x64.dmg">
<equals arg1="${platform}" arg2="macosx" />
</condition>
<fileset dir="windows/work/java" id="jre-optional-windows">
<include name="bin/dtplugin" />
@@ -154,13 +166,13 @@
</condition>
<!-- Set the version of Java that must be present to build. -->
<property name="jdk.update.macosx" value="72" />
<property name="jdk.path.macosx" value="/Library/Java/JavaVirtualMachines/jdk1.7.0_${jdk.update.macosx}.jdk" />
<property name="jdk.path.macosx"
value="/Library/Java/JavaVirtualMachines/jdk${jdk.esoteric}.jdk" />
<available file="${jdk.path.macosx}" property="macosx_jdk_found" />
<fail if="macosx" unless="macosx_jdk_found"
message="JDK 7u${jdk.update.macosx} required.${line.separator}To build on OS X, you must install Oracle's JDK 7u${jdk.update.macosx} from${line.separator}http://www.oracle.com/technetwork/java/javase/downloads${line.separator}Note that only 7u${jdk.update.macosx} (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." />
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." />
<!--
<fail if="linux" unless="java_tools_found"
message="The JAVA_HOME variable must be set to the location of a full JDK. For instance, on Ubuntu Linux, this might be /usr/lib/jvm/java-6-sun." />
@@ -475,7 +487,7 @@
Also, because Ant's copy task does not retain file permissions on Unix systems,
we need to use <exec executable="cp" ... > instead -->
<exec executable="cp">
<arg line="${jdk.path.macosx}/Contents/Home/bin/keytool macosx/work/Processing.app/Contents/PlugIns/jdk1.7.0_${jdk.update.macosx}.jdk/Contents/Home/jre/bin"/>
<arg line="${jdk.path.macosx}/Contents/Home/bin/keytool macosx/work/Processing.app/Contents/PlugIns/jdk${jdk.esoteric}.jdk/Contents/Home/jre/bin"/>
</exec>
<copy todir="macosx/work/Processing.app/Contents/Java">
@@ -488,7 +500,7 @@
<!--
Processing.app/Contents/PlugIns/jdk1.7.0_40.jdk/Contents/Home/jre/lib/fonts
-->
<copy todir="macosx/work/Processing.app/Contents/PlugIns/jdk1.7.0_${jdk.update.macosx}.jdk/Contents/Home/jre/lib/fonts">
<copy todir="macosx/work/Processing.app/Contents/PlugIns/jdk${jdk.esoteric}.jdk/Contents/Home/jre/lib/fonts">
<fileset dir="shared/lib/fonts" includes="*" />
</copy>
@@ -543,7 +555,7 @@
<arg value="--force" />
<arg value="--sign" />
<arg value="Developer ID Application" />
<arg value="Processing.app/Contents/PlugIns/jdk1.7.0_${jdk.update.macosx}.jdk" />
<arg value="Processing.app/Contents/PlugIns/jdk${jdk.esoteric}.jdk" />
</exec>
<exec executable="/usr/bin/codesign" dir="macosx/work">
@@ -649,12 +661,7 @@
<copy file="linux/processing" tofile="linux/work/processing-java" />
<chmod perm="ugo+x" file="linux/work/processing-java" />
<!--
<property name="jre.file"
value="jre-tools-6u37-linux${sun.arch.data.model}.tgz" />
-->
<get src="http://processing.googlecode.com/files/${jre.file}"
<get src="http://download.processing.org/java/${jre.file}"
dest="linux/jre.tgz"
usetimestamp="true" />
@@ -687,10 +694,10 @@
<exec executable="rsync" dir="linux">
<arg value="-a" />
<arg value="--delete" />
<arg value="jre1.7.0_40/" />
<arg value="jre${jdk.esoteric}/" />
<arg value="work/java" />
</exec>
<delete dir="linux/jre1.7.0_40" />
<delete dir="linux/jre${jdk.esoteric}" />
<!-- Remove unused JRE bloat. -->
<delete failonerror="true">
@@ -820,7 +827,7 @@
</chmod>
<!-- starting with 2.0a7, require the local JRE + tools.jar -->
<get src="http://processing.googlecode.com/files/${jre.file}"
<get src="http://download.processing.org/java/${jre.file}"
dest="windows/jre.tgz"
usetimestamp="true" />
@@ -833,7 +840,8 @@
dest="windows/work"
src="windows/jre.tgz"
overwrite="false" />
<move file="windows/work/jre1.7.0_40" tofile="windows/work/java" />
<move file="windows/work/jre${jdk.esoteric}"
tofile="windows/work/java" />
<!-- Remove space-wasting JavaFX garbage. -->
<delete failonerror="true">
+7 -7
View File
@@ -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.
# ---------------------------------------
+34
View File
@@ -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,
* <b>displayWidth</b> is 1024 and <b>displayHeight</b> is 768. These
* dimensions are useful when exporting full-screen applications.
* <br /><br />
* 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,
* <b>displayWidth</b> is 1024 and <b>displayHeight</b> is 768. These
* dimensions are useful when exporting full-screen applications.
* <br /><br />
* 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()
@@ -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, "<html>"
+ matchedClass + " : " + "<font color=#777777>"
+ matchedClass2.substring(0, d) + "</font>", matchedClass
+ "</html>", 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<String>();
} 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<String> candidates = new ArrayList<String>();
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<String> ans = new ArrayList<String>();
// for (int i = 0; i < resources.length; i++) {
// ans.add(resources[i]);
// }
return resources;
}
protected JFrame frmImportSuggest;
private TreeSet<String> ignoredImportSuggestions;
@@ -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] = "<html>"
+ problemsList.get(i).getMessage()
+ " (<font color=#0000ff><u>Import Suggestions available</u></font>)</html>";
}
}
}
}
DefaultTableModel tm = new DefaultTableModel(errorData,
@@ -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] + "\"";
}
}
}
@@ -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;
@@ -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] = "<html>Import '" + className + "' <font color=#777777>(" + list[i] + ")</font></html>";
}
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<String> classList = new JList<String>(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("<html><div alight = \"left\"><font size = \"2\"><br>(Click to insert)</font></div></html>");
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);
}
}
+14 -4
View File
@@ -7,15 +7,18 @@ 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
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
_ 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
manindra
@@ -66,6 +69,13 @@ 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
_ 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