import java.nio.charset.Charset;
import java.util.LinkedList;
import java.util.List;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import be.nikiroo.jvcard.remote.SimpleSocket;
import be.nikiroo.jvcard.resources.Bundles;
import be.nikiroo.jvcard.resources.StringUtils;
-import be.nikiroo.jvcard.resources.Trans;
-import be.nikiroo.jvcard.resources.Trans.StringId;
+import be.nikiroo.jvcard.resources.bundles.ColorBundle;
+import be.nikiroo.jvcard.resources.bundles.DisplayBundle;
+import be.nikiroo.jvcard.resources.bundles.RemoteBundle;
+import be.nikiroo.jvcard.resources.bundles.TransBundle;
+import be.nikiroo.jvcard.resources.enums.DisplayOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
/**
* This class contains the runnable Main method. It will parse the user supplied
static private final int ERR_NO_FILE = 1;
static private final int ERR_SYNTAX = 2;
static private final int ERR_INTERNAL = 3;
- static private Trans transService;
+ static private TransBundle transService;
static private String defaultFn;
static private boolean forceComputedFn;
enum Mode {
- CONTACT_MANAGER, I18N, SERVER, LOAD_PHOTO, SAVE_PHOTO, ONLY_PHOTO,
+ CONTACT_MANAGER, I18N, SERVER, LOAD_PHOTO, SAVE_PHOTO, ONLY_PHOTO, SAVE_CONFIG
}
/**
*
* @return the translated text with the given value where required
*/
- static public String trans(StringId id, String... values) {
- return transService.trans(id, (String[]) values);
+ static public String trans(StringId id, Object... values) {
+ return transService.getString(id, (Object[]) values);
}
/**
// get the "system default" language to help translate the --help
// message if needed
String language = null;
- transService = new Trans(language);
+ transService = new TransBundle(language);
boolean unicode = transService.isUnicode();
String dir = null;
+ "\t--tui: force pure text mode even if swing treminal is available\n"
+ "\t--gui: force swing terminal mode\n"
+ "\t--noutf: force non-utf8 mode if you need it\n"
- + "\t--config DIRECTORY: force the given directory as a CONFIG_DIR\n"
+ + "\t--config DIRECTORY: use the given directory as a CONFIG_DIR\n"
+ + "\t--save-config DIRECTORY: save the current config to DIRECTORY (lang: only current)\n"
+ "\t--server PORT: start a remoting server instead of a client\n"
+ "\t--i18n DIR: generate the translation file for the given language (can be \"\") to/from the .properties given dir\n"
+ "\t--save-photo DIR FORMAT: save the contacts' photos to DIR, named after FORMAT\n"
}
language = args[index];
- transService = new Trans(language);
+ transService = new TransBundle(language);
transService.setUnicode(unicode);
} else if (!noMoreParams && arg.equals("--config")) {
index++;
}
Bundles.setDirectory(args[index]);
- transService = new Trans(language);
+ transService = new TransBundle(language);
transService.setUnicode(unicode);
+ } else if (!noMoreParams && arg.equals("--save-config")) {
+ index++;
+ if (index >= args.length) {
+ System.err
+ .println("Syntax error: no config directory given");
+ System.exit(ERR_SYNTAX);
+ return;
+ }
+ dir = args[index];
+
+ if (mode != Mode.CONTACT_MANAGER) {
+ System.err
+ .println("Syntax error: you can only use one of: \n"
+ + "--server\n"
+ + "--save-config\n"
+ + "--i18n\n"
+ + "--load-photo\n"
+ + "--save-photo\n" + "--only-photo\n");
+ System.exit(ERR_SYNTAX);
+ return;
+ }
+ mode = Mode.SAVE_CONFIG;
} else if (!noMoreParams && arg.equals("--server")) {
if (mode != Mode.CONTACT_MANAGER) {
System.err
.println("Syntax error: you can only use one of: \n"
+ "--server\n"
+ + "--save-config\n"
+ "--i18n\n"
+ "--load-photo\n"
- + "--save-photo\n"
- + "--only-photo\n");
+ + "--save-photo\n" + "--only-photo\n");
System.exit(ERR_SYNTAX);
return;
}
System.err
.println("Syntax error: you can only use one of: \n"
+ "--server\n"
+ + "--save-config\n"
+ "--i18n\n"
+ "--load-photo\n"
- + "--save-photo\n"
- + "--only-photo\n");
+ + "--save-photo\n" + "--only-photo\n");
System.exit(ERR_SYNTAX);
return;
}
System.err
.println("Syntax error: you can only use one of: \n"
+ "--server\n"
+ + "--save-config\n"
+ "--i18n\n"
+ "--load-photo\n"
- + "--save-photo\n"
- + "--only-photo\n");
+ + "--save-photo\n" + "--only-photo\n");
System.exit(ERR_SYNTAX);
return;
}
//
switch (mode) {
+ case SAVE_CONFIG: {
+ try {
+ if (!new File(dir).isDirectory()) {
+ if (!new File(dir).mkdir()) {
+ System.err
+ .println("Cannot create configuration directory: "
+ + dir);
+ }
+ }
+
+ transService.updateFile(dir); // current lang TransBundle
+ new TransBundle().updateFile(dir);
+ new ColorBundle().updateFile(dir);
+ new DisplayBundle().updateFile(dir);
+ new RemoteBundle().updateFile(dir);
+ } catch (IOException e) {
+ e.printStackTrace();
+ System.exit(ERR_INTERNAL);
+ }
+ break;
+ }
case SERVER: {
try {
Optional.runServer(port);
}
case I18N: {
try {
- Trans.generateTranslationFile(dir, language);
+ transService.updateFile(dir);
} catch (IOException e) {
System.err
.println("I/O Exception: Cannot create/update a language in directory: "
+ dir);
+ e.printStackTrace();
}
break;
}
* or always, or never.
*/
static private void readNFN() {
- ResourceBundle map = Bundles.getBundle("display");
- try {
- defaultFn = map.getString("CONTACT_DETAILS_DEFAULT_FN");
- if (defaultFn.trim().length() == 0)
- defaultFn = null;
- } catch (MissingResourceException e) {
- e.printStackTrace();
- }
+ DisplayBundle map = new DisplayBundle();
- try {
- String forceComputedFnStr = map
- .getString("CONTACT_DETAILS_SHOW_COMPUTED_FN");
- if (forceComputedFnStr.length() > 0
- && forceComputedFnStr.equalsIgnoreCase("true"))
- forceComputedFn = true;
- } catch (MissingResourceException e) {
- e.printStackTrace();
- }
+ defaultFn = map.getString(DisplayOption.CONTACT_DETAILS_DEFAULT_FN);
+
+ forceComputedFn = map.getBoolean(
+ DisplayOption.CONTACT_DETAILS_SHOW_COMPUTED_FN, false);
}
}
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.ResourceBundle;
import be.nikiroo.jvcard.Card;
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.Data;
import be.nikiroo.jvcard.parsers.Format;
import be.nikiroo.jvcard.parsers.Vcard21Parser;
-import be.nikiroo.jvcard.resources.Bundles;
import be.nikiroo.jvcard.resources.StringUtils;
+import be.nikiroo.jvcard.resources.bundles.RemoteBundle;
+import be.nikiroo.jvcard.resources.enums.RemotingOption;
/**
* This class implements a small server that can listen for requests to
*/
public Server(int port) throws IOException {
this.port = port;
- ResourceBundle bundle = Bundles.getBundle("remote");
+ RemoteBundle bundle = new RemoteBundle();
try {
- String dir = bundle.getString("SERVER_DATA_PATH");
+ String dir = bundle.getString(RemotingOption.SERVER_DATA_PATH);
dataDir = new File(dir);
dataDir.mkdir();
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import be.nikiroo.jvcard.Card;
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.launcher.CardResult.MergeCallback;
import be.nikiroo.jvcard.parsers.Format;
import be.nikiroo.jvcard.parsers.Vcard21Parser;
-import be.nikiroo.jvcard.resources.Bundles;
import be.nikiroo.jvcard.resources.StringUtils;
+import be.nikiroo.jvcard.resources.bundles.RemoteBundle;
+import be.nikiroo.jvcard.resources.enums.RemotingOption;
/**
* This class will synchronise {@link Card}s between a local instance an a
*/
static private void config() {
String dir = null;
- ResourceBundle bundle = Bundles.getBundle("remote");
+ RemoteBundle bundle = new RemoteBundle();
try {
- dir = bundle.getString("CLIENT_CACHE_DIR").trim();
+ dir = bundle.getString(RemotingOption.CLIENT_CACHE_DIR);
cacheDir = new File(dir + File.separator + "current");
cacheDir.mkdir();
+ dir);
}
- String autoStr = bundle.getString("CLIENT_AUTO_SYNC");
- if (autoStr != null && autoStr.trim().equalsIgnoreCase("true")) {
- autoSync = true;
- }
-
- } catch (MissingResourceException e) {
- throw new InvalidParameterException(
- "Cannot access remote.properties configuration file");
+ autoSync = bundle
+ .getBoolean(RemotingOption.CLIENT_AUTO_SYNC, false);
} catch (Exception e) {
throw new InvalidParameterException(
"Cannot open or create cache store at: " + dir);
package be.nikiroo.jvcard.resources;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.reflect.Field;
import java.util.Locale;
import java.util.ResourceBundle;
public class Bundles {
static private String confDir = getConfDir();
- // TODO: create "Trans" like classes for all .properties file, always get it
- // them from here, including Trans (create a new one each time like
- // currently) + update Main to call trans again when chaning dir
- private int TODO;
-
/**
- * Return the non-localised bundle of the given name.
- *
- * @param name
- * the name of the bundle to load
+ * The type of configuration information the associated {@link Bundle} will
+ * convey.
*
- * @return the bundle
+ * @author niki
+ *
*/
- static public ResourceBundle getBundle(String name) {
- return ResourceBundle.getBundle(Bundles.class.getPackage().getName()
- + "." + name, new FixedResourceBundleControl(confDir));
+ public enum Target {
+ colors, display, jvcard, remote, resources
}
/**
- * Return the localised bundle of the given name and {@link Locale}.
- *
- * @param name
- * the name of the bundle to load
- * @param locale
- * the {@link Locale} to use
+ * Return the configuration directory where to try to find the
+ * <tt>.properties</tt> files in priority.
*
- * @return the localised bundle
+ * @return the configuration directory
*/
- static public ResourceBundle getBundle(String name, Locale locale) {
- return ResourceBundle.getBundle(Bundles.class.getPackage().getName()
- + "." + name, locale, new FixedResourceBundleControl(confDir));
+ static private String getConfDir() {
+ // Do not override user-supplied config directory (see --help)
+ if (Bundles.confDir != null)
+ return Bundles.confDir;
+
+ try {
+ ResourceBundle bundle = ResourceBundle.getBundle(Bundles.class
+ .getPackage().getName() + "." + "jvcard",
+ Locale.getDefault(), new FixedResourceBundleControl(null));
+
+ String configDir = bundle.getString("CONFIG_DIR");
+ if (configDir != null && configDir.trim().length() > 0)
+ return configDir;
+ } catch (Exception e) {
+ }
+
+ return null;
}
/**
}
/**
- * Return the configuration directory where to try to find the
- * <tt>.properties</tt> files in priority.
+ * This class encapsulate a {@link ResourceBundle} in UTF-8. It only allows
+ * to retrieve values associated to an enumeration, and allows some
+ * additional methods.
*
- * @return the configuration directory
+ * @author niki
+ *
+ * @param <E>
+ * the enum to use to get values out of this class
*/
- static private String getConfDir() {
- // Do not override user-supplied config directory (see --help)
- if (Bundles.confDir != null)
- return Bundles.confDir;
+ public class Bundle<E extends Enum<E>> {
+ private Class<E> type;
+ protected Target name;
+ protected ResourceBundle map;
- try {
- ResourceBundle bundle = ResourceBundle.getBundle(Bundles.class
- .getPackage().getName() + "." + "jvcard",
- Locale.getDefault(), new FixedResourceBundleControl(null));
+ /**
+ * Create a new {@link Bundles} of the given name.
+ *
+ * @param type
+ * a runtime instance of the class of E
+ *
+ * @param name
+ * the name of the {@link Bundles}
+ */
+ protected Bundle(Class<E> type, Target name) {
+ this.type = type;
+ this.name = name;
+ this.map = getBundle(name);
+ }
- String configDir = bundle.getString("CONFIG_DIR");
- if (configDir != null && configDir.trim().length() > 0)
- return configDir;
- } catch (Exception e) {
+ /**
+ * Return the value associated to the given id as a {@link String}.
+ *
+ * @param mame
+ * the id of the value to get
+ *
+ * @return the associated value
+ */
+ public String getString(E id) {
+ if (map.containsKey(id.name())) {
+ return map.getString(id.name()).trim();
+ }
+
+ return "";
}
- return null;
- }
+ /**
+ * Return the value associated to the given id as a {@link Boolean}.
+ *
+ * @param mame
+ * the id of the value to get
+ *
+ * @return the associated value
+ */
+ public Boolean getBoolean(E id) {
+ String str = getString(id);
+ if (str != null && str.length() > 0) {
+ if (str.equalsIgnoreCase("true") || str.equalsIgnoreCase("on")
+ || str.equalsIgnoreCase("yes"))
+ return true;
+ if (str.equalsIgnoreCase("false")
+ || str.equalsIgnoreCase("off")
+ || str.equalsIgnoreCase("no"))
+ return false;
+
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the value associated to the given id as a {@link boolean}.
+ *
+ * @param mame
+ * the id of the value to get
+ * @param def
+ * the default value when it is not present in the config
+ * file or if it is not a boolean value
+ *
+ * @return the associated value
+ */
+ public boolean getBoolean(E id, boolean def) {
+ Boolean b = getBoolean(id);
+ if (b != null)
+ return b;
+
+ return def;
+ }
+
+ /**
+ * Return the value associated to the given id as an {@link Integer}.
+ *
+ * @param mame
+ * the id of the value to get
+ *
+ * @return the associated value
+ */
+ public Integer getInteger(E id) {
+ try {
+ return Integer.parseInt(getString(id));
+ } catch (Exception e) {
+ }
+
+ return null;
+ }
+
+ /**
+ * Return the value associated to the given id as a {@link int}.
+ *
+ * @param mame
+ * the id of the value to get
+ * @param def
+ * the default value when it is not present in the config
+ * file or if it is not a int value
+ *
+ * @return the associated value
+ */
+ public int getInteger(E id, int def) {
+ Integer i = getInteger(id);
+ if (i != null)
+ return i;
+
+ return def;
+ }
+
+ /**
+ * Create/update the .properties file. Will use the most likely
+ * candidate as base if the file does not already exists and this
+ * resource is translatable (for instance, "en_US" will use "en" as a
+ * base if the resource is a translation file).
+ *
+ * @param path
+ * the path where the .properties files are
+ *
+ * @throws IOException
+ * in case of IO errors
+ */
+ public void updateFile(String path) throws IOException {
+ File file = getUpdateFile(path);
+
+ BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
+ new FileOutputStream(file), "UTF-8"));
+
+ writeHeader(writer);
+ writer.write("\n");
+ writer.write("\n");
+
+ for (Field field : type.getDeclaredFields()) {
+ Meta meta = field.getAnnotation(Meta.class);
+ if (meta != null) {
+ E id = E.valueOf(type, field.getName());
+ String info = getMetaInfo(meta);
+
+ if (info != null) {
+ writer.write(info);
+ writer.write("\n");
+ }
+
+ writeValue(writer, id);
+ }
+ }
+
+ writer.close();
+ }
+ /**
+ * Return formated, display-able information from the {@link Meta} field
+ * given. Each line will always starts with a "#" character.
+ *
+ * @param meta
+ * the {@link Meta} field
+ *
+ * @return the information to display or NULL if none
+ */
+ protected String getMetaInfo(Meta meta) {
+ String what = meta.what();
+ String where = meta.where();
+ String format = meta.format();
+ String info = meta.info();
+
+ int opt = what.length() + where.length() + format.length();
+ if (opt + info.length() == 0)
+ return null;
+
+ StringBuilder builder = new StringBuilder();
+ builder.append("# ");
+
+ if (opt > 0) {
+ builder.append("(");
+ if (what.length() > 0) {
+ builder.append("WHAT: " + what);
+ if (where.length() + format.length() > 0)
+ builder.append(", ");
+ }
+
+ if (where.length() > 0) {
+ builder.append("WHERE: " + where);
+ if (format.length() > 0)
+ builder.append(", ");
+ }
+
+ if (format.length() > 0) {
+ builder.append("FORMAT: " + format);
+ }
+
+ builder.append(")");
+ if (info.length() > 0) {
+ builder.append("\n# ");
+ }
+ }
+
+ builder.append(info);
+
+ return builder.toString();
+ }
+
+ /**
+ * Write the header found in the configuration <tt>.properties</tt> file
+ * of this {@link Bundles}.
+ *
+ * @param writer
+ * the {@link Writer} to write the header in
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ protected void writeHeader(Writer writer) throws IOException {
+ writer.write("# " + name + "\n");
+ writer.write("#\n");
+ }
+
+ /**
+ * Write the given id to the config file, i.e.,
+ * "MY_ID = my_curent_value" followed by a new line
+ *
+ * @param writer
+ * the {@link Writer} to write into
+ * @param id
+ * the id to write
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ protected void writeValue(Writer writer, E id) throws IOException {
+ writer.write(id.name());
+ writer.write(" = ");
+ writer.write(getString(id));
+ writer.write("\n");
+ }
+
+ /**
+ * Return the non-localised bundle of the given name.
+ *
+ * @param name
+ * the name of the bundle to load
+ *
+ * @return the bundle
+ */
+ protected ResourceBundle getBundle(Target name) {
+ return ResourceBundle.getBundle(Bundles.class.getPackage()
+ .getName() + "." + name.name(),
+ new FixedResourceBundleControl(confDir));
+ }
+
+ /**
+ * Return the localised bundle of the given name and {@link Locale}.
+ *
+ * @param name
+ * the name of the bundle to load
+ * @param locale
+ * the {@link Locale} to use
+ *
+ * @return the localised bundle
+ */
+ protected ResourceBundle getBundle(Target name, Locale locale) {
+ return ResourceBundle.getBundle(Bundles.class.getPackage()
+ .getName() + "." + name.name(), locale,
+ new FixedResourceBundleControl(confDir));
+ }
+
+ /**
+ * Return the source file for this {@link Bundles} from the given path.
+ *
+ * @param path
+ * the path where the .properties files are
+ *
+ * @return the source {@link File}
+ *
+ * @throws IOException
+ * in case of IO errors
+ */
+ protected File getUpdateFile(String path) {
+ return new File(path, name.name() + ".properties");
+ }
+ }
}
+++ /dev/null
-package be.nikiroo.jvcard.resources;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStreamWriter;
-import java.lang.reflect.Field;
-import java.util.Locale;
-import java.util.ResourceBundle;
-
-/**
- * This class manages the translation of {@link Trans.StringId}s into
- * user-understandable text.
- *
- * @author niki
- *
- */
-public class Trans {
- private ResourceBundle map;
- private boolean utf = true;
- private Locale locale;
-
- /**
- * Create a translation service with the default language.
- */
- public Trans() {
- setLanguage(null);
- }
-
- /**
- * Create a translation service for the given language. (Will fall back to
- * the default one i not found.)
- *
- * @param language
- * the language to use
- */
- public Trans(String language) {
- setLanguage(language);
- }
-
- /**
- * Translate the given {@link StringId} into user text.
- *
- * @param stringId
- * the ID to translate
- * @param values
- * the values to insert instead of the place holders in the
- * translation
- *
- * @return the translated text with the given value where required
- */
- public String trans(StringId stringId, String... values) {
- StringId id = stringId;
- String result = null;
-
- if (!isUnicode()) {
- try {
- id = StringId.valueOf(stringId.name() + "_NOUTF");
- } catch (IllegalArgumentException iae) {
- // no special _NOUTF version found
- }
- }
-
- if (id == StringId.NULL) {
- result = "";
- } else if (id == StringId.DUMMY) {
- result = "[dummy]";
- } else if (map.containsKey(id.name())) {
- result = map.getString(id.name());
- } else {
- result = id.toString();
- }
-
- if (values != null && values.length > 0)
- return String.format(locale, result, (Object[]) values);
- else
- return result;
- }
-
- /**
- * Check if unicode characters should be used.
- *
- * @return TRUE to allow unicode
- */
- public boolean isUnicode() {
- return utf;
- }
-
- /**
- * Allow or disallow unicode characters in the program.
- *
- * @param utf
- * TRUE to allow unuciode, FALSE to only allow ASCII characters
- */
- public void setUnicode(boolean utf) {
- this.utf = utf;
- }
-
- /**
- * Initialise the translation mappings for the given language.
- *
- * @param language
- * the language to initialise, in the form "en-GB" or "fr" for
- * instance
- */
- private void setLanguage(String language) {
- locale = getLocaleFor(language);
- map = Bundles.getBundle("resources", locale);
- }
-
- /**
- * Create/update the translation .properties files. Will use the most likely
- * candidate as base if the file does not already exists (for instance,
- * "en_US" will use "en" as a base).
- *
- * @param path
- * the path where the .properties files are
- *
- * @param language
- * the language code to create/update (e.g.: <tt>fr-BE</tt>)
- *
- * @throws IOException
- * in case of IO errors
- */
- static public void generateTranslationFile(String path, String language)
- throws IOException {
-
- Locale locale = getLocaleFor(language);
- String code = locale.toString();
- Trans trans = new Trans(code);
-
- File file = null;
- if (code.length() > 0) {
- file = new File(path + "resources_" + code + ".properties");
- } else {
- // Default properties file:
- file = new File(path + "resources.properties");
- }
-
- BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
- new FileOutputStream(file), "UTF-8"));
-
- String name = locale.getDisplayCountry(locale);
- if (name.length() == 0)
- name = locale.getDisplayLanguage(locale);
- if (name.length() == 0)
- name = "default";
-
- if (code.length() > 0) {
- name = name + " (" + code + ")";
- }
-
- writer.append("# " + name + " translation file (UTF-8)\n");
- writer.append("# \n");
- writer.append("# Note that any key can be doubled with a _NOUTF suffix\n");
- writer.append("# to use when the flag --noutf is passed\n");
- writer.append("# \n");
- writer.append("# Also, the comments always refer to the key below them.\n");
- writer.append("# \n");
- writer.append("\n");
-
- for (Field field : StringId.class.getDeclaredFields()) {
- Meta meta = field.getAnnotation(Meta.class);
- if (meta != null) {
- StringId id = StringId.valueOf(field.getName());
- String info = getMetaInfo(meta);
- if (info != null) {
- writer.append(info);
- writer.append("\n");
- }
-
- writer.append(id.name());
- writer.append(" = ");
- if (!trans.trans(id).equals(id.name()))
- writer.append(trans.trans(id));
- writer.append("\n");
- }
- }
-
- writer.close();
- }
-
- /**
- * Return the {@link Locale} representing the given language.
- *
- * @param language
- * the language to initialise, in the form "en-GB" or "fr" for
- * instance
- *
- * @return the corresponding {@link Locale} or the default {@link Locale} if
- * it is not known
- */
- static private Locale getLocaleFor(String language) {
- Locale locale;
-
- if (language == null) {
- locale = Locale.getDefault();
- } else {
- language = language.replaceAll("_", "-");
- String lang = language;
- String country = null;
- if (language.contains("-")) {
- lang = language.split("-")[0];
- country = language.split("-")[1];
- }
-
- if (country != null)
- locale = new Locale(lang, country);
- else
- locale = new Locale(lang);
- }
-
- return locale;
- }
-
- /**
- * Return formated, display-able information from the {@link Meta} field
- * given. Each line will always starts with a "#" character.
- *
- * @param meta
- * the {@link Meta} field
- *
- * @return the information to display or NULL if none
- */
- static private String getMetaInfo(Meta meta) {
- String what = meta.what();
- String where = meta.where();
- String format = meta.format();
- String info = meta.info();
-
- int opt = what.length() + where.length() + format.length();
- if (opt + info.length() == 0)
- return null;
-
- StringBuilder builder = new StringBuilder();
- builder.append("# ");
-
- if (opt > 0) {
- builder.append("(");
- if (what.length() > 0) {
- builder.append("WHAT: " + what);
- if (where.length() + format.length() > 0)
- builder.append(", ");
- }
-
- if (where.length() > 0) {
- builder.append("WHERE: " + where);
- if (format.length() > 0)
- builder.append(", ");
- }
-
- if (format.length() > 0) {
- builder.append("FORMAT: " + format);
- }
-
- builder.append(")");
- if (info.length() > 0) {
- builder.append("\n# ");
- }
- }
-
- builder.append(info);
-
- return builder.toString();
- }
-
- /**
- * The enum representing textual information to be translated to the user as
- * a key.
- *
- * Note that each key that should be translated MUST be annotated with a
- * {@link Meta} annotation.
- *
- * @author niki
- *
- */
- public enum StringId {
- DUMMY, // <-- TODO : remove
- NULL, // Special usage, no annotations so it is not visible in
- // .properties files
- @Meta(what = "a key to press", where = "action keys", format = "MUST BE 3 chars long", info = "Tab key")
- KEY_TAB, // keys
- @Meta(what = "a key to press", where = "action keys", format = "MUST BE 3 chars long", info = "Enter key")
- KEY_ENTER, //
- @Meta(what = "Action key", where = "All screens except the first (KEY_ACTION_QUIT)", format = "", info = "Go back to previous screen")
- KEY_ACTION_BACK, //
- @Meta(what = "Action key", where = "MainWindow", format = "", info = "Get help text")
- KEY_ACTION_HELP, //
- @Meta(what = "Action key", where = "FileList", format = "", info = "View the selected card")
- KEY_ACTION_VIEW_CARD, //
- @Meta(what = "Action key", where = "ContactList", format = "", info = "View the selected contact")
- KEY_ACTION_VIEW_CONTACT, //
- @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Edit the contact")
- KEY_ACTION_EDIT_CONTACT, //
- @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Edit the contact in RAW mode")
- KEY_ACTION_EDIT_CONTACT_RAW, //
- @Meta(what = "Action key", where = "ContactList", format = "", info = "Save the whole card")
- KEY_ACTION_SAVE_CARD, //
- @Meta(what = "", where = "ContactList", format = "", info = "Delete the selected contact")
- KEY_ACTION_DELETE_CONTACT, //
- @Meta(what = "Action key", where = "ContactList", format = "", info = "Filter the displayed contacts")
- KEY_ACTION_SEARCH, //
- @Meta(what = "", where = "", format = "we could use: ' ', ┃, │...", info = "Field separator")
- DEAULT_FIELD_SEPARATOR, // MainContentList
- @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Invert the photo's colours")
- KEY_ACTION_INVERT, //
- @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Show the photo in 'fullscreen'")
- KEY_ACTION_FULLSCREEN, //
- @Meta(what = "Action key", where = "ContactList, ContactDetails, ContactDetailsRaw", format = "", info = "Switch between the available display formats")
- KEY_ACTION_SWITCH_FORMAT, // multi-usage
- @Meta(what = "Action key", where = "Contact list, Edit Contact", format = "", info = "Add a new contact/field")
- KEY_ACTION_ADD, //
- @Meta(what = "User question: TEXT", where = "Contact list", format = "", info = "New contact")
- ASK_USER_CONTACT_NAME, //
- @Meta(what = "User question: [Y|N]", where = "Contact list", format = "%s = contact name", info = "Delete contact")
- CONFIRM_USER_DELETE_CONTACT, //
- @Meta(what = "Error", where = "Contact list", format = "%s = contact name", info = "cannot delete a contact")
- ERR_CANNOT_DELETE_CONTACT, //
- };
-}
--- /dev/null
+package be.nikiroo.jvcard.resources.bundles;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Bundles;
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+import be.nikiroo.jvcard.resources.Bundles.Target;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+
+/**
+ * All colour information must come from here.
+ *
+ * @author niki
+ *
+ */
+public class ColorBundle extends Bundle<ColorOption> {
+ public ColorBundle() {
+ new Bundles().super(ColorOption.class, Target.colors);
+ }
+
+ @Override
+ protected void writeHeader(Writer writer) throws IOException {
+ ColorOption.writeHeader(writer);
+ }
+
+ @Override
+ protected void writeValue(Writer writer, ColorOption id) throws IOException {
+ writer.write(id.name() + "_FG");
+ writer.write(" = ");
+ if (map.containsKey(id.name() + "_FG"))
+ writer.write(map.getString(id.name() + "_FG").trim());
+
+ writer.write("\n");
+
+ writer.write(id.name() + "_BG");
+ writer.write(" = ");
+ if (map.containsKey(id.name() + "_BG"))
+ writer.write(map.getString(id.name() + "_BG").trim());
+
+ writer.write("\n");
+ }
+}
--- /dev/null
+package be.nikiroo.jvcard.resources.bundles;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Bundles;
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+import be.nikiroo.jvcard.resources.Bundles.Target;
+import be.nikiroo.jvcard.resources.enums.DisplayOption;
+
+/**
+ * This class manages the display configuration of the application.
+ *
+ * @author niki
+ *
+ */
+public class DisplayBundle extends Bundle<DisplayOption> {
+ public DisplayBundle() {
+ new Bundles().super(DisplayOption.class, Target.display);
+ }
+
+ @Override
+ protected void writeHeader(Writer writer) throws IOException {
+ DisplayOption.writeHeader(writer);
+ }
+}
--- /dev/null
+package be.nikiroo.jvcard.resources.bundles;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Bundles;
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+import be.nikiroo.jvcard.resources.Bundles.Target;
+import be.nikiroo.jvcard.resources.enums.RemotingOption;
+
+/**
+ * This class manages the display configuration of the application.
+ *
+ * @author niki
+ *
+ */
+public class RemoteBundle extends Bundle<RemotingOption> {
+ public RemoteBundle() {
+ new Bundles().super(RemotingOption.class, Target.remote);
+ }
+
+ @Override
+ protected void writeHeader(Writer writer) throws IOException {
+ RemotingOption.writeHeader(writer);
+ }
+}
--- /dev/null
+package be.nikiroo.jvcard.resources.bundles;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Locale;
+
+import be.nikiroo.jvcard.resources.Bundles;
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+import be.nikiroo.jvcard.resources.Bundles.Target;
+import be.nikiroo.jvcard.resources.enums.StringId;
+
+/**
+ * This class manages the translation of {@link TransBundle.StringId}s into
+ * user-understandable text.
+ *
+ * @author niki
+ *
+ */
+public class TransBundle extends Bundle<StringId> {
+ private boolean utf = true;
+ private Locale locale;
+
+ /**
+ * Create a translation service with the default language.
+ */
+ public TransBundle() {
+ new Bundles().super(StringId.class, Target.resources);
+ setLanguage(null);
+ }
+
+ /**
+ * Create a translation service for the given language. (Will fall back to
+ * the default one i not found.)
+ *
+ * @param language
+ * the language to use
+ */
+ public TransBundle(String language) {
+ new Bundles().super(StringId.class, Target.resources);
+
+ setLanguage(language);
+ }
+
+ @Override
+ public String getString(StringId id) {
+ return getString(id, (Object[]) null);
+ }
+
+ /**
+ * Translate the given {@link StringId} into user text.
+ *
+ * @param stringId
+ * the ID to translate
+ * @param values
+ * the values to insert instead of the place holders in the
+ * translation
+ *
+ * @return the translated text with the given value where required
+ */
+ public String getString(StringId stringId, Object... values) {
+ StringId id = stringId;
+ String result = "";
+
+ if (!isUnicode()) {
+ try {
+ id = StringId.valueOf(stringId.name() + "_NOUTF");
+ } catch (IllegalArgumentException iae) {
+ // no special _NOUTF version found
+ }
+ }
+
+ if (id == StringId.NULL) {
+ result = "";
+ } else if (id == StringId.DUMMY) {
+ result = "[dummy]";
+ } else if (map.containsKey(id.name())) {
+ result = map.getString(id.name());
+ } else {
+ result = id.toString();
+ }
+
+ if (values != null && values.length > 0)
+ return String.format(locale, result, (Object[]) values);
+ else
+ return result;
+ }
+
+ /**
+ * Check if unicode characters should be used.
+ *
+ * @return TRUE to allow unicode
+ */
+ public boolean isUnicode() {
+ return utf;
+ }
+
+ /**
+ * Allow or disallow unicode characters in the program.
+ *
+ * @param utf
+ * TRUE to allow unuciode, FALSE to only allow ASCII characters
+ */
+ public void setUnicode(boolean utf) {
+ this.utf = utf;
+ }
+
+ @Override
+ protected File getUpdateFile(String path) {
+ String code = locale.toString();
+ File file = null;
+ if (code.length() > 0) {
+ file = new File(path, name.name() + "_" + code + ".properties");
+ } else {
+ // Default properties file:
+ file = new File(path, name.name() + ".properties");
+ }
+
+ return file;
+ }
+
+ @Override
+ protected void writeHeader(Writer writer) throws IOException {
+ String code = locale.toString();
+ String name = locale.getDisplayCountry(locale);
+
+ if (name.length() == 0)
+ name = locale.getDisplayLanguage(locale);
+ if (name.length() == 0)
+ name = "default";
+
+ if (code.length() > 0) {
+ name = name + " (" + code + ")";
+ }
+
+ StringId.writeHeader(writer, name);
+ }
+
+ /**
+ * Initialise the translation mappings for the given language.
+ *
+ * @param language
+ * the language to initialise, in the form "en-GB" or "fr" for
+ * instance
+ */
+ private void setLanguage(String language) {
+ locale = getLocaleFor(language);
+ map = getBundle(Target.resources, locale);
+ }
+
+ /**
+ * Return the {@link Locale} representing the given language.
+ *
+ * @param language
+ * the language to initialise, in the form "en-GB" or "fr" for
+ * instance
+ *
+ * @return the corresponding {@link Locale} or the default {@link Locale} if
+ * it is not known
+ */
+ static private Locale getLocaleFor(String language) {
+ Locale locale;
+
+ if (language == null) {
+ locale = Locale.getDefault();
+ } else {
+ language = language.replaceAll("_", "-");
+ String lang = language;
+ String country = null;
+ if (language.contains("-")) {
+ lang = language.split("-")[0];
+ country = language.split("-")[1];
+ }
+
+ if (country != null)
+ locale = new Locale(lang, country);
+ else
+ locale = new Locale(lang);
+ }
+
+ return locale;
+ }
+}
-# application colours
+# Application colours
#
# Note that you can define a colour in one of those 3 ways:
# - WHITE: one of the ANSI colour names, in upper case
# - 255: one of the 256 indexed colours of the terminal (the 16 first colours are theme-based)
#
# ...and thus either for xxx_FG (foreground colour) or xxx_BG (background colour)
+#
+# (FORMAT: colour)
+DEFAULT_FG = BLACK
+DEFAULT_BG = WHITE
+# (FORMAT: colour)
TITLE_MAIN_FG = WHITE
TITLE_MAIN_BG = BLUE
+# (FORMAT: colour)
TITLE_VARIABLE_FG = GREEN
TITLE_VARIABLE_BG = BLUE
+# (FORMAT: colour)
TITLE_COUNT_FG = RED
TITLE_COUNT_BG = BLUE
-
-DEFAULT_FG = BLACK
-DEFAULT_BG = WHITE
-
+# (FORMAT: colour)
ACTION_KEY_FG = WHITE
ACTION_KEY_BG = RED
+# (FORMAT: colour)
ACTION_DESC_FG = WHITE
ACTION_DESC_BG = BLUE
-CONTACT_LINE_FG = WHITE
-CONTACT_LINE_BG = BLACK
-CONTACT_LINE_SELECTED_FG = WHITE
-CONTACT_LINE_SELECTED_BG = BLUE
-CONTACT_LINE_SEPARATOR_FG = RED
-CONTACT_LINE_SEPARATOR_BG = BLACK
-CONTACT_LINE_SEPARATOR_SELECTED_FG = RED
-CONTACT_LINE_SEPARATOR_SELECTED_BG = BLUE
+# (FORMAT: colour)
LINE_MESSAGE_FG = BLUE
LINE_MESSAGE_BG = WHITE
+# (FORMAT: colour)
LINE_MESSAGE_ERR_FG = RED
LINE_MESSAGE_ERR_BG = WHITE
+# (FORMAT: colour)
LINE_MESSAGE_QUESTION_FG = BLUE
LINE_MESSAGE_QUESTION_BG = WHITE
+# (FORMAT: colour)
LINE_MESSAGE_ANS_FG = BLUE
LINE_MESSAGE_ANS_BG = BLACK
+# (FORMAT: colour)
+CONTACT_LINE_FG = WHITE
+CONTACT_LINE_BG = BLACK
+# (FORMAT: colour)
+CONTACT_LINE_SEPARATOR_FG = RED
+CONTACT_LINE_SEPARATOR_BG = BLACK
+# (FORMAT: colour)
+CONTACT_LINE_SELECTED_FG = WHITE
+CONTACT_LINE_SELECTED_BG = BLUE
+# (FORMAT: colour)
+CONTACT_LINE_SEPARATOR_SELECTED_FG = RED
+CONTACT_LINE_SEPARATOR_SELECTED_BG = BLUE
+# (FORMAT: colour)
+CONTACT_LINE_DIRTY_FG = BLACK
+CONTACT_LINE_DIRTY_BG = WHITE
+# (FORMAT: colour)
+CONTACT_LINE_DIRTY_SELECTED_FG = BLACK
+CONTACT_LINE_DIRTY_SELECTED_BG = WHITE
+# (FORMAT: colour)
VIEW_CONTACT_NAME_FG = BLACK
VIEW_CONTACT_NAME_BG = WHITE
+# (FORMAT: colour)
VIEW_CONTACT_NORMAL_FG = WHITE
VIEW_CONTACT_NORMAL_BG = BLACK
+# (FORMAT: colour)
VIEW_CONTACT_HIGHLIGHT_FG = RED
VIEW_CONTACT_HIGHLIGHT_BG = BLACK
+# (FORMAT: colour)
VIEW_CONTACT_NOTES_TITLE_FG = BLACK
VIEW_CONTACT_NOTES_TITLE_BG = WHITE
-CONTACT_LINE_DIRTY_SELECTED_FG = BLACK
-CONTACT_LINE_DIRTY_SELECTED_BG = WHITE
-CONTACT_LINE_DIRTY_FG = BLACK
-CONTACT_LINE_DIRTY_BG = WHITE
-
-# display options configuration
-
-# The contact list format is basically a list of VCF field names
+# Display options configuration
+#
+# The Contact List Format (CLF) is basically a list of VCF field names
# separated by a pipe and optionally parametrised.
# The parameters allows you to:
# - @x: (the 'x' is the letter 'x') show only a present/not present info
#
# In case of lists or multiple-fields values, you can select a specific
# list or field with:
-# - FIELD@(0): select the first value in a list</li>
-# - FIELD@[1]: select the second field in a multiple-fields value</li>
+# - FIELD@(0): select the first value in a list
+# - FIELD@[1]: select the second field in a multiple-fields value
#
# You can also add a fixed text if it starts with a simple-quote (').
#
# Example: "'Contact: |N@10|FN@20|NICK@+|PHOTO@x"
#
-# You can cycle through them if you have more than one
-# (in this case, separate them with a comma (',')
-CONTACT_LIST_FORMAT = NICKNAME@10|FN@+|EMAIL@30|PHOTO@x,N@[0]@20|N@[1]@+|EMAIL@40
-
-# The list of details to show in View Contact mode:
+#
+# The Contact Details Info Format (CDIF):
# - Each detail (separated by a pipe "|" character) is visible on its own line
# - It is made up of two parts: the label and the linked VCF field (optional),
# separated by an equal "=", sharp "#", plus "+" or asterisk "*" sign
# Example:
# CONTACT_DETAILS_INFO = Phone:=TEL|eMail:=EMAIL
#
-# This will print two lines in View mode:
+# This will print two lines:
# Phone: +32 888 88 88 88
# eMail: nobody@nowhere.com
-CONTACT_DETAILS_INFO = Phone:=TEL|eMail:=EMAIL
+#
+
+# (FORMAT: coma-separated list of CLF)
+# The format of each line in the contact list
+CONTACT_LIST_FORMAT = NICKNAME@10|FN@+|EMAIL@30|PHOTO@x,N@[0]@20|N@[1]@+|EMAIL@40
+# (FORMAT: CDIF)
+# The list of details to show in View Contact mode
+CONTACT_DETAILS_INFO = Phone:=TEL|eMail:=EMAIL
+# (FORMAT: Integer or nothing for auto)
# The size of the details' labels
CONTACT_DETAILS_LABEL_WIDTH = 12
-
+# (FORMAT: CLF)
+# The default value of FN if it is not present
CONTACT_DETAILS_DEFAULT_FN = N@[1]|' |N@[0]
-
+# (FORMAT: TRUE or FALSE)
+# TRUE to force all FNs to be recreated from CONTACT_DETAILS_DEFAULT_FN
CONTACT_DETAILS_SHOW_COMPUTED_FN = true
--- /dev/null
+package be.nikiroo.jvcard.resources.enums;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Meta;
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+
+/**
+ * Represent an element that can be coloured (foreground/background colours).
+ *
+ * @author niki
+ *
+ */
+public enum ColorOption {
+ @Meta(what = "", where = "", format = "colour", info = "")
+ DEFAULT, //
+
+ @Meta(what = "", where = "", format = "colour", info = "")
+ TITLE_MAIN, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ TITLE_VARIABLE, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ TITLE_COUNT, //
+
+ @Meta(what = "", where = "", format = "colour", info = "")
+ ACTION_KEY, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ ACTION_DESC, //
+
+ @Meta(what = "", where = "", format = "colour", info = "")
+ LINE_MESSAGE, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ LINE_MESSAGE_ERR, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ LINE_MESSAGE_QUESTION, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ LINE_MESSAGE_ANS, //
+
+ @Meta(what = "", where = "", format = "colour", info = "")
+ CONTACT_LINE, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ CONTACT_LINE_SEPARATOR, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ CONTACT_LINE_SELECTED, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ CONTACT_LINE_SEPARATOR_SELECTED, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ CONTACT_LINE_DIRTY, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ CONTACT_LINE_DIRTY_SELECTED, //
+
+ @Meta(what = "", where = "", format = "colour", info = "")
+ VIEW_CONTACT_NAME, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ VIEW_CONTACT_NORMAL, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ VIEW_CONTACT_HIGHLIGHT, //
+ @Meta(what = "", where = "", format = "colour", info = "")
+ VIEW_CONTACT_NOTES_TITLE, //
+
+ ;
+
+ /**
+ * Write the header found in the configuration <tt>.properties</tt> file of
+ * this {@link Bundle}.
+ *
+ * @param writer
+ * the {@link Writer} to write the header in
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ static public void writeHeader(Writer writer) throws IOException {
+ writer.write("# Application colours\n");
+ writer.write("# \n");
+ writer.write("# Note that you can define a colour in one of those 3 ways:\n");
+ writer.write("# - WHITE: one of the ANSI colour names, in upper case\n");
+ writer.write("# - @RRGGBB: a RGB code we will try to match using one of the 256 Terminal colours\n");
+ writer.write("# - #RRGGBB: an exact RGB colour (please make sure your terminal supports this)\n");
+ writer.write("# - 255: one of the 256 indexed colours of the terminal (the 16 first colours are theme-based) \n");
+ writer.write("# \n");
+ writer.write("# ...and thus either for xxx_FG (foreground colour) or xxx_BG (background colour)\n");
+ writer.write("# \n");
+ }
+}
\ No newline at end of file
--- /dev/null
+package be.nikiroo.jvcard.resources.enums;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+import be.nikiroo.jvcard.resources.Meta;
+
+public enum DisplayOption {
+ @Meta(what = "", where = "", format = "coma-separated list of CLF", info = "The format of each line in the contact list")
+ CONTACT_LIST_FORMAT, //
+ @Meta(what = "", where = "", format = "CDIF", info = "The list of details to show in View Contact mode")
+ CONTACT_DETAILS_INFO, //
+ @Meta(what = "", where = "", format = "Integer or nothing for auto", info = "The size of the details' labels")
+ CONTACT_DETAILS_LABEL_WIDTH, //
+ @Meta(what = "", where = "", format = "CLF", info = "The default value of FN if it is not present")
+ CONTACT_DETAILS_DEFAULT_FN, //
+ @Meta(what = "", where = "", format = "TRUE or FALSE", info = "TRUE to force all FNs to be recreated from CONTACT_DETAILS_DEFAULT_FN")
+ CONTACT_DETAILS_SHOW_COMPUTED_FN, //
+
+ ;
+
+ /**
+ * Write the header found in the configuration <tt>.properties</tt> file of
+ * this {@link Bundle}.
+ *
+ * @param writer
+ * the {@link Writer} to write the header in
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ static public void writeHeader(Writer writer) throws IOException {
+ writer.write("# Display options configuration\n");
+ writer.write("#\n");
+ writer.write("# The Contact List Format (CLF) is basically a list of VCF field names\n");
+ writer.write("# separated by a pipe and optionally parametrised.\n");
+ writer.write("# The parameters allows you to:\n");
+ writer.write("# - @x: (the 'x' is the letter 'x') show only a present/not present info\n");
+ writer.write("# - @n: limit the size to a fixed value 'n'\n");
+ writer.write("# - @+: expand the size of this field as much as possible\n");
+ writer.write("#\n");
+ writer.write("# In case of lists or multiple-fields values, you can select a specific\n");
+ writer.write("# list or field with:\n");
+ writer.write("# - FIELD@(0): select the first value in a list\n");
+ writer.write("# - FIELD@[1]: select the second field in a multiple-fields value\n");
+ writer.write("#\n");
+ writer.write("# You can also add a fixed text if it starts with a simple-quote (').\n");
+ writer.write("#\n");
+ writer.write("# Example: \"'Contact: |N@10|FN@20|NICK@+|PHOTO@x\"\n");
+ writer.write("# \n");
+ writer.write("# \n");
+ writer.write("# The Contact Details Info Format (CDIF):\n");
+ writer.write("# - Each detail (separated by a pipe \"|\" character) is visible on its own line\n");
+ writer.write("# - It is made up of two parts: the label and the linked VCF field (optional),\n");
+ writer.write("# separated by an equal \"=\", sharp \"#\", plus \"+\" or asterisk \"*\" sign\n");
+ writer.write("# - \"=FIELD\" will take the preferred value for this field\n");
+ writer.write("# - \"+FIELD\" will take the preferred value for this field and highlight it\n");
+ writer.write("# - \"#FIELD\" will take all the values with this field's name\n");
+ writer.write("# - \"*FIELD\" will take all the values with this field's name, highlighting the preferred one\n");
+ writer.write("#\n");
+ writer.write("# Example:\n");
+ writer.write("# CONTACT_DETAILS_INFO = Phone:=TEL|eMail:=EMAIL\n");
+ writer.write("#\n");
+ writer.write("# This will print two lines:\n");
+ writer.write("# Phone: +32 888 88 88 88\n");
+ writer.write("# eMail: nobody@nowhere.com\n");
+ writer.write("#\n");
+ }
+}
--- /dev/null
+package be.nikiroo.jvcard.resources.enums;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Meta;
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+
+public enum RemotingOption {
+ @Meta(what = "", where = "Server", format = "directory", info = "when starting as a jVCard remote server, where to look for data")
+ SERVER_DATA_PATH, //
+
+ @Meta(what = "", where = "Client", format = "directory", info = "when loading \"jvcard://\" links, where to save cache files")
+ CLIENT_CACHE_DIR, //
+ @Meta(what = "", where = "Client", format = "TRUE or FALSE", info = "Automatically synchronise remote cards")
+ CLIENT_AUTO_SYNC, //
+
+ ;
+
+ /**
+ * Write the header found in the configuration <tt>.properties</tt> file of
+ * this {@link Bundle}.
+ *
+ * @param writer
+ * the {@link Writer} to write the header in
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ static public void writeHeader(Writer writer) throws IOException {
+ writer.write("# Remote configuration (client and server)\n");
+ writer.write("#\n");
+ }
+}
--- /dev/null
+package be.nikiroo.jvcard.resources.enums;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import be.nikiroo.jvcard.resources.Bundles.Bundle;
+import be.nikiroo.jvcard.resources.Meta;
+
+/**
+ * The enum representing textual information to be translated to the user as a
+ * key.
+ *
+ * Note that each key that should be translated MUST be annotated with a
+ * {@link Meta} annotation.
+ *
+ * @author niki
+ *
+ */
+public enum StringId {
+ DUMMY, // <-- TODO : remove
+ NULL, // Special usage, no annotations so it is not visible in
+ // .properties files
+ @Meta(what = "a key to press", where = "action keys", format = "MUST BE 3 chars long", info = "Tab key")
+ KEY_TAB, // keys
+ @Meta(what = "a key to press", where = "action keys", format = "MUST BE 3 chars long", info = "Enter key")
+ KEY_ENTER, //
+ @Meta(what = "Action key", where = "All screens except the first (KEY_ACTION_QUIT)", format = "", info = "Go back to previous screen")
+ KEY_ACTION_BACK, //
+ @Meta(what = "Action key", where = "MainWindow", format = "", info = "Get help text")
+ KEY_ACTION_HELP, //
+ @Meta(what = "Action key", where = "FileList", format = "", info = "View the selected card")
+ KEY_ACTION_VIEW_CARD, //
+ @Meta(what = "Action key", where = "ContactList", format = "", info = "View the selected contact")
+ KEY_ACTION_VIEW_CONTACT, //
+ @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Edit the contact")
+ KEY_ACTION_EDIT_CONTACT, //
+ @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Edit the contact in RAW mode")
+ KEY_ACTION_EDIT_CONTACT_RAW, //
+ @Meta(what = "Action key", where = "ContactList", format = "", info = "Save the whole card")
+ KEY_ACTION_SAVE_CARD, //
+ @Meta(what = "", where = "ContactList", format = "", info = "Delete the selected contact")
+ KEY_ACTION_DELETE_CONTACT, //
+ @Meta(what = "Action key", where = "ContactList", format = "", info = "Filter the displayed contacts")
+ KEY_ACTION_SEARCH, //
+ @Meta(what = "", where = "", format = "we could use: ' ', ┃, │...", info = "Field separator")
+ DEAULT_FIELD_SEPARATOR, // MainContentList
+ @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Invert the photo's colours")
+ KEY_ACTION_INVERT, //
+ @Meta(what = "Action key", where = "ContactDetails", format = "", info = "Show the photo in 'fullscreen'")
+ KEY_ACTION_FULLSCREEN, //
+ @Meta(what = "Action key", where = "ContactList, ContactDetails, ContactDetailsRaw", format = "", info = "Switch between the available display formats")
+ KEY_ACTION_SWITCH_FORMAT, // multi-usage
+ @Meta(what = "Action key", where = "Contact list, Edit Contact", format = "", info = "Add a new contact/field")
+ KEY_ACTION_ADD, //
+ @Meta(what = "User question: TEXT", where = "Contact list", format = "", info = "New contact")
+ ASK_USER_CONTACT_NAME, //
+ @Meta(what = "User question: [Y|N]", where = "Contact list", format = "%s = contact name", info = "Delete contact")
+ CONFIRM_USER_DELETE_CONTACT, //
+ @Meta(what = "Error", where = "Contact list", format = "%s = contact name", info = "cannot delete a contact")
+ ERR_CANNOT_DELETE_CONTACT, //
+
+ ;
+
+ /**
+ * Write the header found in the configuration <tt>.properties</tt> file of
+ * this {@link Bundle}.
+ *
+ * @param writer
+ * the {@link Writer} to write the header in
+ * @param name
+ * the file name
+ *
+ * @throws IOException
+ * in case of IO error
+ */
+ static public void writeHeader(Writer writer, String name)
+ throws IOException {
+ writer.write("# " + name + " translation file (UTF-8)\n");
+ writer.write("# \n");
+ writer.write("# Note that any key can be doubled with a _NOUTF suffix\n");
+ writer.write("# to use when the flag --noutf is passed\n");
+ writer.write("# \n");
+ writer.write("# Also, the comments always refer to the key below them.\n");
+ writer.write("# \n");
+ writer.write("\n");
+ }
+};
-# remote configuration (client and server)
-#
+# Remote configuration (client and server)
+#
-###############
-### Server: ###
-###############
-# when starting as a jVCard remote server, where to look for data:
+# (WHERE: Server, FORMAT: directory)
+# when starting as a jVCard remote server, where to look for data
SERVER_DATA_PATH = /tmp/server/
-
-###############
-### Client: ###
-###############
-
+# (WHERE: Client, FORMAT: directory)
# when loading "jvcard://" links, where to save cache files
-CLIENT_CACHE_DIR = /tmp/client/
-
-# "true" to automatically synchronise remote cards
-CLIENT_AUTO_SYNC = true
+CLIENT_CACHE_DIR = /tmp/client/
+# (WHERE: Client, FORMAT: TRUE or FALSE)
+# Automatically synchronise remote cards
+CLIENT_AUTO_SYNC = true
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.Data;
import be.nikiroo.jvcard.launcher.Main;
-import be.nikiroo.jvcard.resources.Trans.StringId;
+import be.nikiroo.jvcard.resources.enums.StringId;
import com.googlecode.lanterna.input.KeyStroke;
import com.googlecode.lanterna.input.KeyType;
import be.nikiroo.jvcard.launcher.Main;
import be.nikiroo.jvcard.resources.StringUtils;
-import be.nikiroo.jvcard.resources.Trans.StringId;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
import be.nikiroo.jvcard.tui.KeyAction.Mode;
-import be.nikiroo.jvcard.tui.UiColors.Element;
import be.nikiroo.jvcard.tui.panes.ContactDetails;
import be.nikiroo.jvcard.tui.panes.ContactDetailsRaw;
import be.nikiroo.jvcard.tui.panes.ContactList;
if (mess != null || messagePanel.getChildCount() > 0) {
messagePanel.removeAllComponents();
if (mess != null) {
- Element element = (error ? UiColors.Element.LINE_MESSAGE_ERR
- : UiColors.Element.LINE_MESSAGE);
- Label lbl = element.createLabel(" " + mess + " ");
+ ColorOption element = (error ? ColorOption.LINE_MESSAGE_ERR
+ : ColorOption.LINE_MESSAGE);
+ Label lbl = UiColors.createLabel(element, " " + mess + " ");
messagePanel.addComponent(lbl, LinearLayout
.createLayoutData(LinearLayout.Alignment.Center));
}
llayout.setSpacing(0);
hpanel.setLayoutManager(llayout);
- Label lbl = UiColors.Element.LINE_MESSAGE_QUESTION.createLabel(" "
+ Label lbl = UiColors.createLabel(ColorOption.LINE_MESSAGE_QUESTION, " "
+ question + " ");
text = new TextBox(new TerminalSize(getSize().getColumns()
- lbl.getSize().getColumns(), 1));
super.setTitle(prefix);
Label lblPrefix = new Label(prefix);
- UiColors.Element.TITLE_MAIN.themeLabel(lblPrefix);
+ UiColors.themeLabel(ColorOption.TITLE_MAIN, lblPrefix);
Label lblTitle = null;
if (title.length() > 0) {
lblTitle = new Label(title);
- UiColors.Element.TITLE_VARIABLE.themeLabel(lblTitle);
+ UiColors.themeLabel(ColorOption.TITLE_VARIABLE, lblTitle);
}
Label lblCount = null;
if (countStr != null) {
lblCount = new Label(countStr);
- UiColors.Element.TITLE_COUNT.themeLabel(lblCount);
+ UiColors.themeLabel(ColorOption.TITLE_COUNT, lblCount);
}
titlePanel.removeAllComponents();
layout.setSpacing(0);
kPane.setLayoutManager(layout);
- kPane.addComponent(UiColors.Element.ACTION_KEY
- .createLabel(keyTrans));
- kPane.addComponent(UiColors.Element.ACTION_DESC.createLabel(trans));
+ kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_KEY,
+ keyTrans));
+ kPane.addComponent(UiColors.createLabel(ColorOption.ACTION_DESC, trans));
actionPanel.addComponent(kPane);
}
}
if (width > 0) {
- actionPanel.addComponent(UiColors.Element.ACTION_DESC
- .createLabel(StringUtils.padString("", width)));
+ actionPanel.addComponent(UiColors.createLabel(ColorOption.ACTION_DESC,
+ StringUtils.padString("", width)));
}
}
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import be.nikiroo.jvcard.resources.Bundles;
+import be.nikiroo.jvcard.resources.bundles.ColorBundle;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.gui2.Label;
* @author niki
*
*/
-public class UiColors {
+public class UiColors extends ColorBundle {
static private Object lock = new Object();
static private UiColors instance = null;
- private ResourceBundle bundle = null;
private Map<String, TextColor> colorMap = null;
private UiColors() {
+ super();
colorMap = new HashMap<String, TextColor>();
- bundle = Bundles.getBundle("colors");
}
/**
- * Represent an element that can be coloured (foreground/background
- * colours).
- *
- * @author niki
- *
- */
- public enum Element {
- DEFAULT, //
- TITLE_MAIN, TITLE_VARIABLE, TITLE_COUNT, //
- ACTION_KEY, ACTION_DESC, //
- LINE_MESSAGE, LINE_MESSAGE_ERR, LINE_MESSAGE_QUESTION, LINE_MESSAGE_ANS, //
- CONTACT_LINE, CONTACT_LINE_SEPARATOR, CONTACT_LINE_SELECTED, CONTACT_LINE_SEPARATOR_SELECTED, CONTACT_LINE_DIRTY, CONTACT_LINE_DIRTY_SELECTED, //
- VIEW_CONTACT_NAME, VIEW_CONTACT_NORMAL, VIEW_CONTACT_HIGHLIGHT, VIEW_CONTACT_NOTES_TITLE, //
- ;
-
- /**
- * Get the foreground colour of this element.
- *
- * @return the colour
- */
- public TextColor getForegroundColor() {
- return UiColors.getInstance().getForegroundColor(this);
- }
-
- /**
- * Get the background colour of this element.
- *
- * @return the colour
- */
- public TextColor getBackgroundColor() {
- return UiColors.getInstance().getBackgroundColor(this);
- }
-
- /**
- * Create a new {@link Label} with the colours of this {@link Element}.
- *
- * @param text
- * the text of the {@link Label}
- *
- * @return the new {@link Label}
- */
- public Label createLabel(String text) {
- return UiColors.getInstance().createLabel(this, text);
- }
-
- /**
- * Theme a {@link Label} with the colours of this {@link Element}.
- *
- * @param lbl
- * the {@link Label}
- */
- public void themeLabel(Label lbl) {
- UiColors.getInstance().themeLabel(this, lbl);
- }
- }
-
- /**
- * Create a new {@link Label} with the colours of the given {@link Element}.
+ * Create a new {@link Label} with the colours of the given {@link ColorOption}.
*
* @param el
- * the {@link Element}
+ * the {@link ColorOption}
* @param text
* the text of the {@link Label}
*
* @return the new {@link Label}
*/
- private Label createLabel(Element el, String text) {
+ static public Label createLabel(ColorOption el, String text) {
if (text == null)
text = "";
}
/**
- * Theme a {@link Label} with the colours of the given {@link Element}.
+ * Theme a {@link Label} with the colours of the given {@link ColorOption}.
*
* @param el
- * the {@link Element}
+ * the {@link ColorOption}
* @param lbl
* the {@link Label}
*/
- private void themeLabel(Element el, Label lbl) {
- lbl.setForegroundColor(el.getForegroundColor());
- lbl.setBackgroundColor(el.getBackgroundColor());
+ static public void themeLabel(ColorOption el, Label lbl) {
+ lbl.setForegroundColor(getForegroundColor(el));
+ lbl.setBackgroundColor(getBackgroundColor(el));
}
/**
* Return the background colour of the given element.
*
* @param el
- * the {@link Element}
+ * the {@link ColorOption}
*
* @return its background colour
*/
- private TextColor getBackgroundColor(Element el) {
- if (!colorMap.containsKey(el.name() + "_BG")) {
+ static public TextColor getBackgroundColor(ColorOption el) {
+ if (!getInstance().colorMap.containsKey(el.name() + "_BG")) {
String value = null;
try {
- value = bundle.getString(el.name() + "_BG");
+ value = getInstance().map.getString(el.name() + "_BG");
} catch (MissingResourceException mre) {
value = null;
}
- colorMap.put(el.name() + "_BG",
+ getInstance().colorMap.put(el.name() + "_BG",
convertToColor(value, TextColor.ANSI.BLACK));
}
- return colorMap.get(el.name() + "_BG");
+ return getInstance().colorMap.get(el.name() + "_BG");
}
/**
* Return the foreground colour of the given element.
*
* @param el
- * the {@link Element}
+ * the {@link ColorOption}
*
* @return its foreground colour
*/
- private TextColor getForegroundColor(Element el) {
- if (!colorMap.containsKey(el.name() + "_FG")) {
+ static public TextColor getForegroundColor(ColorOption el) {
+ if (!getInstance().colorMap.containsKey(el.name() + "_FG")) {
String value = null;
try {
- value = bundle.getString(el.name() + "_FG");
+ value = getInstance().map.getString(el.name() + "_FG");
} catch (MissingResourceException mre) {
value = null;
}
- colorMap.put(el.name() + "_FG",
+ getInstance().colorMap.put(el.name() + "_FG",
convertToColor(value, TextColor.ANSI.WHITE));
}
- return colorMap.get(el.name() + "_FG");
+ return getInstance().colorMap.get(el.name() + "_FG");
}
/**
*
* @return the (unique) instance
*/
- static public UiColors getInstance() {
+ static private UiColors getInstance() {
synchronized (lock) {
if (instance == null)
instance = new UiColors();
return defaultColor;
}
-
}
import java.awt.Image;
import java.util.LinkedList;
import java.util.List;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.Data;
import be.nikiroo.jvcard.TypeInfo;
-import be.nikiroo.jvcard.resources.Bundles;
import be.nikiroo.jvcard.resources.StringUtils;
-import be.nikiroo.jvcard.resources.Trans;
+import be.nikiroo.jvcard.resources.bundles.DisplayBundle;
+import be.nikiroo.jvcard.resources.enums.DisplayOption;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
import be.nikiroo.jvcard.tui.ImageTextControl;
import be.nikiroo.jvcard.tui.KeyAction;
import be.nikiroo.jvcard.tui.KeyAction.DataType;
// from .properties file:
private int labelSize = -1;
private String infoFormat = "";
+
//
public ContactDetails(Contact contact) {
// Get the .properties info:
- ResourceBundle map = Bundles.getBundle("display");
-
- try {
- labelSize = Integer.parseInt(map
- .getString("CONTACT_DETAILS_LABEL_WIDTH"));
-
- } catch (NumberFormatException e) {
- e.printStackTrace();
- labelSize = -1;
- } catch (MissingResourceException e) {
- labelSize = -1;
- }
-
- try {
- infoFormat = map.getString("CONTACT_DETAILS_INFO");
- } catch (MissingResourceException e) {
- e.printStackTrace();
- }
+ DisplayBundle map = new DisplayBundle();
+ labelSize = map.getInteger(DisplayOption.CONTACT_DETAILS_LABEL_WIDTH,
+ -1);
+ infoFormat = map.getString(DisplayOption.CONTACT_DETAILS_INFO);
//
BorderLayout blayout = new BorderLayout();
Panel notePanel = new Panel();
notePanel.setLayoutManager(new LinearLayout(Direction.HORIZONTAL));
- notePanel.addComponent(UiColors.Element.VIEW_CONTACT_NOTES_TITLE
- .createLabel("Notes:"));
- note = UiColors.Element.VIEW_CONTACT_NORMAL.createLabel("");
+ notePanel.addComponent(UiColors.createLabel(
+ ColorOption.VIEW_CONTACT_NOTES_TITLE, "Notes:"));
+ note = UiColors.createLabel(ColorOption.VIEW_CONTACT_NORMAL, "");
notePanel.addComponent(note);
setContact(contact);
infoPanel.removeAllComponents();
String name = contact.getPreferredDataValue("FN");
- infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NAME
- .createLabel(name));
- infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
- .createLabel(""));
+ infoPanel.addComponent(UiColors.createLabel(
+ ColorOption.VIEW_CONTACT_NAME, name));
+ infoPanel.addComponent(UiColors.createLabel(
+ ColorOption.VIEW_CONTACT_NORMAL, ""));
// List of infos:
String[] infos = infoFormat.split("\\|");
all = true;
if (all || hl || info.contains("=")) {
- UiColors.Element el = hl ? UiColors.Element.VIEW_CONTACT_HIGHLIGHT
- : UiColors.Element.VIEW_CONTACT_NORMAL;
+ ColorOption el = hl ? ColorOption.VIEW_CONTACT_HIGHLIGHT
+ : ColorOption.VIEW_CONTACT_NORMAL;
int index = info.indexOf('=');
if (index < 0)
if (all) {
for (Data data : contact.getData(field)) {
if (data.isPreferred()) {
- infoPanel.addComponent(el
- .createLabel(StringUtils.padString(
- label, labelSize)
+ infoPanel.addComponent(UiColors.createLabel(el,
+ StringUtils.padString(label, labelSize)
+ data.toString()));
} else {
- infoPanel
- .addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
- .createLabel(StringUtils
- .padString(label,
- labelSize)
- + data.toString()));
+ infoPanel.addComponent(UiColors.createLabel(
+ ColorOption.VIEW_CONTACT_NORMAL,
+ StringUtils.padString(label, labelSize)
+ + data.toString()));
}
}
} else {
String val = contact.getPreferredDataValue(field);
if (val == null)
val = "";
- infoPanel.addComponent(el.createLabel(StringUtils
- .padString(label, labelSize) + val));
+ infoPanel.addComponent(UiColors.createLabel(el,
+ StringUtils.padString(label, labelSize) + val));
}
} else {
String label = info;
- infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
- .createLabel(StringUtils
- .padString(label, labelSize)));
+ infoPanel.addComponent(UiColors.createLabel(
+ ColorOption.VIEW_CONTACT_NORMAL,
+ StringUtils.padString(label, labelSize)));
}
}
// end of list
- infoPanel.addComponent(UiColors.Element.VIEW_CONTACT_NORMAL
- .createLabel(""));
+ infoPanel.addComponent(UiColors.createLabel(
+ ColorOption.VIEW_CONTACT_NORMAL, ""));
String notes = contact.getPreferredDataValue("NOTE");
if (notes == null)
List<KeyAction> actions = new LinkedList<KeyAction>();
actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
- Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
+ StringId.KEY_ACTION_SWITCH_FORMAT) {
@Override
public boolean onAction() {
if (txtImage != null) {
return false;
}
});
- actions.add(new KeyAction(Mode.NONE, 'i',
- Trans.StringId.KEY_ACTION_INVERT) {
+ actions.add(new KeyAction(Mode.NONE, 'i', StringId.KEY_ACTION_INVERT) {
@Override
public boolean onAction() {
if (txtImage != null) {
}
});
actions.add(new KeyAction(Mode.NONE, 'f',
- Trans.StringId.KEY_ACTION_FULLSCREEN) {
+ StringId.KEY_ACTION_FULLSCREEN) {
@Override
public boolean onAction() {
fullscreenImage = !fullscreenImage;
});
// TODO: add "normal" edit
actions.add(new KeyAction(Mode.CONTACT_DETAILS_RAW, 'r',
- Trans.StringId.KEY_ACTION_EDIT_CONTACT_RAW) {
+ StringId.KEY_ACTION_EDIT_CONTACT_RAW) {
@Override
public Object getObject() {
return contact;
import be.nikiroo.jvcard.TypeInfo;
import be.nikiroo.jvcard.launcher.Main;
import be.nikiroo.jvcard.resources.StringUtils;
-import be.nikiroo.jvcard.resources.Trans;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
import be.nikiroo.jvcard.tui.KeyAction;
import be.nikiroo.jvcard.tui.KeyAction.DataType;
import be.nikiroo.jvcard.tui.KeyAction.Mode;
-import be.nikiroo.jvcard.tui.UiColors.Element;
import com.googlecode.lanterna.input.KeyType;
// TODO: add, remove
actions.add(new KeyAction(Mode.ASK_USER, KeyType.Enter,
- Trans.StringId.DUMMY) {
+ StringId.DUMMY) {
@Override
public Object getObject() {
return getSelectedData();
return "Cannot modify value";
}
});
- actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd', Trans.StringId.DUMMY) {
+ actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd', StringId.DUMMY) {
@Override
public Object getObject() {
return getSelectedData();
}
});
// TODO: ui
- actions.add(new KeyAction(Mode.ASK_USER, 'a', Trans.StringId.DUMMY) {
+ actions.add(new KeyAction(Mode.ASK_USER, 'a', StringId.DUMMY) {
@Override
public Object getObject() {
return contact;
});
// TODO: use a real UI for this, not a simple text box (a list or
// something, maybe a whole new pane?)
- actions.add(new KeyAction(Mode.ASK_USER, 't', Trans.StringId.DUMMY) {
+ actions.add(new KeyAction(Mode.ASK_USER, 't', StringId.DUMMY) {
private String previous;
@Override
return "Cannot modify value";
}
});
- actions.add(new KeyAction(Mode.ASK_USER, 'g', Trans.StringId.DUMMY) {
+ actions.add(new KeyAction(Mode.ASK_USER, 'g', StringId.DUMMY) {
private String previous;
@Override
}
});
actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
- Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
+ StringId.KEY_ACTION_SWITCH_FORMAT) {
@Override
public boolean onAction() {
extMode = !extMode;
if (data == null)
return parts;
- Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
- : Element.CONTACT_LINE;
- Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
- : Element.CONTACT_LINE_SEPARATOR;
- Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
- : Element.CONTACT_LINE_DIRTY;
+ ColorOption el = (focused && selected) ? ColorOption.CONTACT_LINE_SELECTED
+ : ColorOption.CONTACT_LINE;
+ ColorOption elSep = (focused && selected) ? ColorOption.CONTACT_LINE_SEPARATOR_SELECTED
+ : ColorOption.CONTACT_LINE_SEPARATOR;
+ ColorOption elDirty = (focused && selected) ? ColorOption.CONTACT_LINE_DIRTY_SELECTED
+ : ColorOption.CONTACT_LINE_DIRTY;
if (data.isDirty()) {
parts.add(new TextPart(" ", el));
import be.nikiroo.jvcard.Contact;
import be.nikiroo.jvcard.Data;
import be.nikiroo.jvcard.launcher.Main;
-import be.nikiroo.jvcard.resources.Bundles;
-import be.nikiroo.jvcard.resources.Trans;
+import be.nikiroo.jvcard.resources.bundles.DisplayBundle;
+import be.nikiroo.jvcard.resources.enums.DisplayOption;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
import be.nikiroo.jvcard.tui.KeyAction;
import be.nikiroo.jvcard.tui.KeyAction.DataType;
import be.nikiroo.jvcard.tui.KeyAction.Mode;
-import be.nikiroo.jvcard.tui.UiColors.Element;
import com.googlecode.lanterna.input.KeyType;
private String format;
public ContactList(Card card) {
+ DisplayBundle map = new DisplayBundle();
formats = new LinkedList<String>();
- for (String format : Bundles.getBundle("display")
- .getString("CONTACT_LIST_FORMAT").split(",")) {
+ for (String format : map.getString(DisplayOption.CONTACT_LIST_FORMAT)
+ .split(",")) {
formats.add(format);
}
// TODO ui
actions.add(new KeyAction(Mode.ASK_USER, 'a',
- Trans.StringId.KEY_ACTION_ADD) {
+ StringId.KEY_ACTION_ADD) {
@Override
public Object getObject() {
return card;
@Override
public String getQuestion() {
- return Main.trans(Trans.StringId.ASK_USER_CONTACT_NAME);
+ return Main.trans(StringId.ASK_USER_CONTACT_NAME);
}
@Override
}
});
actions.add(new KeyAction(Mode.ASK_USER_KEY, 'd',
- Trans.StringId.KEY_ACTION_DELETE_CONTACT) {
+ StringId.KEY_ACTION_DELETE_CONTACT) {
@Override
public Object getObject() {
return getSelectedContact();
if (contact != null)
contactName = "" + contact.getPreferredDataValue("FN");
- return Main.trans(Trans.StringId.CONFIRM_USER_DELETE_CONTACT,
+ return Main.trans(
+ StringId.CONFIRM_USER_DELETE_CONTACT,
contactName);
}
if (contact != null)
contactName = "" + contact.getPreferredDataValue("FN");
- return Main.trans(Trans.StringId.ERR_CANNOT_DELETE_CONTACT,
+ return Main.trans(
+ StringId.ERR_CANNOT_DELETE_CONTACT,
contactName);
}
}
});
actions.add(new KeyAction(Mode.ASK_USER_KEY, 's',
- Trans.StringId.KEY_ACTION_SAVE_CARD) {
+ StringId.KEY_ACTION_SAVE_CARD) {
@Override
public Object getObject() {
return card;
});
actions.add(new KeyAction(Mode.CONTACT_DETAILS, KeyType.Enter,
- Trans.StringId.KEY_ACTION_VIEW_CONTACT) {
+ StringId.KEY_ACTION_VIEW_CONTACT) {
@Override
public Object getObject() {
return getSelectedContact();
}
});
actions.add(new KeyAction(Mode.NONE, KeyType.Tab,
- Trans.StringId.KEY_ACTION_SWITCH_FORMAT) {
+ StringId.KEY_ACTION_SWITCH_FORMAT) {
@Override
public boolean onAction() {
switchFormat();
}
});
actions.add(new KeyAction(Mode.ASK_USER, 'w',
- Trans.StringId.KEY_ACTION_SEARCH) {
+ StringId.KEY_ACTION_SEARCH) {
@Override
public String getQuestion() {
if (contact == null)
return parts;
- Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
- : Element.CONTACT_LINE;
- Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
- : Element.CONTACT_LINE_SEPARATOR;
- Element elDirty = (focused && selected) ? Element.CONTACT_LINE_DIRTY_SELECTED
- : Element.CONTACT_LINE_DIRTY;
+ ColorOption el = (focused && selected) ? ColorOption.CONTACT_LINE_SELECTED
+ : ColorOption.CONTACT_LINE;
+ ColorOption elSep = (focused && selected) ? ColorOption.CONTACT_LINE_SEPARATOR_SELECTED
+ : ColorOption.CONTACT_LINE_SEPARATOR;
+ ColorOption elDirty = (focused && selected) ? ColorOption.CONTACT_LINE_DIRTY_SELECTED
+ : ColorOption.CONTACT_LINE_DIRTY;
width -= 2; // dirty mark space
import be.nikiroo.jvcard.launcher.Main;
import be.nikiroo.jvcard.parsers.Format;
import be.nikiroo.jvcard.resources.StringUtils;
-import be.nikiroo.jvcard.resources.Trans;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
import be.nikiroo.jvcard.tui.KeyAction;
import be.nikiroo.jvcard.tui.KeyAction.DataType;
import be.nikiroo.jvcard.tui.KeyAction.Mode;
-import be.nikiroo.jvcard.tui.UiColors.Element;
import com.googlecode.lanterna.input.KeyType;
// TODO: from ini file?
int SIZE_COL_1 = 3;
- Element el = (focused && selected) ? Element.CONTACT_LINE_SELECTED
- : Element.CONTACT_LINE;
- Element elSep = (focused && selected) ? Element.CONTACT_LINE_SEPARATOR_SELECTED
- : Element.CONTACT_LINE_SEPARATOR;
+ ColorOption el = (focused && selected) ? ColorOption.CONTACT_LINE_SELECTED
+ : ColorOption.CONTACT_LINE;
+ ColorOption elSep = (focused && selected) ? ColorOption.CONTACT_LINE_SEPARATOR_SELECTED
+ : ColorOption.CONTACT_LINE_SEPARATOR;
List<TextPart> parts = new LinkedList<TextPart>();
// TODO del, save...
actions.add(new KeyAction(Mode.CONTACT_LIST, KeyType.Enter,
- Trans.StringId.KEY_ACTION_VIEW_CARD) {
+ StringId.KEY_ACTION_VIEW_CARD) {
private Object obj = null;
@Override
import be.nikiroo.jvcard.launcher.Main;
import be.nikiroo.jvcard.resources.StringUtils;
-import be.nikiroo.jvcard.resources.Trans.StringId;
-import be.nikiroo.jvcard.tui.UiColors.Element;
+import be.nikiroo.jvcard.resources.enums.ColorOption;
+import be.nikiroo.jvcard.resources.enums.StringId;
+import be.nikiroo.jvcard.tui.UiColors;
import com.googlecode.lanterna.TextColor;
import com.googlecode.lanterna.gui2.AbstractListBox.ListItemRenderer;
*/
public class TextPart {
private String text;
- private Element element;
+ private ColorOption element;
- public TextPart(String text, Element element) {
+ public TextPart(String text, ColorOption element) {
this.text = text;
this.element = element;
}
return text;
}
- public Element getElement() {
+ public ColorOption getElement() {
return element;
}
public TextColor getForegroundColor() {
if (element != null)
- return element.getForegroundColor();
- return Element.DEFAULT.getForegroundColor();
+ return UiColors.getForegroundColor(element);
+ return UiColors.getForegroundColor(ColorOption.DEFAULT);
}
public TextColor getBackgroundColor() {
if (element != null)
- return element.getBackgroundColor();
- return Element.DEFAULT.getBackgroundColor();
+ return UiColors.getBackgroundColor(element);
+ return UiColors.getBackgroundColor(ColorOption.DEFAULT);
}
}
addItem(run.toString());
}
setSelectedIndex(index);
-
+
return deleted;
}
if (selected && focused) {
parts.add(new TextPart("" + lines.getItems().get(index),
- Element.CONTACT_LINE_SELECTED));
+ ColorOption.CONTACT_LINE_SELECTED));
} else {
parts.add(new TextPart("" + lines.getItems().get(index),
- Element.CONTACT_LINE));
+ ColorOption.CONTACT_LINE));
}
return parts;