mirror of
https://github.com/processing/processing4.git
synced 2026-06-16 04:26:26 +02:00
here we go
This commit is contained in:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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">
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
# ---------------------------------------
|
||||
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user