Author: jflesch
Date: 2008-02-20 18:16:22 +0000 (Wed, 20 Feb 2008)
New Revision: 18084

Added:
   trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraph.java
   trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraphPanel.java
   trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotGraphNode.java
Modified:
   trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java
   trunk/apps/Thaw/src/thaw/gui/CheckBox.java
   trunk/apps/Thaw/src/thaw/gui/GUIHelper.java
   trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties
   trunk/apps/Thaw/src/thaw/i18n/thaw.properties
   trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
   trunk/apps/Thaw/src/thaw/plugins/TransferLogs.java
   trunk/apps/Thaw/src/thaw/plugins/WebOfTrustViewer.java
   trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java
   trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java
   trunk/apps/Thaw/src/thaw/plugins/signatures/IdentityTable.java
   trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustTab.java
   trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentity.java
   trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentityList.java
Log:
Web of trust : add a more visual way of seeing the web of trust

Modified: trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java
===================================================================
--- trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java      2008-02-20 15:37:37 UTC 
(rev 18083)
+++ trunk/apps/Thaw/src/thaw/fcp/FCPClientPut.java      2008-02-20 18:16:22 UTC 
(rev 18084)
@@ -425,7 +425,7 @@
                        return true;
                } else {
                        setStatus(false, true, false);
-
+                       Logger.warning(this, "Unable to send the file to the 
node");
                        status = "Unable to send the file to the node";

                        notifyChange();
@@ -658,7 +658,7 @@
                        if ("PutFailed".equals( msg.getMessageName() )) {
                                setStatus(false, true, false);
                                fatal = true;
-
+                               
                                putFailedCode = 
Integer.parseInt(msg.getValue("Code"));

                                status = "Failed 
("+msg.getValue("CodeDescription")+")";
@@ -688,6 +688,7 @@
                                        
queueManager.getQueryManager().getConnection().removeFromWriterQueue();
                                }

+                               Logger.warning(this, "Protocol error ! : 
"+msg.getValue("CodeDescription"));
                                status = "Protocol error 
("+msg.getValue("CodeDescription")+")";

                                if((msg.getValue("Fatal") != null) &&

Modified: trunk/apps/Thaw/src/thaw/gui/CheckBox.java
===================================================================
--- trunk/apps/Thaw/src/thaw/gui/CheckBox.java  2008-02-20 15:37:37 UTC (rev 
18083)
+++ trunk/apps/Thaw/src/thaw/gui/CheckBox.java  2008-02-20 18:16:22 UTC (rev 
18084)
@@ -6,11 +6,11 @@

 import thaw.core.Config;

-
+/**
+ * Memorize the checkbox status (selected or not) in the configuration
+ * @author jflesch
+ */
 public class CheckBox extends JCheckBox implements ActionListener {
-       /**
-        * 
-        */
        private static final long serialVersionUID = -7815009734483702831L;

        public final static String PREFIX = "checkbox_";

Modified: trunk/apps/Thaw/src/thaw/gui/GUIHelper.java
===================================================================
--- trunk/apps/Thaw/src/thaw/gui/GUIHelper.java 2008-02-20 15:37:37 UTC (rev 
18083)
+++ trunk/apps/Thaw/src/thaw/gui/GUIHelper.java 2008-02-20 18:16:22 UTC (rev 
18084)
@@ -1,5 +1,7 @@
 package thaw.gui;

+import java.awt.Graphics;
+import java.awt.geom.*;
 import java.awt.Toolkit;
 import java.awt.datatransfer.Clipboard;
 import java.awt.datatransfer.StringSelection;
@@ -116,4 +118,30 @@

                return ((new Long(gb)).toString() +" GB");
        }
+       
+       
+       public final static int ARROW_SIZE = 15;
+       public final static double ARROW_ANGLE = Math.PI / 6; /* 30?? */
+       
+       private static void paintLine(Graphics g, int headX, int headY, int 
lng, double angle) {
+               int endX = (int)(headX + (Math.cos(angle)*lng));
+               int endY = (int)(headY + (Math.sin(angle)*lng));
+               
+               g.drawLine(headX, headY, endX, endY);
+       }
+       
+       /* paint an arrow */
+       public static void paintArrow(Graphics g, int headX, int headY, int 
endX, int endY) {
+               g.drawLine(headX, headY, endX, endY);
+               
+               double dist = new Point2D.Double(headX, headY).distance(endX, 
endY);
+               
+               double theta = Math.acos((endX-headX) / dist);
+               
+               if ((endY-headY) < 0)
+                       theta = -1 * theta;
+
+               paintLine(g, headX, headY, ARROW_SIZE, theta+ARROW_ANGLE);
+               paintLine(g, headX, headY, ARROW_SIZE, theta-ARROW_ANGLE);
+       }
 }

Modified: trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties     2008-02-20 
15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties     2008-02-20 
18:16:22 UTC (rev 18084)
@@ -733,6 +733,8 @@
 thaw.plugin.wot.itsTrustLevel=Niveau de confiance de l'utilisateur
 thaw.plugin.wot.yourTrustLevel=Votre niveau de confiance
 thaw.plugin.wot.wotTrustLevel=Niveau de confiance calcul?? par le WoT
+thaw.plugin.wot.seeGraph=Voir la toile de confiance
+thaw.plugin.wot.seeTrustList=Voir la liste de confiance

 ## node configurator


Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2008-02-20 15:37:37 UTC 
(rev 18083)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2008-02-20 18:16:22 UTC 
(rev 18084)
@@ -740,6 +740,8 @@
 thaw.plugin.wot.itsTrustLevel=User's trust level
 thaw.plugin.wot.yourTrustLevel=Your trust level
 thaw.plugin.wot.wotTrustLevel=Computed trust level
+thaw.plugin.wot.seeGraph=See WoT graph
+thaw.plugin.wot.seeTrustList=See trust list

 ##?Node configurator


Modified: trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties    2008-02-20 15:37:37 UTC 
(rev 18083)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties    2008-02-20 18:16:22 UTC 
(rev 18084)
@@ -722,6 +722,7 @@

 ## Web of Trust
 thaw.plugin.wot=Toile de confiance
+thaw.plugin.wot.viewer=Visionneur de toile de confiance
 thaw.plugin.wot.activated=Activer la toile de confiance
 thaw.plugin.wot.usedIdentity=Identit\u00e9 utilis\u00e9e pour publier la liste 
de confiances
 thaw.plugin.wot.usedIdentity.none=[Ne pas publier la liste de confiance]
@@ -732,6 +733,8 @@
 thaw.plugin.wot.itsTrustLevel=Niveau de confiance de l'utilisateur
 thaw.plugin.wot.yourTrustLevel=Votre niveau de confiance
 thaw.plugin.wot.wotTrustLevel=Niveau de confiance calcul\u00e9 par le WoT
+thaw.plugin.wot.seeGraph=Voir la toile de confiance
+thaw.plugin.wot.seeTrustList=Voir la liste de confiance

 ## node configurator


Modified: trunk/apps/Thaw/src/thaw/plugins/TransferLogs.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/TransferLogs.java  2008-02-20 15:37:37 UTC 
(rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/TransferLogs.java  2008-02-20 18:16:22 UTC 
(rev 18084)
@@ -241,6 +241,9 @@


        protected void notifyAddition(FCPTransferQuery query) {
+               if (!query.isPersistent())
+                       return;
+               
                new Transfer(db, query, table);
                table.refresh();
        }

Modified: trunk/apps/Thaw/src/thaw/plugins/WebOfTrustViewer.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/WebOfTrustViewer.java      2008-02-20 
15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/WebOfTrustViewer.java      2008-02-20 
18:16:22 UTC (rev 18084)
@@ -30,6 +30,8 @@

        public boolean run(Core core) {
                this.core = core;
+               
+               core.getConfig().addListener("wotIdentityUsed", this);

                /* Hsqldb */
                if(core.getPluginManager().getPlugin("thaw.plugins.Hsqldb") == 
null) {

Modified: trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java    
2008-02-20 15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java    
2008-02-20 18:16:22 UTC (rev 18084)
@@ -15,10 +15,6 @@


 public class GraphPanel extends JComponent implements MouseListener {
-
-       /**
-        * 
-        */
        private static final long serialVersionUID = 5478870004197620690L;

        public final static int BORDER = 50;

Modified: trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java  2008-02-20 
15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java  2008-02-20 
18:16:22 UTC (rev 18084)
@@ -6,7 +6,9 @@
 import java.awt.Graphics;
 import java.awt.Color;

+import thaw.gui.GUIHelper;

+
 public class Node implements Comparable {

        public final static int RADIUS = 4;
@@ -336,7 +338,9 @@
                                g.setColor(Color.PINK);
                        }

-                       g.drawLine(realX+zeroX, realY+zeroY, targetX+zeroX, 
targetY+zeroY);
+                       //g.drawLine(realX+zeroX, realY+zeroY, targetX+zeroX, 
targetY+zeroY);
+                       GUIHelper.paintArrow(g, targetX+zeroX, targetY+zeroY,
+                                                               realX+zeroX, 
realY+zeroY);

                        if (target.isSelected())
                                g.setColor(Color.GRAY);

Modified: trunk/apps/Thaw/src/thaw/plugins/signatures/IdentityTable.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/signatures/IdentityTable.java      
2008-02-20 15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/signatures/IdentityTable.java      
2008-02-20 18:16:22 UTC (rev 18084)
@@ -1,5 +1,7 @@
 package thaw.plugins.signatures;

+import java.awt.event.KeyEvent;
+import java.awt.event.KeyListener;
 import java.awt.event.MouseEvent;
 import java.awt.event.MouseListener;
 import java.util.Observable;
@@ -12,7 +14,7 @@
 import thaw.core.I18n;
 import thaw.gui.Table;

-public class IdentityTable extends Observable implements MouseListener {
+public class IdentityTable extends Observable implements MouseListener, 
KeyListener {
        private static final long serialVersionUID = -6972180330110075151L;

        private thaw.gui.Table table;
@@ -26,6 +28,7 @@
                table.setDefaultRenderer(table.getColumnClass(0), renderer = 
new IdentityRenderer(model));
                table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
                table.addMouseListener(this);
+               table.addKeyListener(this);
        }

        public void setModel(IdentityModel model) {
@@ -175,5 +178,19 @@
        public void mouseReleased(MouseEvent arg0) {
        }

+       public void keyPressed(KeyEvent arg0) {
+               // TODO Raccord de m??thode auto-g??n??r??
+               
+       }

+       public void keyReleased(KeyEvent arg0) {
+               setChanged();
+               notifyObservers(model.getIdentity(table.getSelectedRow()));
+       }
+
+       public void keyTyped(KeyEvent arg0) {
+               
+       }
+
+
 }

Added: trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraph.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraph.java            
                (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraph.java    
2008-02-20 18:16:22 UTC (rev 18084)
@@ -0,0 +1,222 @@
+package thaw.plugins.webOfTrust;
+
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.geom.Point2D;
+import java.util.Hashtable;
+import java.util.Iterator;
+
+import javax.swing.JComponent;
+import javax.swing.JScrollPane;
+
+import thaw.plugins.Hsqldb;
+import thaw.plugins.signatures.Identity;
+
+public class WebOfTrustGraph extends JComponent implements MouseListener {
+       public final static int BORDER = 40;
+       
+       private static final long serialVersionUID = 7654372155349615901L;
+       
+       private JScrollPane myScrollPane;
+       
+       private boolean visible;
+       
+       private Hashtable nodes;
+       private WotGraphNode center;
+       private WotGraphNode selectedNode;
+
+       
+       private float zoom = 1;
+       private int minX = 0;
+       private int maxX = 1;
+       private int minY = 0;
+       private int maxY = 1;
+       private int zeroX = 200;
+       private int zeroY = 200;
+       
+
+       public WebOfTrustGraph(Hsqldb db) {
+               nodes = new Hashtable();
+               
+               visible = false;
+               
+               addMouseListener(this);
+       }
+
+       public void setScrollPane(JScrollPane pane) {
+               this.myScrollPane = pane;
+       }
+
+       public void redraw(Identity c) {
+               this.center = new WotGraphNode(this, new WotIdentity(c));
+               
+               if (!visible)
+                       return;
+
+               nodes = new Hashtable();
+               
+               this.center.setPosition(0, 0);
+               this.center.generateNeighbours();
+               this.center.optimizePositions();
+               addNode(this.center);
+               
+               if (myScrollPane != null)
+                       myScrollPane.revalidate();
+               
+               computeMinMax();
+               computeOptimalZoom();
+               recomputeSize();
+
+               repaint();
+       }
+       
+       private void computeMinMax() {
+               minX = 0;
+               minY = 0;
+               maxX = 1;
+               maxY = 1;
+               
+               synchronized(nodes) {
+                       for (Iterator it = nodes.values().iterator() ; 
it.hasNext() ; ) {
+                               WotGraphNode n = (WotGraphNode)it.next();
+                               
+                               if (n.getX() < minX) minX = n.getX();
+                               if (n.getX() > maxX) maxX = n.getX();
+                               if (n.getY() < minY) minY = n.getY();
+                               if (n.getY() > maxY) maxY = n.getY();
+                       }
+               }
+       }
+       
+       private void recomputeSize() {
+               Dimension dim = new Dimension((int)((maxX - minX) * zoom) + 
(2*BORDER),
+                               (int)((maxY - minY) * zoom) + (2*BORDER));
+
+               this.setPreferredSize(dim);
+               this.setSize((int)((maxX - minX) * zoom) + (2*BORDER),
+                               (int)((maxY - minY) * zoom) + (2*BORDER));
+               myScrollPane.revalidate();
+       }
+       
+       public void computeOptimalZoom() {
+               Dimension size = myScrollPane.getSize();
+               double zoomX = (size.getWidth()-(2*BORDER)) / (maxX - minX);
+               double zoomY = (size.getHeight()-(2*BORDER)) / (maxY - minY);
+
+               zoom = (float)(((zoomX > zoomY) ? zoomY : zoomX));
+               
+               if (zoom == 0)
+                       zoom = 1;
+               
+               recomputeZero();
+       }
+       
+       private void recomputeZero() {
+               zeroX = (-1 * (int)(minX * zoom)) + BORDER;
+               zeroY = (-1 * (int)(minY * zoom)) + BORDER;
+       }
+       
+       public float getZoom() {
+               return zoom;
+       }
+       
+       public void setZoom(float z) {
+               this.zoom = z;
+               recomputeSize();
+               recomputeZero();
+               repaint();              
+       }
+       
+       public WotGraphNode getNode(String publicKey) {
+               synchronized(nodes) {
+                       return (WotGraphNode)nodes.get(publicKey);
+               }
+       }
+       
+       public WotGraphNode getNearestNode(int x, int y) {
+               WotGraphNode selected = null;
+               float lastDist = 999999999;
+               
+               synchronized(nodes) {
+                       for (Iterator it = nodes.values().iterator() ; 
it.hasNext() ; ) {
+                               WotGraphNode n = (WotGraphNode)it.next();
+                               float dist = (float)new Point2D.Float(n.getX(), 
n.getY()).distance(x, y);
+                               
+                               if (dist < lastDist) {
+                                       selected = n;
+                                       lastDist = dist;
+                               }
+                       }
+               }
+               
+               return selected;
+       }
+       
+       public void addNode(WotGraphNode node) {
+               synchronized(nodes) {
+                       nodes.put(node.getIdentity().getPublicKey(), node);
+               }
+       }
+       
+       public void paintComponent(Graphics g) {
+               /* background */
+               Dimension d = getSize();
+               g.setColor(java.awt.Color.WHITE);
+               g.fillRect(0, 0, (int)d.getWidth(), (int)d.getHeight());
+               
+               synchronized(nodes) {
+                       for (Iterator it = nodes.values().iterator() ; 
it.hasNext() ; ) {
+                               ((WotGraphNode)it.next()).paintLinks(g, zoom, 
zeroX, zeroY);
+                       }
+                       
+                       for (Iterator it = nodes.values().iterator() ; 
it.hasNext() ; ) {
+                               ((WotGraphNode)it.next()).paintNode(g, zoom, 
zeroX, zeroY);
+                       }
+               }
+       }
+
+       public void mouseClicked(MouseEvent e) {
+               int x = (int)((e.getX() - zeroX) / zoom);
+               int y = (int)((e.getY() - zeroY) / zoom);
+               
+               WotGraphNode node = getNearestNode(x, y);
+               
+               synchronized(nodes) {
+                       for (Iterator it = nodes.values().iterator() ; 
it.hasNext() ; ) {
+                               WotGraphNode n = (WotGraphNode)it.next();
+                               n.setSelected(n == node);
+                       }
+               }
+               
+               selectedNode = node;
+               
+               repaint();
+       }
+
+       public void mouseEntered(MouseEvent arg0) {     }
+
+       public void mouseExited(MouseEvent arg0) { }
+
+       public void mousePressed(MouseEvent arg0) {
+               mouseClicked(arg0);
+       }
+
+       public void mouseReleased(MouseEvent e) {
+               int x = (int)((e.getX() - zeroX) / zoom);
+               int y = (int)((e.getY() - zeroY) / zoom);
+
+               selectedNode.setPosition(x, y);
+               repaint();
+       }
+       
+       public void setVisible(boolean v) {
+               visible = v;
+               
+               if (v && center != null) {
+                       myScrollPane.revalidate();
+                       redraw(center.getIdentity());
+               }
+       }
+}

Added: trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraphPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraphPanel.java       
                        (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustGraphPanel.java       
2008-02-20 18:16:22 UTC (rev 18084)
@@ -0,0 +1,70 @@
+package thaw.plugins.webOfTrust;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+
+import javax.swing.JButton;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import thaw.core.I18n;
+import thaw.plugins.Hsqldb;
+import thaw.plugins.signatures.Identity;
+
+public class WebOfTrustGraphPanel implements ActionListener {
+       private JPanel panel;
+       
+       private WebOfTrustGraph graph;
+       private JScrollPane sp;
+       
+       private JButton zoomMore;
+       private JButton zoomLess;
+       
+       public WebOfTrustGraphPanel(Hsqldb db) {
+               graph = new WebOfTrustGraph(db);
+               sp = new JScrollPane(graph);
+               sp.getVerticalScrollBar().setUnitIncrement(15);
+               graph.setScrollPane(sp);
+
+               JPanel buttonPanel = new JPanel(new GridLayout(1, 2));
+               zoomMore = new JButton("+");
+               zoomMore.addActionListener(this);
+               buttonPanel.add(zoomMore);
+               zoomLess = new JButton("-");
+               zoomLess.addActionListener(this);
+               buttonPanel.add(zoomLess);
+               
+               JPanel northPanel = new JPanel(new BorderLayout());
+               
+               northPanel.add(new JLabel(I18n.getMessage("thaw.plugin.wot")), 
BorderLayout.WEST);
+               northPanel.add(new JLabel(""), BorderLayout.CENTER);
+               northPanel.add(buttonPanel, BorderLayout.EAST);
+
+               panel = new JPanel(new BorderLayout(5, 5));
+               panel.add(northPanel, BorderLayout.NORTH);
+               panel.add(sp, BorderLayout.CENTER);
+       }
+       
+       public void refresh(Identity i) {
+               graph.redraw(i);
+       }
+       
+       public void setVisible(boolean v) {
+               graph.setVisible(v);
+       }
+       
+       public JPanel getPanel() {
+               return panel;           
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               if (e.getSource() == zoomMore) {
+                       graph.setZoom(graph.getZoom()*2);
+               } else if (e.getSource() == zoomLess) {
+                       graph.setZoom(graph.getZoom()/2);
+               }
+       }
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustTab.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustTab.java      
2008-02-20 15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WebOfTrustTab.java      
2008-02-20 18:16:22 UTC (rev 18084)
@@ -2,9 +2,12 @@

 import java.awt.BorderLayout;
 import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.Observable;
 import java.util.Observer;

+import javax.swing.JButton;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JScrollPane;
@@ -17,16 +20,21 @@
 import thaw.plugins.signatures.Identity;


-public class WebOfTrustTab implements Signatures.SignaturesObserver, Observer {
+public class WebOfTrustTab implements Signatures.SignaturesObserver, Observer, 
ActionListener {

        private Config config;

        private JSplitPane mainSplit;
        private JPanel rightPanel;
+       private JPanel subRightPanel;
        private JPanel itsTrustListPanel;

        private WotIdentityList idList;
+       
+       private JButton switchButton;
+       private boolean trustListDisplayed = true;
        private TrustListTable trustListTable;
+       private WebOfTrustGraphPanel graphPanel;

        public WebOfTrustTab(Hsqldb db, Config config) {
                this.config = config;
@@ -34,19 +42,33 @@
                JPanel leftPanel;

                leftPanel = new JPanel(new BorderLayout(5,5));
-               rightPanel = new JPanel(new GridLayout(1, 1));
+               rightPanel = new JPanel(new BorderLayout(5, 5));
                itsTrustListPanel = new JPanel(new BorderLayout(5,5));

                idList = new WotIdentityList(db, config);
                trustListTable = new TrustListTable(db, config);
+               graphPanel = new WebOfTrustGraphPanel(db);

                leftPanel.add(new 
JLabel(I18n.getMessage("thaw.plugin.wot.yourTrustList")), BorderLayout.NORTH);
                leftPanel.add(new JScrollPane(idList.getList()), 
BorderLayout.CENTER);
                itsTrustListPanel.add(new 
JLabel(I18n.getMessage("thaw.plugin.wot.itsTrustList")), BorderLayout.NORTH);
                itsTrustListPanel.add(new 
JScrollPane(trustListTable.getTable()), BorderLayout.CENTER);

-               rightPanel.add(itsTrustListPanel);
+               trustListDisplayed = true;
+               switchButton = new JButton();
+               updateSwitchButton();
+               switchButton.addActionListener(this);

+               JPanel northRight = new JPanel(new BorderLayout());
+               northRight.add(new JLabel(""), BorderLayout.CENTER);
+               northRight.add(switchButton, BorderLayout.EAST);
+               
+               subRightPanel = new JPanel(new GridLayout(1, 1));
+               subRightPanel.add(itsTrustListPanel);
+               
+               rightPanel.add(northRight, BorderLayout.NORTH);
+               rightPanel.add(subRightPanel, BorderLayout.CENTER);
+               
                mainSplit = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                                                        
leftPanel, rightPanel);

@@ -88,6 +110,40 @@
        public void update(Observable o, Object param) {
                if (o == idList) {
                        trustListTable.refresh((Identity)param);
+                       graphPanel.refresh((Identity)param);
                }
        }
+       
+       private void updateSwitchButton() {
+               if (trustListDisplayed)
+                       
switchButton.setText(I18n.getMessage("thaw.plugin.wot.seeGraph"));
+               else
+                       
switchButton.setText(I18n.getMessage("thaw.plugin.wot.seeTrustList"));
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               if (e.getSource() == switchButton) {
+                       trustListDisplayed = !trustListDisplayed;
+                       
+                       if (trustListDisplayed) {
+                               graphPanel.setVisible(false);
+                               subRightPanel.remove(graphPanel.getPanel());
+                               subRightPanel.add(itsTrustListPanel);
+                               itsTrustListPanel.revalidate();
+                               subRightPanel.revalidate();
+                               itsTrustListPanel.repaint();
+                       } else {
+                               subRightPanel.remove(itsTrustListPanel);
+                               subRightPanel.add(graphPanel.getPanel());
+                               graphPanel.getPanel().repaint();
+                               graphPanel.getPanel().revalidate();
+                               subRightPanel.revalidate();
+                               mainSplit.revalidate();
+                               graphPanel.setVisible(true);
+                               graphPanel.getPanel().repaint();
+                       }
+                       
+                       updateSwitchButton();
+               }               
+       }
 }

Added: trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotGraphNode.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotGraphNode.java               
                (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotGraphNode.java       
2008-02-20 18:16:22 UTC (rev 18084)
@@ -0,0 +1,221 @@
+package thaw.plugins.webOfTrust;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.util.Iterator;
+import java.util.Random;
+import java.util.Vector;
+
+import thaw.gui.GUIHelper;
+import thaw.plugins.signatures.Identity;
+
+public class WotGraphNode {
+       public final static int MAX_DEPTH = 50; /* just a security */
+       
+       public final static int MAX_DISTANCE = 500;
+       public final static int MIN_DISTANCE = 50;
+       
+       public final static int NODE_RADIUS = 4;
+       
+       public final static int MAX_OPTIMIZATION_CYCLES = 30;
+       
+       private WebOfTrustGraph graph;
+       private WotIdentity identity;
+       private int x = -1;
+       private int y = -1;
+       
+       private WotGraphNode[] neighbours;
+       private int[] trustLinks;
+       
+       private final static Random random = new Random();
+       
+       private boolean selected = false;
+       
+       public WotGraphNode(WebOfTrustGraph graph, WotIdentity i) {
+               this.graph = graph;
+               this.identity = i;
+               x = -1;
+               y = -1;
+       }
+       
+       public Identity getIdentity() {
+               return identity;
+       }
+       
+       public void setSelected(boolean s) {
+               this.selected = s;
+       }
+       
+       public void setPosition(int x, int y) {
+               this.x = x;
+               this.y = y;
+       }
+       
+       public int getX() {
+               return x;
+       }
+       
+       public int getY() {
+               return y;
+       }
+       
+       private int getAValueNear(int x) {
+               int diff = 
(random.nextInt(MAX_DISTANCE-MIN_DISTANCE))+MIN_DISTANCE;
+               boolean pos = random.nextBoolean();
+               
+               if (!pos)
+                       return x + (-1 * diff);
+               return x + diff;
+       }
+       
+       public void setAlmostRandomPosition(WotGraphNode parent) {
+               this.x = getAValueNear(parent.getX());
+               this.y = getAValueNear(parent.getY());
+       }
+       
+       public void generateNeighbours() {
+               generateNeighbours(0);
+       }
+       
+       public void generateNeighbours(int depth) {
+               if (depth == MAX_DEPTH)
+                       return;
+               
+               /* search neighbours */
+               Vector trustList = identity.getTrustList();
+               
+               neighbours = new WotGraphNode[trustList.size()];
+               trustLinks = new int[trustList.size()];
+               
+               int i = 0;
+               
+               for (Iterator it = trustList.iterator() ; it.hasNext() ; ) {
+                       WotIdentity.TrustLink link = 
(WotIdentity.TrustLink)it.next();
+                       neighbours[i] = new WotGraphNode(graph, 
link.getDestination());
+                       trustLinks[i] = link.getLinkTrustLevel();
+
+                       i++;
+               }
+               
+               /* synchronizing with the already existing nodes */
+               for (i = 0 ; i < neighbours.length ; i++) {
+                       WotGraphNode node = 
graph.getNode(neighbours[i].getIdentity().getPublicKey());
+                       
+                       if (node != null) {
+                               neighbours[i] = node;
+                       } else {
+                               neighbours[i].setAlmostRandomPosition(this);
+                               neighbours[i].generateNeighbours(depth+1); /* 
recursivity */
+                               graph.addNode(neighbours[i]);
+                       }
+               }
+       }
+       
+       public int nmbNeighbours() {
+               return neighbours.length;
+       }
+       
+       public int getAverageX() {
+               int sum = 0;
+               
+               for (int i = 0 ; i < neighbours.length ; i++)
+                       sum += neighbours[i].getX();
+               
+               return sum / neighbours.length;
+       }
+       
+       public int getAverageY() {
+               int sum = 0;
+               
+               for (int i = 0 ; i < neighbours.length ; i++)
+                       sum += neighbours[i].getY();
+               
+               return sum / neighbours.length;
+       }
+       
+       public void switchPosition(WotGraphNode node) {
+               int newX = node.getX();
+               int newY = node.getY();
+               
+               node.setPosition(x, y);
+               setPosition(newX, newY);
+       }
+       
+       
+       public void optimizePositions() {
+               for (int i = 0 ; i < MAX_OPTIMIZATION_CYCLES ;i++) {
+                       boolean hasMove = false;
+                       
+                       for (int j = 0; j < neighbours.length ; j++) {
+                               if (neighbours[j].nmbNeighbours() <= 0)
+                                       continue;
+                               
+                               int x = neighbours[j].getAverageX();
+                               int y = neighbours[j].getAverageY();
+                               
+                               WotGraphNode nearest = graph.getNearestNode(x, 
y);
+                               
+                               if (nearest != neighbours[j]) {
+                                       switchPosition(nearest);
+                                       hasMove = true;
+                               }
+                       }
+                       
+                       if (!hasMove)
+                               break;
+               }
+               
+               for (int j = 0; j < neighbours.length ; j++) {
+                       neighbours[j].optimizePositions();
+               }
+       }
+       
+       
+       public void paintNode(Graphics g, float zoom, int zeroX, int zeroY) {
+               int realX = (int)(x * zoom);
+               int realY = (int)(y * zoom);
+               
+               g.setColor(identity.getTrustLevelColor());
+               
+               if (selected) {
+                       g.drawOval( realX - NODE_RADIUS + zeroX,
+                                       realY - NODE_RADIUS + zeroY,
+                                       2*NODE_RADIUS,
+                                       2*NODE_RADIUS);
+               } else {
+                       g.fillOval( realX - NODE_RADIUS + zeroX,
+                                       realY - NODE_RADIUS + zeroY,
+                                       2*NODE_RADIUS,
+                                       2*NODE_RADIUS);
+               }
+
+               g.drawString(identity.toString(),
+                               realX + zeroX,
+                               realY + zeroY - 10);
+       }
+       
+       private void paintLink(Graphics g, WotGraphNode neighbour, int 
trustLink,
+                                                       int myX, int myY, 
+                                                       float zoom, int zeroX, 
int zeroY) {
+               int targetX = (int)(neighbour.getX()*zoom);
+               int targetY = (int)(neighbour.getY()*zoom);
+
+               if (trustLink < 0)
+                       g.setColor(Color.RED);
+               else if (trustLink > 0)
+                       g.setColor(Color.BLUE);
+
+               GUIHelper.paintArrow(g, targetX+zeroX, targetY+zeroY, myX, myY);
+       }
+       
+       
+       public void paintLinks(Graphics g, float zoom, int zeroX, int zeroY) {
+               int realX = (int)(x * zoom)+zeroX;
+               int realY = (int)(y * zoom)+zeroY;
+               
+               for (int i = 0 ; i < neighbours.length ; i++) {
+                       paintLink(g, neighbours[i], trustLinks[i], realX, 
realY, zoom, zeroX, zeroY);
+               }
+       }
+
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentity.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentity.java        
2008-02-20 15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentity.java        
2008-02-20 18:16:22 UTC (rev 18084)
@@ -7,6 +7,7 @@

 import java.io.File;
 import java.sql.*;
+import java.util.Iterator;
 import java.util.Vector;

 import org.xml.sax.Attributes;
@@ -356,6 +357,10 @@
                }
        }

+       public Vector getTrustList() {
+               return getTrustList(getDb(), this);
+       }
+       
        /**
         * @param db
         * @param idSrc
@@ -366,6 +371,19 @@

                WotIdentity src = new WotIdentity(idSrc);

+               if (idSrc.getPrivateKey() != null) {
+
+                       /* mode lazy bastard => on */
+                       Vector oids = getOtherWotIdentities(db);
+                       
+                       for (Iterator it = oids.iterator(); it.hasNext() ; ) {
+                               WotIdentity id = (WotIdentity)it.next();
+                               v.add(new TrustLink(db, src, id, 
id.getUserTrustLevel()));
+                       }
+
+                       return v;
+               }
+               
                try {
                        synchronized(db.dbLock) {
                                PreparedStatement st;
@@ -378,7 +396,7 @@
                                                                                
                                " signatures.trustLevel AS yourTrustLevel, "+
                                                                                
                                " wotTrustLists.trustLevel AS linkTrustLevel "+
                                                                                
"FROM wotTrustLists INNER JOIN signatures ON wotTrustLists.destination = 
signatures.id "+
-                                                                               
"WHERE source = ?");
+                                                                               
"WHERE wotTrustLists.source = ?");
                                st.setInt(1, idSrc.getId());

                                ResultSet set = st.executeQuery();
@@ -411,17 +429,23 @@
        /**
         * Returns only the identities with a trust > 0
         */
-       public static Vector getOtherIdentities(Hsqldb db) {
+       public static Vector getOtherWotIdentities(Hsqldb db) {
                Vector v = new Vector();

                try {
                        synchronized(db.dbLock) {
                                PreparedStatement st;

-                               st = 
db.getConnection().prepareStatement("SELECT id, "+
-                                                                               
                                " nickname, publicKey, "+
-                                                                               
                                " privateKey, isDup, trustLevel "+
-                                                                               
                                "FROM signatures WHERE privateKey IS NULL AND 
trustLevel >= 0");
+                               st = 
db.getConnection().prepareStatement("SELECT signatures.id AS id, "+
+                                               " signatures.nickname AS 
nickname, "+
+                                               " signatures.publicKey AS 
publicKey, "+
+                                               " signatures.privateKey AS 
privateKey, "+
+                                               " signatures.isDup AS isDup, "+
+                                               " signatures.trustLevel AS 
trustLevel "+
+                                               "FROM wotKeys INNER JOIN 
signatures ON wotKeys.sigId = signatures.id "+
+                                               "WHERE signatures.privateKey IS 
NULL "+
+                                               "AND signatures.trustLevel >= 
0");
+                               
                                ResultSet set = st.executeQuery();

                                /* TODO : Optimize if possible */

Modified: trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentityList.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentityList.java    
2008-02-20 15:37:37 UTC (rev 18083)
+++ trunk/apps/Thaw/src/thaw/plugins/webOfTrust/WotIdentityList.java    
2008-02-20 18:16:22 UTC (rev 18084)
@@ -1,30 +1,51 @@
 package thaw.plugins.webOfTrust;

+import java.util.Iterator;
 import java.util.Observable;
 import java.util.Observer;
 import java.util.Vector;

 import thaw.core.Config;
+import thaw.core.Logger;
 import thaw.gui.Table;
 import thaw.plugins.Hsqldb;
+import thaw.plugins.signatures.Identity;
 import thaw.plugins.signatures.IdentityTable;

 public class WotIdentityList extends Observable implements Observer {
        private Hsqldb db;

        private IdentityTable table;
+       private int usedIdentityId = -1;

        public WotIdentityList(Hsqldb db, Config config) {
                this.db = db;

                table = new IdentityTable(config, "wotIdList_", false);
                table.addObserver(this);
+               
+               try {
+                       if (config.getValue("wotIdentityUsed") != null)
+                               usedIdentityId = 
Integer.parseInt(config.getValue("wotIdentityUsed"));
+               } catch(Exception e) {
+                       Logger.error(this, "Error in the config : can't find 
the identity to use to upload the trust list (or its keys) => won't insert the 
trust list ; Exception throwed: "+e.toString());
+               }

                refresh();
        }

        public void refresh() {
-               Vector ids = WotIdentity.getOtherIdentities(db);
+               Vector yourIds = WotIdentity.getYourIdentities(db);
+               
+               Vector ids = new Vector();
+               
+               for (Iterator it = yourIds.iterator(); it.hasNext() ; ) {
+                       Identity i = (Identity)it.next();
+                       if (i.getId() == usedIdentityId)
+                               ids.add(i);
+               }
+               
+               ids.addAll(WotIdentity.getOtherWotIdentities(db));
                table.setIdentities(ids);
        }



Reply via email to