diff --git a/apps/desktopgui/desktopgui/resources/logo/logo_green.jpg b/apps/desktopgui/desktopgui/resources/logo/logo_green.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9a29b6d1c3e10d658683a91c89fcfe106e538028
Binary files /dev/null and b/apps/desktopgui/desktopgui/resources/logo/logo_green.jpg differ
diff --git a/apps/desktopgui/desktopgui/resources/logo/logo_orange.jpg b/apps/desktopgui/desktopgui/resources/logo/logo_orange.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..137a25e7a033e632799ebb118a73c3044fedc0ee
Binary files /dev/null and b/apps/desktopgui/desktopgui/resources/logo/logo_orange.jpg differ
diff --git a/apps/desktopgui/desktopgui/resources/logo/logo_red.jpg b/apps/desktopgui/desktopgui/resources/logo/logo_red.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1da898381264bae953ddc628254788cbd4137433
Binary files /dev/null and b/apps/desktopgui/desktopgui/resources/logo/logo_red.jpg differ
diff --git a/apps/desktopgui/src/gui/GeneralConfiguration.form b/apps/desktopgui/src/gui/GeneralConfiguration.form
new file mode 100644
index 0000000000000000000000000000000000000000..070e2013828698aaffd404e9d1c9f6b75bdf401a
--- /dev/null
+++ b/apps/desktopgui/src/gui/GeneralConfiguration.form
@@ -0,0 +1,103 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<Form version="1.5" maxVersion="1.6" type="org.netbeans.modules.form.forminfo.JFrameFormInfo">
+  <Properties>
+    <Property name="defaultCloseOperation" type="int" value="3"/>
+    <Property name="name" type="java.lang.String" value="Form" noResource="true"/>
+  </Properties>
+  <SyntheticProperties>
+    <SyntheticProperty name="formSizePolicy" type="int" value="1"/>
+  </SyntheticProperties>
+  <AuxValues>
+    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="2"/>
+    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="true"/>
+    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+  </AuxValues>
+
+  <Layout>
+    <DimensionLayout dim="0">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <EmptySpace max="32767" attributes="0"/>
+              <Component id="jTabbedPane1" min="-2" pref="478" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+    <DimensionLayout dim="1">
+      <Group type="103" groupAlignment="0" attributes="0">
+          <Group type="102" alignment="1" attributes="0">
+              <EmptySpace max="32767" attributes="0"/>
+              <Component id="jTabbedPane1" min="-2" pref="369" max="-2" attributes="0"/>
+              <EmptySpace max="-2" attributes="0"/>
+          </Group>
+      </Group>
+    </DimensionLayout>
+  </Layout>
+  <SubComponents>
+    <Container class="javax.swing.JTabbedPane" name="jTabbedPane1">
+      <Properties>
+        <Property name="name" type="java.lang.String" value="jTabbedPane1" noResource="true"/>
+      </Properties>
+
+      <Layout class="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout"/>
+      <SubComponents>
+        <Container class="javax.swing.JPanel" name="jPanel1">
+          <Properties>
+            <Property name="name" type="java.lang.String" value="jPanel1" noResource="true"/>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
+              <JTabbedPaneConstraints tabName="tab1">
+                <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel1.TabConstraints.tabTitle"/>
+              </JTabbedPaneConstraints>
+            </Constraint>
+          </Constraints>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="474" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="338" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+        </Container>
+        <Container class="javax.swing.JPanel" name="jPanel2">
+          <Properties>
+            <Property name="name" type="java.lang.String" value="jPanel2" noResource="true"/>
+          </Properties>
+          <Constraints>
+            <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout" value="org.netbeans.modules.form.compat2.layouts.support.JTabbedPaneSupportLayout$JTabbedPaneConstraintsDescription">
+              <JTabbedPaneConstraints tabName="tab2">
+                <Property name="tabTitle" type="java.lang.String" resourceKey="jPanel2.TabConstraints.tabTitle"/>
+              </JTabbedPaneConstraints>
+            </Constraint>
+          </Constraints>
+
+          <Layout>
+            <DimensionLayout dim="0">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="474" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+            <DimensionLayout dim="1">
+              <Group type="103" groupAlignment="0" attributes="0">
+                  <EmptySpace min="0" pref="338" max="32767" attributes="0"/>
+              </Group>
+            </DimensionLayout>
+          </Layout>
+        </Container>
+      </SubComponents>
+    </Container>
+  </SubComponents>
+</Form>
diff --git a/apps/desktopgui/src/gui/GeneralConfiguration.java b/apps/desktopgui/src/gui/GeneralConfiguration.java
new file mode 100644
index 0000000000000000000000000000000000000000..b9c74038133a5afecc29fd5e7271fe7c7d433b62
--- /dev/null
+++ b/apps/desktopgui/src/gui/GeneralConfiguration.java
@@ -0,0 +1,106 @@
+/*
+ * GeneralConfiguration.java
+ *
+ * Created on 10 april 2009, 19:04
+ */
+
+package gui;
+
+/**
+ *
+ * @author  mathias
+ */
+public class GeneralConfiguration extends javax.swing.JFrame {
+
+    /** Creates new form GeneralConfiguration */
+    public GeneralConfiguration() {
+        initComponents();
+    }
+
+    /** This method is called from within the constructor to
+     * initialize the form.
+     * WARNING: Do NOT modify this code. The content of this method is
+     * always regenerated by the Form Editor.
+     */
+    @SuppressWarnings("unchecked")
+    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+    private void initComponents() {
+
+        jTabbedPane1 = new javax.swing.JTabbedPane();
+        jPanel1 = new javax.swing.JPanel();
+        jPanel2 = new javax.swing.JPanel();
+
+        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
+        setName("Form"); // NOI18N
+
+        jTabbedPane1.setName("jTabbedPane1"); // NOI18N
+
+        jPanel1.setName("jPanel1"); // NOI18N
+
+        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
+        jPanel1.setLayout(jPanel1Layout);
+        jPanel1Layout.setHorizontalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 474, Short.MAX_VALUE)
+        );
+        jPanel1Layout.setVerticalGroup(
+            jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 338, Short.MAX_VALUE)
+        );
+
+        org.jdesktop.application.ResourceMap resourceMap = org.jdesktop.application.Application.getInstance(desktopgui.Main.class).getContext().getResourceMap(GeneralConfiguration.class);
+        jTabbedPane1.addTab(resourceMap.getString("jPanel1.TabConstraints.tabTitle"), jPanel1); // NOI18N
+
+        jPanel2.setName("jPanel2"); // NOI18N
+
+        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
+        jPanel2.setLayout(jPanel2Layout);
+        jPanel2Layout.setHorizontalGroup(
+            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 474, Short.MAX_VALUE)
+        );
+        jPanel2Layout.setVerticalGroup(
+            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGap(0, 338, Short.MAX_VALUE)
+        );
+
+        jTabbedPane1.addTab(resourceMap.getString("jPanel2.TabConstraints.tabTitle"), jPanel2); // NOI18N
+
+        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
+        getContentPane().setLayout(layout);
+        layout.setHorizontalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 478, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap())
+        );
+        layout.setVerticalGroup(
+            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+            .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                .addComponent(jTabbedPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 369, javax.swing.GroupLayout.PREFERRED_SIZE)
+                .addContainerGap())
+        );
+
+        pack();
+    }// </editor-fold>//GEN-END:initComponents
+
+    /**
+    * @param args the command line arguments
+    */
+    public static void main(String args[]) {
+        java.awt.EventQueue.invokeLater(new Runnable() {
+            public void run() {
+                new GeneralConfiguration().setVisible(true);
+            }
+        });
+    }
+
+    // Variables declaration - do not modify//GEN-BEGIN:variables
+    private javax.swing.JPanel jPanel1;
+    private javax.swing.JPanel jPanel2;
+    private javax.swing.JTabbedPane jTabbedPane1;
+    // End of variables declaration//GEN-END:variables
+
+}
diff --git a/apps/desktopgui/src/gui/JPopupTrayIcon.java b/apps/desktopgui/src/gui/JPopupTrayIcon.java
new file mode 100644
index 0000000000000000000000000000000000000000..83872e4a51958c1b9b5ca094800ec731392574a3
--- /dev/null
+++ b/apps/desktopgui/src/gui/JPopupTrayIcon.java
@@ -0,0 +1,176 @@
+/*
+* Created on Sep 15, 2008  5:51:33 PM
+*/
+
+/*
+ * This class is part of fishfarm project: https://fishfarm.dev.java.net/
+ * It is licensed under the GPL version 2.0 with Classpath Exception.
+ * 
+ * Copyright (C) 2008  Michael Bien
+ * 
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, 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 General Public License for more details.
+ * 
+ * You should have received a copy of the GNU 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 gui;
+
+import java.awt.Dimension;
+import java.awt.Frame;
+import java.awt.GraphicsEnvironment;
+import java.awt.Image;
+import java.awt.Point;
+import java.awt.PopupMenu;
+import java.awt.TrayIcon;
+import java.awt.Window;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import javax.swing.JDialog;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JPopupMenu;
+import javax.swing.JWindow;
+import javax.swing.RootPaneContainer;
+import javax.swing.event.PopupMenuEvent;
+import javax.swing.event.PopupMenuListener;
+
+
+
+/**
+ * JPopupMenu compatible TrayIcon based on Alexander Potochkin's JXTrayIcon
+ * (http://weblogs.java.net/blog/alexfromsun/archive/2008/02/jtrayicon_updat.html)
+ * but uses a JWindow instead of a JDialog to workaround some bugs on linux.
+ *
+ * @author Michael Bien
+ */
+public class JPopupTrayIcon extends TrayIcon {
+
+    private JPopupMenu menu;
+    
+    private Window window;
+    private PopupMenuListener popupListener;
+    
+    private final static boolean IS_WINDOWS = System.getProperty("os.name").toLowerCase().contains("windows");
+
+    public JPopupTrayIcon(Image image) {
+        super(image);
+        init();
+    }
+
+    public JPopupTrayIcon(Image image, String tooltip) {
+        super(image, tooltip);
+        init();
+    }
+
+    public JPopupTrayIcon(Image image, String tooltip, PopupMenu popup) {
+        super(image, tooltip, popup);
+        init();
+    }
+
+    public JPopupTrayIcon(Image image, String tooltip, JPopupMenu popup) {
+        super(image, tooltip);
+        init();
+        setJPopupMenu(popup);
+    }
+
+
+    private final void init() {
+
+
+        popupListener = new PopupMenuListener() {
+
+            @Override
+            public void popupMenuWillBecomeVisible(PopupMenuEvent e) {
+//                System.out.println("popupMenuWillBecomeVisible");
+            }
+
+            @Override
+            public void popupMenuWillBecomeInvisible(PopupMenuEvent e) {
+//                System.out.println("popupMenuWillBecomeInvisible");
+                if(window != null) {
+                    window.dispose();
+                    window = null;
+                }
+            }
+
+            @Override
+            public void popupMenuCanceled(PopupMenuEvent e) {
+//                System.out.println("popupMenuCanceled");
+                if(window != null) {
+                    window.dispose();
+                    window = null;
+                }
+            }
+        };
+
+        addMouseListener(new MouseAdapter() {
+            @Override
+            public void mousePressed(MouseEvent e) {
+//                System.out.println(e.getPoint());
+                showJPopupMenu(e);
+            }
+
+            @Override
+            public void mouseReleased(MouseEvent e) {
+//                System.out.println(e.getPoint());
+                showJPopupMenu(e);
+            }
+        });
+
+    }
+
+    private final void showJPopupMenu(MouseEvent e) {
+        if(e.isPopupTrigger() && menu != null) {
+            if (window == null) {
+
+                if(IS_WINDOWS) {
+                    window = new JDialog((Frame)null);
+                    ((JDialog)window).setUndecorated(true);
+                }else{
+                    window = new JWindow((Frame)null);
+                }
+                window.setAlwaysOnTop(true);
+                Dimension size = menu.getPreferredSize();
+
+                Point centerPoint = GraphicsEnvironment.getLocalGraphicsEnvironment().getCenterPoint();
+                if(e.getY() > centerPoint.getY())
+                    window.setLocation(e.getX(), e.getY() - size.height);
+                else
+                    window.setLocation(e.getX(), e.getY());
+
+                window.setVisible(true);
+                
+                menu.show(((RootPaneContainer)window).getContentPane(), 0, 0);
+
+                // popup works only for focused windows
+                window.toFront();
+
+            }
+        }
+    }
+
+
+    public final JPopupMenu getJPopupMenu() {
+        return menu;
+    }
+
+    public final void setJPopupMenu(JPopupMenu menu) {
+        if (this.menu != null) {
+            this.menu.removePopupMenuListener(popupListener);
+        }
+        this.menu = menu;
+        menu.addPopupMenuListener(popupListener);
+    }
+
+}
diff --git a/apps/desktopgui/src/gui/SpeedSelector.form b/apps/desktopgui/src/gui/SpeedSelector.form
index 6ccf414b5b5053bd12dbfeb2c5e3341aca6052bf..79d25ae9650187e565486e5823d843a5a52a4727 100644
--- a/apps/desktopgui/src/gui/SpeedSelector.form
+++ b/apps/desktopgui/src/gui/SpeedSelector.form
@@ -22,6 +22,7 @@
     <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
     <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,56,0,0,2,102"/>
   </AuxValues>
 
   <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
diff --git a/apps/desktopgui/src/gui/SpeedSelector2.form b/apps/desktopgui/src/gui/SpeedSelector2.form
index 215d407f0fdb816796caa1f101cd111b7c5b90bb..5c305de19b450dfc4a0d812173e600d01612449d 100644
--- a/apps/desktopgui/src/gui/SpeedSelector2.form
+++ b/apps/desktopgui/src/gui/SpeedSelector2.form
@@ -26,6 +26,7 @@
     <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
     <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
     <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+    <AuxValue name="designerSize" type="java.awt.Dimension" value="-84,-19,0,5,115,114,0,18,106,97,118,97,46,97,119,116,46,68,105,109,101,110,115,105,111,110,65,-114,-39,-41,-84,95,68,20,2,0,2,73,0,6,104,101,105,103,104,116,73,0,5,119,105,100,116,104,120,112,0,0,1,44,0,0,2,105"/>
   </AuxValues>
 
   <Layout class="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout">
@@ -82,7 +83,7 @@
       </Properties>
       <Constraints>
         <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-          <AbsoluteConstraints x="40" y="130" width="-1" height="40"/>
+          <AbsoluteConstraints x="40" y="120" width="-1" height="40"/>
         </Constraint>
       </Constraints>
     </Component>
@@ -97,7 +98,7 @@
       </Properties>
       <Constraints>
         <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-          <AbsoluteConstraints x="40" y="80" width="-1" height="40"/>
+          <AbsoluteConstraints x="40" y="70" width="-1" height="40"/>
         </Constraint>
       </Constraints>
     </Component>
@@ -108,7 +109,7 @@
       </Properties>
       <Constraints>
         <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-          <AbsoluteConstraints x="30" y="190" width="530" height="50"/>
+          <AbsoluteConstraints x="30" y="170" width="530" height="70"/>
         </Constraint>
       </Constraints>
     </Component>
diff --git a/apps/desktopgui/src/gui/SpeedSelector2.java b/apps/desktopgui/src/gui/SpeedSelector2.java
index d929e4ccd2ca7462b0520c88f43f0982e01ef7b4..1177b5725817f5aead7062dc8dae196af3fc67e7 100644
--- a/apps/desktopgui/src/gui/SpeedSelector2.java
+++ b/apps/desktopgui/src/gui/SpeedSelector2.java
@@ -85,19 +85,19 @@ public class SpeedSelector2 extends javax.swing.JFrame {
         browseButton.setActionCommand(resourceMap.getString("browseButton.actionCommand")); // NOI18N
         browseButton.setName("browseButton"); // NOI18N
         getContentPane().add(browseButton);
-        browseButton.setBounds(40, 130, 520, 40);
+        browseButton.setBounds(40, 120, 520, 40);
 
         buttonGroup1.add(downloadButton);
         downloadButton.setText(resourceMap.getString("downloadButton.text")); // NOI18N
         downloadButton.setActionCommand(resourceMap.getString("downloadButton.actionCommand")); // NOI18N
         downloadButton.setName("downloadButton"); // NOI18N
         getContentPane().add(downloadButton);
-        downloadButton.setBounds(40, 80, 499, 40);
+        downloadButton.setBounds(40, 70, 499, 40);
 
         jLabel1.setText(resourceMap.getString("jLabel1.text")); // NOI18N
         jLabel1.setName("jLabel1"); // NOI18N
         getContentPane().add(jLabel1);
-        jLabel1.setBounds(30, 190, 530, 50);
+        jLabel1.setBounds(30, 170, 530, 70);
 
         pack();
     }// </editor-fold>//GEN-END:initComponents
diff --git a/apps/desktopgui/src/gui/SpeedSelector3.form b/apps/desktopgui/src/gui/SpeedSelector3.form
index ec2697221650b2f024d3c6fbd227a12a1823996e..9c6ef533aaf1ec69c313bf085b509734d178baf0 100644
--- a/apps/desktopgui/src/gui/SpeedSelector3.form
+++ b/apps/desktopgui/src/gui/SpeedSelector3.form
@@ -329,7 +329,7 @@
       </Properties>
       <Constraints>
         <Constraint layoutClass="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout" value="org.netbeans.modules.form.compat2.layouts.DesignAbsoluteLayout$AbsoluteConstraintsDescription">
-          <AbsoluteConstraints x="20" y="200" width="600" height="40"/>
+          <AbsoluteConstraints x="20" y="180" width="600" height="70"/>
         </Constraint>
       </Constraints>
     </Component>
diff --git a/apps/desktopgui/src/gui/SpeedSelector3.java b/apps/desktopgui/src/gui/SpeedSelector3.java
index 8115acb2bc3b8a1cfe4549942f1d2249a95e5476..1f523befda0448ae38a6f64d2ad316afb9a1163e 100644
--- a/apps/desktopgui/src/gui/SpeedSelector3.java
+++ b/apps/desktopgui/src/gui/SpeedSelector3.java
@@ -122,12 +122,12 @@ public class SpeedSelector3 extends javax.swing.JFrame {
         uploadUsageLabel.setText(resourceMap.getString("uploadUsageLabel.text")); // NOI18N
         uploadUsageLabel.setName("uploadUsageLabel"); // NOI18N
         getContentPane().add(uploadUsageLabel);
-        uploadUsageLabel.setBounds(20, 150, 141, 30);
+        uploadUsageLabel.setBounds(20, 150, 19, 30);
 
         downloadUsageLabel.setText(resourceMap.getString("downloadUsageLabel.text")); // NOI18N
         downloadUsageLabel.setName("downloadUsageLabel"); // NOI18N
         getContentPane().add(downloadUsageLabel);
-        downloadUsageLabel.setBounds(340, 150, 162, 30);
+        downloadUsageLabel.setBounds(340, 150, 19, 30);
 
         uploadField.setText(resourceMap.getString("uploadField.text")); // NOI18N
         uploadField.setMinimumSize(new java.awt.Dimension(77, 27));
@@ -236,7 +236,7 @@ public class SpeedSelector3 extends javax.swing.JFrame {
         explanation.setText(resourceMap.getString("explanation.text")); // NOI18N
         explanation.setName("explanation"); // NOI18N
         getContentPane().add(explanation);
-        explanation.setBounds(20, 200, 600, 40);
+        explanation.setBounds(20, 180, 600, 70);
 
         pack();
     }// </editor-fold>//GEN-END:initComponents
diff --git a/apps/desktopgui/src/gui/Tray.java b/apps/desktopgui/src/gui/Tray.java
index bf3cd28c87a80652ff007debcc2b8f3790d27fd7..5a8da78db9480eba8dcd68c9c96279a2cd31ff64 100644
--- a/apps/desktopgui/src/gui/Tray.java
+++ b/apps/desktopgui/src/gui/Tray.java
@@ -9,9 +9,6 @@ import desktopgui.*;
 import java.awt.AWTException;
 import java.awt.Desktop;
 import java.awt.Image;
-import java.awt.MenuItem;
-import java.awt.Menu;
-import java.awt.PopupMenu;
 import java.awt.SystemTray;
 import java.awt.Toolkit;
 import java.awt.TrayIcon;
@@ -23,8 +20,12 @@ import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.logging.Level;
 import java.util.logging.Logger;
+import javax.swing.JMenu;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
 import router.RouterHandler;
 import router.RouterHelper;
+import router.configuration.PeerHelper;
 
 /**
  *
@@ -41,12 +42,13 @@ public class Tray {
 
         Image image = Toolkit.getDefaultToolkit().getImage("desktopgui/resources/logo/logo.jpg");
 
-        PopupMenu popup = new PopupMenu();
+        final JPopupMenu popup = new JPopupMenu();
 
         //Create menu items to put in the popup menu
-        MenuItem browserLauncher = new MenuItem("Launch browser");
+        JMenuItem browserLauncher = new JMenuItem("Launch browser");
         browserLauncher.addActionListener(new ActionListener() {
 
+            @Override
             public void actionPerformed(ActionEvent arg0) {
                 if(Desktop.isDesktopSupported()) {
                     Desktop desktop = Desktop.getDesktop();
@@ -66,9 +68,10 @@ public class Tray {
             }
 
         });
-        MenuItem howto = new MenuItem("How to use I2P");
+        JMenuItem howto = new JMenuItem("How to use I2P");
         howto.addActionListener(new ActionListener() {
 
+            @Override
             public void actionPerformed(ActionEvent arg0) {
                 if(Desktop.isDesktopSupported()) {
                     Desktop desktop = Desktop.getDesktop();
@@ -84,18 +87,20 @@ public class Tray {
             }
             
         });
-        Menu config = new Menu("Configuration");
-        MenuItem speedConfig = new MenuItem("Speed");
+        JMenu config = new JMenu("Configuration");
+        JMenuItem speedConfig = new JMenuItem("Speed");
         speedConfig.addActionListener(new ActionListener() {
 
+            @Override
             public void actionPerformed(ActionEvent arg0) {
                 (new SpeedSelector()).setVisible(true);
             }
             
         });
-        MenuItem advancedConfig = new MenuItem("Advanced Configuration");
+        JMenuItem advancedConfig = new JMenuItem("Advanced Configuration");
         advancedConfig.addActionListener(new ActionListener() {
 
+            @Override
             public void actionPerformed(ActionEvent arg0) {
                 if(Desktop.isDesktopSupported()) {
                     Desktop desktop = Desktop.getDesktop();
@@ -110,7 +115,7 @@ public class Tray {
             }
 
         });
-        MenuItem viewLog = new MenuItem("View log");
+        JMenuItem viewLog = new JMenuItem("View log");
         viewLog.addActionListener(new ActionListener() {
 
             @Override
@@ -119,17 +124,21 @@ public class Tray {
             }
             
         });
-        MenuItem shutdown = new MenuItem("Shutdown I2P");
+        JMenuItem shutdown = new JMenuItem("Shutdown I2P");
         shutdown.addActionListener(new ActionListener() {
 
+            @Override
             public void actionPerformed(ActionEvent arg0) {
                 RouterHandler.setStatus(RouterHandler.SHUTDOWN_GRACEFULLY);
                 long shutdownTime = RouterHelper.getGracefulShutdownTimeRemaining();
                 System.out.println(shutdownTime);
-                if(shutdownTime>0)
-                    trayIcon.displayMessage("Shutting down...", "Shutdown time remaining: " + shutdownTime/1000 + " seconds.", TrayIcon.MessageType.INFO);
-                else
+                if(shutdownTime>0) {
+                    trayIcon.displayMessage("Shutting down...", "Shutdown time remaining: " + shutdownTime/1000 + " seconds."
+                            + System.getProperty("line.separator") + "Shutdown will not happen immediately, because we are still participating in the network.", TrayIcon.MessageType.INFO);
+                }
+                else {
                     trayIcon.displayMessage("Shutting down...", "Shutting down immediately.", TrayIcon.MessageType.INFO);
+                }
             }
 
         });
@@ -147,7 +156,31 @@ public class Tray {
         popup.add(shutdown);
 
         //Add tray icon
-        trayIcon = new TrayIcon(image, "I2P: the anonymous network", popup);
+        trayIcon = new JPopupTrayIcon(image, "I2P: the anonymous network", popup);
+        PeerHelper.addReachabilityListener(new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                trayIcon.setToolTip("I2P Network status: " + PeerHelper.getReachability());
+            }
+            
+        });
+        PeerHelper.addActivePeerListener(new ActionListener() {
+
+            @Override
+            public void actionPerformed(ActionEvent arg0) {
+                int activePeers = PeerHelper.getActivePeers();
+                if(activePeers == 0)
+                    trayIcon.setImage(Toolkit.getDefaultToolkit().getImage("desktopgui/resources/logo/logo_red.jpg"));
+                else if(activePeers < 10)
+                    trayIcon.setImage(Toolkit.getDefaultToolkit().getImage("desktopgui/resources/logo/logo_orange.jpg"));
+                else
+                    trayIcon.setImage(Toolkit.getDefaultToolkit().getImage("desktopgui/resources/logo/logo_green.jpg"));
+                
+            }
+            
+        });
+        
         try {
             tray.add(trayIcon);
         } catch (AWTException ex) {
@@ -156,6 +189,6 @@ public class Tray {
     }
     
     private SystemTray tray = null;
-    private TrayIcon trayIcon = null;
+    private JPopupTrayIcon trayIcon = null;
     
 }
diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector.properties b/apps/desktopgui/src/gui/resources/SpeedSelector.properties
index 03b04286f6e5838b98cb6c68b0a98ace8e295e4a..00eb6c973db4796bd1dc942a21e542398244d456 100644
--- a/apps/desktopgui/src/gui/resources/SpeedSelector.properties
+++ b/apps/desktopgui/src/gui/resources/SpeedSelector.properties
@@ -3,4 +3,4 @@ Form.title=I2P Speed Configuration
 nextButton.text=Next
 uploadLabel.text=What is your maximum upload speed?
 downloadLabel.text=What is your maximum download speed?
-speedExplanation.text=Explanation about speeds...
+speedExplanation.text=<html>The maximum speed is set by your provider. It can be given in <b>kilobit (kbps)</b> or <b>kilobyte (kBps)</b>.<br />One kilobyte equals eight kilobit.</html>
diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector2.properties b/apps/desktopgui/src/gui/resources/SpeedSelector2.properties
index 54424ed0515479b7c2a13cb92ec1bf8fe7c48f6e..909518ada2f2c92286a3ad909f4971148a8ad494 100644
--- a/apps/desktopgui/src/gui/resources/SpeedSelector2.properties
+++ b/apps/desktopgui/src/gui/resources/SpeedSelector2.properties
@@ -6,4 +6,4 @@ downloadButton.text=Downloading: I want to use I2P for downloads and filesharing
 nextButton.text=Next
 browseButton.actionCommand=Browsing
 downloadButton.actionCommand=Downloading
-jLabel1.text=Text explaining ...
+jLabel1.text=<html>I2P can be used for many different purposes. Here, we present two possible descriptions. If you use a lot of bandwidth in I2P (for example using downloading), please check the <b>downloading</b> option. If your bandwidth usage is limited, please check the <b>browsing</b> option.</html>
diff --git a/apps/desktopgui/src/gui/resources/SpeedSelector3.properties b/apps/desktopgui/src/gui/resources/SpeedSelector3.properties
index 9d0718f8db2c5365b9adf586f416d546d8ccbac8..6dca3ca51603dd9a6667aea2588bda0812aecd5f 100644
--- a/apps/desktopgui/src/gui/resources/SpeedSelector3.properties
+++ b/apps/desktopgui/src/gui/resources/SpeedSelector3.properties
@@ -14,4 +14,4 @@ downloadBurstField.text=jTextField5
 uploadMonth.text=jTextField1
 downloadMonth.text=jTextField2
 settingsInfo.text=The profile information your entered, indicates that these are your optimal settings:
-explanation.text=Text explaining ...
+explanation.text=<html>We give a suggested upload and download speed. If your provider imposes a monthly bandwidth limit (usually given in <b>gigabyte (GB)</b>), please enter a value lower than that limit. If you run I2P only 50% of the time, you can double the bandwidth limit to use the same amount as when you are online 100% of the time.</html>
diff --git a/apps/desktopgui/src/router/configuration/PeerHelper.java b/apps/desktopgui/src/router/configuration/PeerHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..2272456f8d893926f4004c9c7f74c4a3514d2198
--- /dev/null
+++ b/apps/desktopgui/src/router/configuration/PeerHelper.java
@@ -0,0 +1,165 @@
+package router.configuration;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+import java.util.TimerTask;
+import net.i2p.data.RouterAddress;
+import net.i2p.router.CommSystemFacade;
+import net.i2p.router.RouterContext;
+import net.i2p.router.networkdb.kademlia.FloodfillNetworkDatabaseFacade;
+import net.i2p.router.transport.ntcp.NTCPAddress;
+import router.RouterHelper;
+
+/**
+ * Part of the code imported and adapted from the I2P Router Console (which is licensed as public domain)
+ */
+public class PeerHelper {
+    public static String getReachability() {
+        RouterContext context = RouterHelper.getContext();
+        if (context.router().getUptime() > 60*1000
+                && (!context.router().gracefulShutdownInProgress())
+                && !context.clientManager().isAlive())
+            return "ERROR: Client Manager I2CP Error - check logs";  // not a router problem but the user should know
+        if (!context.clock().getUpdatedSuccessfully())
+            return "ERROR: ClockSkew";
+        if (context.router().isHidden())
+            return "Hidden";
+
+        int status = context.commSystem().getReachabilityStatus();
+        switch (status) {
+            case CommSystemFacade.STATUS_OK:
+                RouterAddress ra = context.router().getRouterInfo().getTargetAddress("NTCP");
+                if (ra == null || (new NTCPAddress(ra)).isPubliclyRoutable())
+                    return "OK";
+                return "ERROR: Private TCP Address";
+            case CommSystemFacade.STATUS_DIFFERENT:
+                return "ERROR: You are behind a symmetric NAT.";
+            case CommSystemFacade.STATUS_REJECT_UNSOLICITED:
+                if (context.router().getRouterInfo().getTargetAddress("NTCP") != null)
+                    return "WARNING: You are behind a firewall and have Inbound TCP Enabled";
+                if (((FloodfillNetworkDatabaseFacade)context.netDb()).floodfillEnabled())
+                    return "WARNING: You are behind a firewall and are a floodfill router";
+                if (context.router().getRouterInfo().getCapabilities().indexOf('O') >= 0)
+                    return "WARNING: You are behind a firewall and are a fast router";
+                return "Firewalled";
+            case CommSystemFacade.STATUS_HOSED:
+                return "ERROR: The UDP port is already in use. Set i2np.udp.internalPort=xxxx to a different value in the advanced config and restart";
+            case CommSystemFacade.STATUS_UNKNOWN: // fallthrough
+            default:
+                ra = context.router().getRouterInfo().getTargetAddress("UDP");
+                if (ra == null && context.router().getUptime() > 5*60*1000) {
+                    if (context.getProperty(PROP_I2NP_NTCP_HOSTNAME) == null ||
+                        context.getProperty(PROP_I2NP_NTCP_PORT) == null)
+                        return "ERROR: UDP is disabled and the inbound TCP host/port combination is not set";
+                    else
+                        return "WARNING: You are behind a firewall and have UDP Disabled";
+                }
+                return "Testing";
+        }
+    }
+    
+    /**
+     * How many peers we are talking to now
+     *
+     */
+    public static int getActivePeers() {
+        RouterContext context = RouterHelper.getContext();
+        if (context == null) 
+            return 0;
+        else
+            return context.commSystem().countActivePeers();
+    }
+    
+    public static void addActivePeerListener(ActionListener listener) {
+        synchronized(activePeerListeners) {
+            activePeerListeners.add(listener);
+            if(activePeerTimer == null) {
+                activePeerTimer = new Timer();
+                TimerTask t = new TimerTask() {
+                    private int activePeers = 0;
+
+                    @Override
+                    public void run() {
+                        int newActivePeers = getActivePeers();
+                        if(!(activePeers == newActivePeers)) {
+                            synchronized(activePeerListeners) {
+                                for(int i=0; i<activePeerListeners.size(); i++) {
+                                    activePeerListeners.get(i).actionPerformed(new ActionEvent(this, 0, ""));
+                                }
+                            }
+                            activePeers = newActivePeers;
+                        }
+                    }
+                };
+                activePeerTimer.schedule(t, 60*1000);
+            }
+        }
+    }
+    
+    public static void removeActivePeerListener(ActionListener listener) {
+        synchronized(activePeerListeners) {
+            activePeerListeners.remove(listener);
+            if(activePeerListeners.size() == 0) {
+                activePeerTimer.cancel();
+                activePeerTimer = null;
+            }
+        }
+    }
+    
+    
+    
+    public static void addReachabilityListener(ActionListener listener) {
+        synchronized(reachabilityListeners) {
+            reachabilityListeners.add(listener);
+            if(reachabilityTimer == null) {
+                reachabilityTimer = new Timer();
+                TimerTask t = new TimerTask() {
+                    
+                    private String reachability = "";
+
+                    @Override
+                    public void run() {
+                        String newReachability = getReachability();
+                        if(!reachability.equals(newReachability)) {
+                            synchronized(reachabilityListeners) {
+                                for(int i=0; i<reachabilityListeners.size(); i++) {
+                                    reachabilityListeners.get(i).actionPerformed(new ActionEvent(this, 0, ""));
+                                }
+                            }
+                            reachability = newReachability;
+                        }
+                    }
+                    
+                };
+                reachabilityTimer.schedule(t, 60*1000);
+            }
+        }
+    }
+    
+    public static void removeReachabilityListener(ActionListener listener) {
+        synchronized(reachabilityListeners) {
+            reachabilityListeners.remove(listener);
+            if(reachabilityListeners.size() == 0) {
+                reachabilityTimer.cancel();
+                reachabilityTimer = null;
+            }
+        }
+    }
+    
+    private static List<ActionListener> reachabilityListeners = new ArrayList<ActionListener>();
+    private static Timer reachabilityTimer = null;
+    
+    private static List<ActionListener> activePeerListeners = new ArrayList<ActionListener>();
+    private static Timer activePeerTimer = null;
+    
+    /** copied from various private components */
+    public final static String PROP_I2NP_UDP_PORT = "i2np.udp.port";
+    public final static String PROP_I2NP_INTERNAL_UDP_PORT = "i2np.udp.internalPort";
+    public final static String PROP_I2NP_NTCP_HOSTNAME = "i2np.ntcp.hostname";
+    public final static String PROP_I2NP_NTCP_PORT = "i2np.ntcp.port";
+    public final static String PROP_I2NP_NTCP_AUTO_PORT = "i2np.ntcp.autoip";
+    public final static String PROP_I2NP_NTCP_AUTO_IP = "i2np.ntcp.autoport";
+}