Cleanup, imported i18n support from I2P and GNU gettext.

Imported high res/svg version of itoopie from dr|zed.
This commit is contained in:
dev
2011-06-20 12:38:52 +00:00
parent 6e86a911ef
commit 2219834dda
17 changed files with 655 additions and 321 deletions

View File

@ -1,10 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project basedir="." default="all" name="desktopgui"> <project basedir="." default="all" name="itoopie">
<property name="src" value="src"/> <property name="src" value="src"/>
<property name="build" value="build"/> <property name="build" value="build"/>
<property name="dist" location="dist"/> <property name="dist" location="dist"/>
<property name="jar" value="desktopgui.jar"/> <property name="jar" value="itoopie.jar"/>
<property name="resources" value="resources"/> <property name="resources" value="resources"/>
<property name="javadoc" value="javadoc"/> <property name="javadoc" value="javadoc"/>
@ -33,7 +33,7 @@
<pathelement location="../../router/java/build/router.jar" /> <pathelement location="../../router/java/build/router.jar" />
</classpath> </classpath>
</javac> </javac>
<copy todir="${build}/desktopgui/${resources}"> <copy todir="${build}/itoopie/${resources}">
<fileset dir="${resources}" /> <fileset dir="${resources}" />
</copy> </copy>
</target> </target>
@ -48,7 +48,7 @@
<jar basedir="${build}" destfile="${dist}/${jar}"> <jar basedir="${build}" destfile="${dist}/${jar}">
<manifest> <manifest>
<attribute name="Main-Class" value="net.i2p.desktopgui.Main"/> <attribute name="Main-Class" value="net.i2p.itoopie.Main"/>
</manifest> </manifest>
</jar> </jar>
</target> </target>
@ -61,7 +61,7 @@
packagenames="*" packagenames="*"
use="true" use="true"
splitindex="true" splitindex="true"
windowtitle="Desktopgui"> windowtitle="itoopie">
<classpath> <classpath>
<pathelement location="../../router/java/build/router.jar" /> <pathelement location="../../router/java/build/router.jar" />
<pathelement location="../../core/java/build/i2p.jar" /> <pathelement location="../../core/java/build/i2p.jar" />
@ -69,7 +69,8 @@
</javadoc> </javadoc>
</target> </target>
<target name="poupdate"> <target name="poupdate" depends="init">
<exec executable="sh" osfamily="unix" failifexecutionfails="true" > <exec executable="sh" osfamily="unix" failifexecutionfails="true" >
<arg value="./bundle-messages.sh" /> <arg value="./bundle-messages.sh" />
<arg value="-p" /> <arg value="-p" />

View File

@ -9,8 +9,9 @@
# #
# zzz - public domain # zzz - public domain
# Mathiasdm - modifications for desktopgui # Mathiasdm - modifications for desktopgui
# hottuna - modifications for itoopie
# #
CLASS=net.i2p.desktopgui.messages CLASS=net.i2p.itoopie.messages
TMPFILE=build/javafiles.txt TMPFILE=build/javafiles.txt
export TZ=UTC export TZ=UTC
@ -19,7 +20,7 @@ then
POUPDATE=1 POUPDATE=1
fi fi
# add ../java/ so the refs will work in the po file # add ../src/ so the refs will work in the po file
JPATHS="src" JPATHS="src"
for i in locale/messages_*.po for i in locale/messages_*.po
do do
@ -34,8 +35,8 @@ do
fi fi
echo $LG echo $LG
if [ -s build/net/i2p/desktopgui/messages_$LG.class -a \ if [ -s build/net/i2p/itoopie/messages_$LG.class -a \
build/net/i2p/desktopgui/messages_$LG.class -nt $i -a \ build/net/i2p/itoopie/messages_$LG.class -nt $i -a \
! -s $TMPFILE ] ! -s $TMPFILE ]
then then
continue continue
@ -57,10 +58,10 @@ do
# To start a new translation, copy the header from an old translation to the new .po file, # To start a new translation, copy the header from an old translation to the new .po file,
# then ant distclean updater. # then ant distclean updater.
find $JPATHS -name *.java > $TMPFILE find $JPATHS -name *.java > $TMPFILE
xgettext -f $TMPFILE -F -L java --from-code=UTF-8 --add-comments\ xgettext -f $TMPFILE -F -L java --verbose --from-code=UTF-8 --add-comments\
--keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \ --keyword=_ --keyword=_x --keyword=intl._ --keyword=intl.title \
--keyword=handler._ --keyword=formhandler._ \ --keyword=handler._ --keyword=formhandler._ \
--keyword=net.i2p.router.web.Messages.getString \ --keyword=net.i2p.itoopie.i18n.ItoopieTranslator.getString \
-o ${i}t -o ${i}t
if [ $? -ne 0 ] if [ $? -ne 0 ]
then then

View File

@ -0,0 +1,269 @@
/* GNU gettext for Java
* Copyright (C) 2001, 2007 Free Software Foundation, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published
* by the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
* USA.
*/
package gnu.gettext;
import java.lang.reflect.*;
import java.util.*;
/**
* This class implements the main GNU libintl functions in Java.
* <P>
* Using the GNU gettext approach, compiled message catalogs are normal
* Java ResourceBundle classes and are thus interoperable with standard
* ResourceBundle based code.
* <P>
* The main differences between the Sun ResourceBundle approach and the
* GNU gettext approach are:
* <UL>
* <LI>In the Sun approach, the keys are abstract textual shortcuts.
* In the GNU gettext approach, the keys are the English/ASCII version
* of the messages.
* <LI>In the Sun approach, the translation files are called
* "<VAR>Resource</VAR>_<VAR>locale</VAR>.properties" and have non-ASCII
* characters encoded in the Java
* <CODE>\</CODE><CODE>u<VAR>nnnn</VAR></CODE> syntax. Very few editors
* can natively display international characters in this format. In the
* GNU gettext approach, the translation files are called
* "<VAR>Resource</VAR>.<VAR>locale</VAR>.po"
* and are in the encoding the translator has chosen. Many editors
* can be used. There are at least three GUI translating tools
* (Emacs PO mode, KDE KBabel, GNOME gtranslator).
* <LI>In the Sun approach, the function
* <CODE>ResourceBundle.getString</CODE> throws a
* <CODE>MissingResourceException</CODE> when no translation is found.
* In the GNU gettext approach, the <CODE>gettext</CODE> function
* returns the (English) message key in that case.
* <LI>In the Sun approach, there is no support for plural handling.
* Even the most elaborate MessageFormat strings cannot provide decent
* plural handling. In the GNU gettext approach, we have the
* <CODE>ngettext</CODE> function.
* </UL>
* <P>
* To compile GNU gettext message catalogs into Java ResourceBundle classes,
* the <CODE>msgfmt</CODE> program can be used.
*
* @author Bruno Haible
*/
public abstract class GettextResource extends ResourceBundle {
public static boolean verbose = false;
/**
* Like gettext(catalog,msgid), except that it returns <CODE>null</CODE>
* when no translation was found.
*/
private static String gettextnull (ResourceBundle catalog, String msgid) {
try {
return (String)catalog.getObject(msgid);
} catch (MissingResourceException e) {
return null;
}
}
/**
* Returns the translation of <VAR>msgid</VAR>.
* @param catalog a ResourceBundle
* @param msgid the key string to be translated, an ASCII string
* @return the translation of <VAR>msgid</VAR>, or <VAR>msgid</VAR> if
* none is found
*/
public static String gettext (ResourceBundle catalog, String msgid) {
String result = gettextnull(catalog,msgid);
if (result != null)
return result;
return msgid;
}
/**
* Like ngettext(catalog,msgid,msgid_plural,n), except that it returns
* <CODE>null</CODE> when no translation was found.
*/
private static String ngettextnull (ResourceBundle catalog, String msgid, long n) {
// The reason why we use so many reflective API calls instead of letting
// the GNU gettext generated ResourceBundles implement some interface,
// is that we want the generated ResourceBundles to be completely
// standalone, so that migration from the Sun approach to the GNU gettext
// approach (without use of plurals) is as straightforward as possible.
ResourceBundle origCatalog = catalog;
do {
// Try catalog itself.
if (verbose)
System.out.println("ngettext on "+catalog);
Method handleGetObjectMethod = null;
Method getParentMethod = null;
try {
handleGetObjectMethod = catalog.getClass().getMethod("handleGetObject", new Class[] { java.lang.String.class });
getParentMethod = catalog.getClass().getMethod("getParent", new Class[0]);
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
}
if (verbose)
System.out.println("handleGetObject = "+(handleGetObjectMethod!=null)+", getParent = "+(getParentMethod!=null));
if (handleGetObjectMethod != null
&& Modifier.isPublic(handleGetObjectMethod.getModifiers())
&& getParentMethod != null) {
// A GNU gettext created class.
Method lookupMethod = null;
Method pluralEvalMethod = null;
try {
lookupMethod = catalog.getClass().getMethod("lookup", new Class[] { java.lang.String.class });
pluralEvalMethod = catalog.getClass().getMethod("pluralEval", new Class[] { Long.TYPE });
} catch (NoSuchMethodException e) {
} catch (SecurityException e) {
}
if (verbose)
System.out.println("lookup = "+(lookupMethod!=null)+", pluralEval = "+(pluralEvalMethod!=null));
if (lookupMethod != null && pluralEvalMethod != null) {
// A GNU gettext created class with plural handling.
Object localValue = null;
try {
localValue = lookupMethod.invoke(catalog, new Object[] { msgid });
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
}
if (localValue != null) {
if (verbose)
System.out.println("localValue = "+localValue);
if (localValue instanceof String)
// Found the value. It doesn't depend on n in this case.
return (String)localValue;
else {
String[] pluralforms = (String[])localValue;
long i = 0;
try {
i = ((Long) pluralEvalMethod.invoke(catalog, new Object[] { new Long(n) })).longValue();
if (!(i >= 0 && i < pluralforms.length))
i = 0;
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
}
return pluralforms[(int)i];
}
}
} else {
// A GNU gettext created class without plural handling.
Object localValue = null;
try {
localValue = handleGetObjectMethod.invoke(catalog, new Object[] { msgid });
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
}
if (localValue != null) {
// Found the value. It doesn't depend on n in this case.
if (verbose)
System.out.println("localValue = "+localValue);
return (String)localValue;
}
}
Object parentCatalog = catalog;
try {
parentCatalog = getParentMethod.invoke(catalog, new Object[0]);
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.getTargetException().printStackTrace();
}
if (parentCatalog != catalog)
catalog = (ResourceBundle)parentCatalog;
else
break;
} else
// Not a GNU gettext created class.
break;
} while (catalog != null);
// The end of chain of GNU gettext ResourceBundles is reached.
if (catalog != null) {
// For a non-GNU ResourceBundle we cannot access 'parent' and
// 'handleGetObject', so make a single call to catalog and all
// its parent catalogs at once.
Object value;
try {
value = catalog.getObject(msgid);
} catch (MissingResourceException e) {
value = null;
}
if (value != null)
// Found the value. It doesn't depend on n in this case.
return (String)value;
}
// Default: null.
return null;
}
/**
* Returns the plural form for <VAR>n</VAR> of the translation of
* <VAR>msgid</VAR>.
* @param catalog a ResourceBundle
* @param msgid the key string to be translated, an ASCII string
* @param msgid_plural its English plural form
* @return the translation of <VAR>msgid</VAR> depending on <VAR>n</VAR>,
* or <VAR>msgid</VAR> or <VAR>msgid_plural</VAR> if none is found
*/
public static String ngettext (ResourceBundle catalog, String msgid, String msgid_plural, long n) {
String result = ngettextnull(catalog,msgid,n);
if (result != null)
return result;
// Default: English strings and Germanic plural rule.
return (n != 1 ? msgid_plural : msgid);
}
/* The separator between msgctxt and msgid. */
private static final String CONTEXT_GLUE = "\u0004";
/**
* Returns the translation of <VAR>msgid</VAR> in the context of
* <VAR>msgctxt</VAR>.
* @param catalog a ResourceBundle
* @param msgctxt the context for the key string, an ASCII string
* @param msgid the key string to be translated, an ASCII string
* @return the translation of <VAR>msgid</VAR>, or <VAR>msgid</VAR> if
* none is found
*/
public static String pgettext (ResourceBundle catalog, String msgctxt, String msgid) {
String result = gettextnull(catalog,msgctxt+CONTEXT_GLUE+msgid);
if (result != null)
return result;
return msgid;
}
/**
* Returns the plural form for <VAR>n</VAR> of the translation of
* <VAR>msgid</VAR> in the context of <VAR>msgctxt</VAR>.
* @param catalog a ResourceBundle
* @param msgctxt the context for the key string, an ASCII string
* @param msgid the key string to be translated, an ASCII string
* @param msgid_plural its English plural form
* @return the translation of <VAR>msgid</VAR> depending on <VAR>n</VAR>,
* or <VAR>msgid</VAR> or <VAR>msgid_plural</VAR> if none is found
*/
public static String npgettext (ResourceBundle catalog, String msgctxt, String msgid, String msgid_plural, long n) {
String result = ngettextnull(catalog,msgctxt+CONTEXT_GLUE+msgid,n);
if (result != null)
return result;
// Default: English strings and Germanic plural rule.
return (n != 1 ? msgid_plural : msgid);
}
}

View File

@ -1,52 +0,0 @@
package net.i2p.desktopgui;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.TrayIcon;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.SwingWorker;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.util.Log;
public class ExternalTrayManager extends TrayManager {
private final static Log log = new Log(ExternalTrayManager.class);
protected ExternalTrayManager() {}
@Override
public PopupMenu getMainMenu() {
PopupMenu popup = new PopupMenu();
MenuItem startItem = new MenuItem(_("Start I2P"));
startItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
RouterManager.start();
return null;
}
@Override
protected void done() {
trayIcon.displayMessage(_("Starting"), _("I2P is starting!"), TrayIcon.MessageType.INFO);
//Hide the tray icon.
//We cannot stop the desktopgui program entirely,
//since that risks killing the I2P process as well.
tray.remove(trayIcon);
}
}.execute();
}
});
popup.add(startItem);
return popup;
}
}

View File

@ -1,97 +0,0 @@
package net.i2p.desktopgui;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.Desktop.Action;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.swing.SwingWorker;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.desktopgui.util.BrowseException;
import net.i2p.desktopgui.util.ConfigurationManager;
import net.i2p.desktopgui.util.I2PDesktop;
import net.i2p.util.Log;
/**
* Manages the tray icon life.
*/
public abstract class TrayManager {
private static TrayManager instance = null;
///The tray area, or null if unsupported
protected SystemTray tray = null;
///Our tray icon, or null if unsupported
protected TrayIcon trayIcon = null;
private final static Log log = new Log(TrayManager.class);
/**
* Instantiate tray manager.
*/
protected TrayManager() {}
protected static TrayManager getInstance() {
if(instance == null) {
boolean inI2P = RouterManager.inI2P();
if(inI2P) {
instance = new InternalTrayManager();
}
else {
instance = new ExternalTrayManager();
}
}
return instance;
}
/**
* Add the tray icon to the system tray and start everything up.
*/
protected void startManager() {
if(SystemTray.isSupported()) {
tray = SystemTray.getSystemTray();
trayIcon = new TrayIcon(getTrayImage(), "I2P", getMainMenu());
trayIcon.setImageAutoSize(true); //Resize image to fit the system tray
try {
tray.add(trayIcon);
} catch (AWTException e) {
log.log(Log.WARN, "Problem creating system tray icon!", e);
}
}
}
protected void languageChanged() {
trayIcon.setPopupMenu(getMainMenu());
}
/**
* Build a popup menu, adding callbacks to the different items.
* @return popup menu
*/
protected abstract PopupMenu getMainMenu();
/**
* Get tray icon image from the desktopgui resources in the jar file.
* @return image used for the tray icon
*/
private Image getTrayImage() {
URL url = getClass().getResource("/desktopgui/resources/images/logo.png");
Image image = Toolkit.getDefaultToolkit().getImage(url);
return image;
}
protected static String _(String s) {
return DesktopguiTranslator._(s);
}
}

View File

@ -1,26 +0,0 @@
package net.i2p.desktopgui.i18n;
import net.i2p.I2PAppContext;
import net.i2p.util.Translate;
public class DesktopguiTranslator {
private static final String BUNDLE_NAME = "net.i2p.desktopgui.messages";
private static I2PAppContext ctx;
private static I2PAppContext getRouterContext() {
if(ctx == null) {
ctx = I2PAppContext.getCurrentContext();
}
return ctx;
}
public static String _(String s) {
return Translate.getString(s, getRouterContext(), BUNDLE_NAME);
}
public static String _(String s, Object o) {
return Translate.getString(s, o, getRouterContext(), BUNDLE_NAME);
}
}

View File

@ -1,5 +0,0 @@
<html>
<body>
<p>Desktopgui is a graphical interface to I2P that allows managing the lifecycle of I2P from the system tray.</p>
</body>
</html>

View File

@ -1,98 +0,0 @@
package net.i2p.desktopgui.router;
import java.io.IOException;
import org.tanukisoftware.wrapper.WrapperManager;
import net.i2p.I2PAppContext;
import net.i2p.desktopgui.i18n.DesktopguiTranslator;
import net.i2p.desktopgui.util.ConfigurationManager;
import net.i2p.router.Router;
import net.i2p.router.RouterContext;
import net.i2p.util.Log;
/**
* Handle communications with the router instance.
* @author mathias
*
*/
public class RouterManager {
private final static Log log = new Log(RouterManager.class);
private static I2PAppContext context = I2PAppContext.getCurrentContext();
public static I2PAppContext getAppContext() {
return context;
}
public static RouterContext getRouterContext() throws Exception {
if(context.isRouterContext()) {
return (RouterContext) context;
}
else {
throw new Exception("No RouterContext available!");
}
}
private static Router getRouter() {
try {
return getRouterContext().router();
} catch (Exception e) {
log.error("Failed to get router. Why did we request it if no RouterContext is available?", e);
return null;
}
}
/**
* Start an I2P router instance.
* This method has limited knowledge
* (there is no I2P instance running to collect information from).
*
* It determines the I2P location using the I2PAppContext.
*/
public static void start() {
try {
//TODO: set/get PID
String separator = System.getProperty("file.separator");
String location = getAppContext().getBaseDir().getAbsolutePath();
Runtime.getRuntime().exec(location + separator + "i2psvc " + location + separator + "wrapper.config");
} catch (IOException e) {
log.log(Log.WARN, "Failed to start I2P", e);
}
}
/**
* Restart the running I2P instance.
*/
public static void restart() {
if(inI2P()) {
getRouter().restart();
}
}
/**
* Stop the running I2P instance.
*/
public static void shutDown() {
if(inI2P()) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
WrapperManager.signalStopped(Router.EXIT_HARD);
}
});
t.start();
getRouter().shutdown(Router.EXIT_HARD);
}
}
/**
* Check if we are running inside I2P.
*/
public static boolean inI2P() {
return context.isRouterContext();
}
}

View File

@ -1,4 +1,4 @@
package net.i2p.desktopgui; package net.i2p.itoopie;
import java.awt.MenuItem; import java.awt.MenuItem;
import java.awt.PopupMenu; import java.awt.PopupMenu;
@ -7,14 +7,11 @@ import java.awt.event.ActionListener;
import javax.swing.SwingWorker; import javax.swing.SwingWorker;
import net.i2p.desktopgui.router.RouterManager; import net.i2p.itoopie.util.BrowseException;
import net.i2p.desktopgui.util.BrowseException; import net.i2p.itoopie.util.I2PDesktop;
import net.i2p.desktopgui.util.I2PDesktop;
import net.i2p.util.Log;
public class InternalTrayManager extends TrayManager { public class InternalTrayManager extends TrayManager {
private final static Log log = new Log(InternalTrayManager.class);
protected InternalTrayManager() {} protected InternalTrayManager() {}
@ -39,7 +36,7 @@ public class InternalTrayManager extends TrayManager {
try { try {
I2PDesktop.browse("http://localhost:7657"); I2PDesktop.browse("http://localhost:7657");
} catch (BrowseException e1) { } catch (BrowseException e1) {
log.log(Log.WARN, "Failed to open browser!", e1); //log.log(Log.WARN, "Failed to open browser!", e1);
} }
} }
@ -55,7 +52,7 @@ public class InternalTrayManager extends TrayManager {
@Override @Override
protected Object doInBackground() throws Exception { protected Object doInBackground() throws Exception {
RouterManager.restart(); //RouterManager.restart();
return null; return null;
} }
@ -73,7 +70,7 @@ public class InternalTrayManager extends TrayManager {
@Override @Override
protected Object doInBackground() throws Exception { protected Object doInBackground() throws Exception {
RouterManager.shutDown(); //RouterManager.shutDown();
return null; return null;
} }

View File

@ -1,4 +1,4 @@
package net.i2p.desktopgui; package net.i2p.itoopie;
/* /*
* Main.java * Main.java
@ -8,13 +8,6 @@ import javax.swing.SwingUtilities;
import javax.swing.UIManager; import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException; import javax.swing.UnsupportedLookAndFeelException;
import net.i2p.I2PAppContext;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.desktopgui.util.*;
import net.i2p.util.Log;
import net.i2p.util.Translate;
import net.i2p.util.I2PProperties.I2PPropertyCallback;
/** /**
* The main class of the application. * The main class of the application.
*/ */
@ -22,7 +15,6 @@ public class Main {
///Manages the lifetime of the tray icon. ///Manages the lifetime of the tray icon.
private TrayManager trayManager = null; private TrayManager trayManager = null;
private final static Log log = new Log(Main.class);
/** /**
* Start the tray icon code (loads tray icon in the tray area). * Start the tray icon code (loads tray icon in the tray area).
@ -31,7 +23,7 @@ public class Main {
public void startUp() throws Exception { public void startUp() throws Exception {
trayManager = TrayManager.getInstance(); trayManager = TrayManager.getInstance();
trayManager.startManager(); trayManager.startManager();
/*
if(RouterManager.inI2P()) { if(RouterManager.inI2P()) {
RouterManager.getRouterContext().addPropertyCallback(new I2PPropertyCallback() { RouterManager.getRouterContext().addPropertyCallback(new I2PPropertyCallback() {
@ -44,6 +36,7 @@ public class Main {
}); });
} }
*/
} }
public static void main(String[] args) { public static void main(String[] args) {
@ -58,16 +51,16 @@ public class Main {
try { try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) { } catch (ClassNotFoundException ex) {
log.log(Log.ERROR, null, ex); //log.log(Log.ERROR, null, ex);
} catch (InstantiationException ex) { } catch (InstantiationException ex) {
log.log(Log.ERROR, null, ex); //log.log(Log.ERROR, null, ex);
} catch (IllegalAccessException ex) { } catch (IllegalAccessException ex) {
log.log(Log.ERROR, null, ex); //log.log(Log.ERROR, null, ex);
} catch (UnsupportedLookAndFeelException ex) { } catch (UnsupportedLookAndFeelException ex) {
log.log(Log.ERROR, null, ex); //log.log(Log.ERROR, null, ex);
} }
ConfigurationManager.getInstance().loadArguments(args); //ConfigurationManager.getInstance().loadArguments(args);
final Main main = new Main(); final Main main = new Main();
@ -81,7 +74,7 @@ public class Main {
main.startUp(); main.startUp();
} }
catch(Exception e) { catch(Exception e) {
log.error("Failed while running desktopgui!", e); //log.error("Failed while running desktopgui!", e);
} }
} }

View File

@ -0,0 +1,159 @@
package net.i2p.itoopie;
import java.awt.AWTException;
import java.awt.Desktop;
import java.awt.Image;
import java.awt.MenuItem;
import java.awt.PopupMenu;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.awt.Desktop.Action;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import javax.swing.SwingWorker;
import net.i2p.itoopie.i18n.ItoopieTranslator;
import net.i2p.itoopie.util.BrowseException;
import net.i2p.itoopie.util.ConfigurationManager;
import net.i2p.itoopie.util.I2PDesktop;
/**
* Manages the tray icon life.
*/
public abstract class TrayManager {
private static TrayManager instance = null;
///The tray area, or null if unsupported
protected SystemTray tray = null;
///Our tray icon, or null if unsupported
protected TrayIcon trayIcon = null;
/**
* Instantiate tray manager.
*/
protected TrayManager() {}
protected static synchronized TrayManager getInstance() {
if(instance == null) {
instance = new InternalTrayManager();
}
return instance;
}
/**
* Add the tray icon to the system tray and start everything up.
*/
protected void startManager() {
if(SystemTray.isSupported()) {
tray = SystemTray.getSystemTray();
trayIcon = new TrayIcon(getTrayImage(), "I2P", getMainMenu());
trayIcon.setImageAutoSize(true); //Resize image to fit the system tray
try {
tray.add(trayIcon);
} catch (AWTException e) {
}
}
}
protected void languageChanged() {
trayIcon.setPopupMenu(getMainMenu());
}
/**
* Get tray icon image from the itoopie resources in the jar file.
* @return image used for the tray icon
*/
private Image getTrayImage() {
URL url = getClass().getResource("/itoopie/resources/images/itoopie-logo.png");
Image image = Toolkit.getDefaultToolkit().getImage(url);
return image;
}
protected static String _(String s) {
return ItoopieTranslator._(s);
}
/**
* Build a popup menu, adding callbacks to the different items.
* @return popup menu
*/
public PopupMenu getMainMenu() {
PopupMenu popup = new PopupMenu();
MenuItem browserLauncher = new MenuItem(_("Launch I2P Browser"));
browserLauncher.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
return null;
}
@Override
protected void done() {
try {
I2PDesktop.browse("http://localhost:7657");
} catch (BrowseException e1) {
//log.log(Log.WARN, "Failed to open browser!", e1);
}
}
}.execute();
}
});
MenuItem restartItem = new MenuItem(_("Restart I2P"));
restartItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
//RouterManager.restart();
return null;
}
}.execute();
}
});
MenuItem stopItem = new MenuItem(_("Stop I2P"));
stopItem.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent arg0) {
new SwingWorker<Object, Object>() {
@Override
protected Object doInBackground() throws Exception {
//RouterManager.shutDown();
return null;
}
}.execute();
}
});
popup.add(browserLauncher);
popup.addSeparator();
popup.add(restartItem);
popup.add(stopItem);
return popup;
}
}

View File

@ -0,0 +1,21 @@
package net.i2p.itoopie.i18n;
import java.util.Locale;
import java.util.ResourceBundle;
import net.i2p.itoopie.i18n.UTF8Control;
public class ItoopieTranslator {
private static final String BUNDLE_NAME = "net.i2p.itoopie.messages";
public static String _(String s) {
return Translate.getString(s, BUNDLE_NAME);
}
public static String _(String s, Object o) {
return Translate.getString(s, o, BUNDLE_NAME);
}
}

View File

@ -0,0 +1,169 @@
package net.i2p.itoopie.i18n;
import gnu.gettext.GettextResource;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
/**
* Translate strings efficiently.
* We don't include an English or default ResourceBundle, we simply check
* for "en" and return the original string.
* Support real-time language changing with the routerconsole.lang property.
*
* @author zzz, from a base generated by eclipse.
* @since 0.7.9
*/
public abstract class Translate {
public static final String PROP_LANG = "routerconsole.lang";
private static final String _localeLang = Locale.getDefault().getLanguage();
@SuppressWarnings("unchecked")
private static final Map<String, ResourceBundle> _bundles = new ConcurrentHashMap(2);
@SuppressWarnings("unchecked")
private static final ConcurrentHashMap<String,Boolean> _missing = new ConcurrentHashMap(2);
/** use to look for untagged strings */
private static final String TEST_LANG = "xx";
private static final String TEST_STRING = "XXXX";
/** lang in routerconsole.lang property, else current locale */
public static String getString(String key, String bun) {
String lang = Locale.getDefault().getLanguage();
if (lang.equals("en"))
return key;
else if (lang.equals(TEST_LANG))
return TEST_STRING;
// shouldnt happen but dont dump the po headers if it does
if (key.equals(""))
return key;
ResourceBundle bundle = findBundle(bun, lang);
if (bundle == null)
return key;
try {
return bundle.getString(key);
} catch (MissingResourceException e) {
return key;
}
}
/**
* translate a string with a parameter
* This is a lot more expensive than getString(s, ctx), so use sparingly.
*
* @param s string to be translated containing {0}
* The {0} will be replaced by the parameter.
* Single quotes must be doubled, i.e. ' -> '' in the string.
* @param o parameter, not translated.
* To tranlslate parameter also, use _("foo {0} bar", _("baz"))
* Do not double the single quotes in the parameter.
* Use autoboxing to call with ints, longs, floats, etc.
*/
public static String getString(String s, Object o, String bun) {
String lang = Locale.getDefault().getLanguage();
if (lang.equals(TEST_LANG))
return TEST_STRING + '(' + o + ')' + TEST_STRING;
String x = getString(s, bun);
Object[] oArray = new Object[1];
oArray[0] = o;
try {
MessageFormat fmt = new MessageFormat(x, new Locale(lang));
return fmt.format(oArray, new StringBuffer(), null).toString();
} catch (IllegalArgumentException iae) {
System.err.println("Bad format: orig: \"" + s +
"\" trans: \"" + x +
"\" param: \"" + o +
"\" lang: " + lang);
return "FIXME: " + x + ' ' + o;
}
}
/** for {0} and {1} */
public static String getString(String s, Object o, Object o2, String bun) {
String lang = Locale.getDefault().getLanguage();
if (lang.equals(TEST_LANG))
return TEST_STRING + '(' + o + ',' + o2 + ')' + TEST_STRING;
String x = getString(s, bun);
Object[] oArray = new Object[2];
oArray[0] = o;
oArray[1] = o2;
try {
MessageFormat fmt = new MessageFormat(x, new Locale(lang));
return fmt.format(oArray, new StringBuffer(), null).toString();
} catch (IllegalArgumentException iae) {
System.err.println("Bad format: orig: \"" + s +
"\" trans: \"" + x +
"\" param1: \"" + o +
"\" param2: \"" + o2 +
"\" lang: " + lang);
return "FIXME: " + x + ' ' + o + ',' + o2;
}
}
/**
* Use GNU ngettext
* For .po file format see http://www.gnu.org/software/gettext/manual/gettext.html.gz#Translating-plural-forms
*
* @param n how many
* @param s singluar string, optionally with {0} e.g. "one tunnel"
* @param p plural string optionally with {0} e.g. "{0} tunnels"
* @since 0.7.14
*/
public static String getString(int n, String s, String p, String bun) {
String lang = Locale.getDefault().getLanguage();
if (lang.equals(TEST_LANG))
return TEST_STRING + '(' + n + ')' + TEST_STRING;
ResourceBundle bundle = null;
if (!lang.equals("en"))
bundle = findBundle(bun, lang);
String x;
if (bundle == null)
x = n == 1 ? s : p;
else
x = GettextResource.ngettext(bundle, s, p, n);
Object[] oArray = new Object[1];
oArray[0] = Integer.valueOf(n);
try {
MessageFormat fmt = new MessageFormat(x, new Locale(lang));
return fmt.format(oArray, new StringBuffer(), null).toString();
} catch (IllegalArgumentException iae) {
System.err.println("Bad format: sing: \"" + s +
"\" plural: \"" + p +
"\" lang: " + lang);
return "FIXME: " + s + ' ' + p + ',' + n;
}
}
/** cache both found and not found for speed */
private static ResourceBundle findBundle(String bun, String lang) {
String key = bun + '-' + lang;
ResourceBundle rv = _bundles.get(key);
if (rv == null && !_missing.containsKey(key)) {
try {
// We must specify the class loader so that a webapp can find the bundle in the .war
rv = ResourceBundle.getBundle(bun, new Locale(lang), Thread.currentThread().getContextClassLoader());
if (rv != null)
_bundles.put(key, rv);
} catch (MissingResourceException e) {
_missing.put(key, true);
}
}
return rv;
}
/**
* Clear the cache.
* Call this after adding new bundles to the classpath.
* @since 0.7.12
*/
public static void clearCache() {
_missing.clear();
}
}

View File

@ -0,0 +1,5 @@
<html>
<body>
<p>itoopie is a graphical interface to I2P that allows managing and monitoring most aspects of I2P.</p>
</body>
</html>

View File

@ -1,4 +1,4 @@
package net.i2p.desktopgui.util; package net.i2p.itoopie.util;
public class BrowseException extends Exception { public class BrowseException extends Exception {

View File

@ -1,4 +1,4 @@
package net.i2p.desktopgui.util; package net.i2p.itoopie.util;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;

View File

@ -1,4 +1,4 @@
package net.i2p.desktopgui.util; package net.i2p.itoopie.util;
import java.awt.Desktop; import java.awt.Desktop;
import java.awt.TrayIcon; import java.awt.TrayIcon;
@ -7,12 +7,9 @@ import java.io.IOException;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import net.i2p.desktopgui.router.RouterManager;
import net.i2p.util.Log;
public class I2PDesktop { public class I2PDesktop {
private final static Log log = new Log(I2PDesktop.class);
public static void browse(String url) throws BrowseException { public static void browse(String url) throws BrowseException {
if(Desktop.isDesktopSupported()) { if(Desktop.isDesktopSupported()) {