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"; +}