Author: jflesch
Date: 2007-08-25 16:15:52 +0000 (Sat, 25 Aug 2007)
New Revision: 14878

Added:
   trunk/apps/Thaw/src/thaw/plugins/IndexWebGrapher.java
   trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/
   trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphBuilder.java
   trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java
   trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java
Modified:
   trunk/apps/Thaw/src/thaw/core/PluginManager.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/index/Index.java
   trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java
   trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKDraft.java
Log:
Implement an index web grapher plugin (Graph must still be optimized)

Modified: trunk/apps/Thaw/src/thaw/core/PluginManager.java
===================================================================
--- trunk/apps/Thaw/src/thaw/core/PluginManager.java    2007-08-25 02:17:41 UTC 
(rev 14877)
+++ trunk/apps/Thaw/src/thaw/core/PluginManager.java    2007-08-25 16:15:52 UTC 
(rev 14878)
@@ -37,6 +37,7 @@
                "thaw.plugins.Restarter",
                "thaw.plugins.TransferLogs",
                "thaw.plugins.MDns",
+               "thaw.plugins.IndexWebGrapher",
                "thaw.plugins.SqlConsole",
                "thaw.plugins.LogConsole"
        };

Modified: trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties     2007-08-25 
02:17:41 UTC (rev 14877)
+++ trunk/apps/Thaw/src/thaw/i18n/source.thaw_fr.properties     2007-08-25 
16:15:52 UTC (rev 14878)
@@ -639,5 +639,15 @@


 ## Index web grapher
-thaw.plugin.indexWebGrapher=Dessinateur de toile d'index
+thaw.plugin.indexWebGrapher=Toile d'indexes
+thaw.plugin.indexWebGrapher.shortName=Toile d'indexes
+thaw.plugin.indexWebGrapher.compute=Calculer
+thaw.plugin.indexWebGrapher.computing=En cours ...
+thaw.plugin.indexWebGrapher.waiting=En attente

+thaw.plugin.indexWebGrapher.fanFan.0=H?h?, facile !
+thaw.plugin.indexWebGrapher.fanFan.1=C'est fait !
+thaw.plugin.indexWebGrapher.fanFan.2=Mouahah, je suis trop g?nial !
+thaw.plugin.indexWebGrapher.fanFan.3=C'?tait du gateau !
+thaw.plugin.indexWebGrapher.fanFan.4=Joli, n'est-ce pas ? :)
+

Modified: trunk/apps/Thaw/src/thaw/i18n/thaw.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2007-08-25 02:17:41 UTC 
(rev 14877)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw.properties       2007-08-25 16:15:52 UTC 
(rev 14878)
@@ -657,4 +657,14 @@

 ## index web grapher

-thaw.plugin.indexWebGrapher=Dessinateur de toile d'index
+thaw.plugin.indexWebGrapher=Index web grapher
+thaw.plugin.indexWebGrapher.shortName=Index web
+thaw.plugin.indexWebGrapher.compute=Compute
+thaw.plugin.indexWebGrapher.computing=Computing
+thaw.plugin.indexWebGrapher.waiting=Waiting
+
+thaw.plugin.indexWebGrapher.fanFan.0=Hehe, easy !
+thaw.plugin.indexWebGrapher.fanFan.1=All done !
+thaw.plugin.indexWebGrapher.fanFan.2=Mooahah, I'm so good !
+thaw.plugin.indexWebGrapher.fanFan.3=Piece of cake !
+thaw.plugin.indexWebGrapher.fanFan.4=Nice, isn't it ? :)

Modified: trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties
===================================================================
--- trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties    2007-08-25 02:17:41 UTC 
(rev 14877)
+++ trunk/apps/Thaw/src/thaw/i18n/thaw_fr.properties    2007-08-25 16:15:52 UTC 
(rev 14878)
@@ -639,5 +639,15 @@


 ## Index web grapher
-thaw.plugin.indexWebGrapher=Dessinateur de toile d'index
+thaw.plugin.indexWebGrapher=Toile d'indexes
+thaw.plugin.indexWebGrapher.shortName=Toile d'indexes
+thaw.plugin.indexWebGrapher.compute=Calculer
+thaw.plugin.indexWebGrapher.computing=En cours ...
+thaw.plugin.indexWebGrapher.waiting=En attente

+thaw.plugin.indexWebGrapher.fanFan.0=H\u00e9h\u00e9, facile !
+thaw.plugin.indexWebGrapher.fanFan.1=C'est fait !
+thaw.plugin.indexWebGrapher.fanFan.2=Mouahah, je suis trop g\u00e9nial !
+thaw.plugin.indexWebGrapher.fanFan.3=C'\u00e9tait du gateau !
+thaw.plugin.indexWebGrapher.fanFan.4=Joli, n'est-ce pas ? :)
+

Added: trunk/apps/Thaw/src/thaw/plugins/IndexWebGrapher.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/IndexWebGrapher.java                       
        (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/IndexWebGrapher.java       2007-08-25 
16:15:52 UTC (rev 14878)
@@ -0,0 +1,154 @@
+package thaw.plugins;
+
+import javax.swing.JPanel;
+import javax.swing.JLabel;
+import javax.swing.JButton;
+import javax.swing.JProgressBar;
+import javax.swing.JScrollPane;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+
+import java.awt.event.ActionListener;
+import java.awt.event.ActionEvent;
+
+import java.util.Random;
+
+
+import thaw.core.Core;
+import thaw.core.I18n;
+import thaw.core.Logger;
+
+import thaw.plugins.indexWebGrapher.*;
+
+
+
+public class IndexWebGrapher implements thaw.core.Plugin, ActionListener {
+       public final static int NMB_STEPS = 10;
+
+       private Core core;
+
+       private Hsqldb db;
+
+       private JPanel tabPanel;
+
+       private JScrollPane scrollPane;
+       private GraphPanel graphPanel;
+
+       private JButton compute;
+       private JButton zoomIn;
+       private JButton zoomOut;
+       private JProgressBar progressBar;
+
+       private Random random;
+
+       public boolean run(Core core) {
+               this.core = core;
+
+               this.random = new Random();
+
+               /** dep **/
+
+               if(core.getPluginManager().getPlugin("thaw.plugins.Hsqldb") == 
null) {
+                       Logger.info(this, "Loading Hsqldb plugin");
+
+                       
if(core.getPluginManager().loadPlugin("thaw.plugins.Hsqldb") == null
+                          || 
!core.getPluginManager().runPlugin("thaw.plugins.Hsqldb")) {
+                               Logger.error(this, "Unable to load 
thaw.plugins.Hsqldb !");
+                               return false;
+                       }
+               }
+
+               db = 
(Hsqldb)core.getPluginManager().getPlugin("thaw.plugins.Hsqldb");
+               db.registerChild(this);
+
+
+               /** graphics **/
+
+               tabPanel = new JPanel(new BorderLayout(5, 5));
+
+               JPanel southPanel = new JPanel(new BorderLayout(5, 5));
+
+               compute = new 
JButton(I18n.getMessage("thaw.plugin.indexWebGrapher.compute"));
+               compute.addActionListener(this);
+
+               progressBar = new JProgressBar(0, 100);
+               
progressBar.setString(I18n.getMessage("thaw.plugin.indexWebGrapher.waiting"));
+               progressBar.setStringPainted(true);
+
+               JPanel zoomPanel = new JPanel(new GridLayout(1, 2));
+               zoomPanel.add( (zoomOut = new JButton("-")) );
+               zoomPanel.add( (zoomIn  = new JButton("+")) );
+
+               zoomOut.addActionListener(this);
+               zoomIn.addActionListener(this);
+
+               southPanel.add(compute, BorderLayout.WEST);
+               southPanel.add(progressBar, BorderLayout.CENTER);
+               southPanel.add(zoomPanel, BorderLayout.EAST);
+
+
+               graphPanel = new GraphPanel(this);
+               scrollPane = new JScrollPane(graphPanel,
+                                            
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
+                                            
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
+               scrollPane.getVerticalScrollBar().setUnitIncrement(15);
+
+               tabPanel.add(scrollPane, BorderLayout.CENTER);
+               tabPanel.add(southPanel, BorderLayout.SOUTH);
+
+               
core.getMainWindow().addTab(I18n.getMessage("thaw.plugin.indexWebGrapher.shortName"),
+                                           thaw.gui.IconBox.web,
+                                           tabPanel);
+
+               return true;
+       }
+
+
+       public JScrollPane getScrollPane() {
+               return scrollPane;
+       }
+
+
+       public void setProgress(int step) {
+               String txt = "";
+
+               if (step == NMB_STEPS) {
+                       int fanFan = random.nextInt(5);
+                       txt = 
I18n.getMessage("thaw.plugin.indexWebGrapher.fanFan."+Integer.toString(fanFan));
+               } else {
+                       txt = 
I18n.getMessage("thaw.plugin.indexWebGrapher.computing")
+                               + 
"("+Integer.toString(step)+"/"+Integer.toString(NMB_STEPS)+")";
+               }
+
+               progressBar.setString(txt);
+               progressBar.setValue( (step * 100) / NMB_STEPS );
+       }
+
+
+       public boolean stop() {
+               core.getMainWindow().removeTab(tabPanel);
+
+               return true;
+       }
+
+       public String getNameForUser() {
+               return I18n.getMessage("thaw.plugin.indexWebGrapher");
+       }
+
+       public javax.swing.ImageIcon getIcon() {
+               return thaw.gui.IconBox.web;
+       }
+
+       public void actionPerformed(ActionEvent e) {
+               if (e.getSource() == compute) {
+                       GraphBuilder builder = new GraphBuilder(this, 
graphPanel, db);
+                       Thread th = new Thread(builder);
+                       th.start();
+               } else if (e.getSource() == zoomIn) {
+                       graphPanel.zoomIn();
+               } else if (e.getSource() == zoomOut) {
+                       graphPanel.zoomOut();
+               }
+       }
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/index/Index.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/index/Index.java   2007-08-25 02:17:41 UTC 
(rev 14877)
+++ trunk/apps/Thaw/src/thaw/plugins/index/Index.java   2007-08-25 16:15:52 UTC 
(rev 14878)
@@ -1448,12 +1448,6 @@
        }

        public boolean setNewCommentFlagInMem(boolean flag) {
-               try {
-                       throw new Exception("bleh");
-               } catch(Exception e) {
-                       e.printStackTrace();
-               }
-
                newComment = flag;
                return true;
        }

Added: trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphBuilder.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphBuilder.java          
                (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphBuilder.java  
2007-08-25 16:15:52 UTC (rev 14878)
@@ -0,0 +1,176 @@
+package thaw.plugins.indexWebGrapher;
+
+import java.sql.*;
+
+import java.util.Iterator;
+import java.util.Vector;
+
+
+import thaw.plugins.IndexWebGrapher;
+import thaw.plugins.Hsqldb;
+
+import thaw.fcp.FreenetURIHelper;
+import thaw.core.Logger;
+
+
+public class GraphBuilder implements Runnable {
+
+       private IndexWebGrapher plugin;
+       private GraphPanel graphPanel;
+       private Hsqldb db;
+
+       public GraphBuilder(IndexWebGrapher plugin,
+                           GraphPanel panel,
+                           Hsqldb db) {
+               this.plugin = plugin;
+               this.graphPanel = panel;
+               this.db = db;
+       }
+
+       public void run() {
+               Logger.info(this, "=== Starting ===");
+
+               /* === */
+
+               plugin.setProgress(0);
+               Logger.info(this, "0) Loading all the nodes ...");
+
+               graphPanel.reinit();
+
+               try {
+                       synchronized(db.dbLock) {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("SELECT id, displayName, publicKey "+
+                                                                        "FROM 
indexes");
+
+                               ResultSet set = st.executeQuery();
+
+                               int nmb = 0;
+
+                               while(set.next()) {
+                                       /* will register itself in the 
graphPanel */
+                                       new Node(nmb,
+                                                set.getInt("id") /* index id 
*/,
+                                                set.getString("displayName"),
+                                                set.getString("publicKey"),
+                                                graphPanel);
+                                       nmb++;
+                               }
+
+                               Logger.info(this, Integer.toString(nmb)+" nodes 
loaded");
+                       }
+               } catch(SQLException e) {
+                       Logger.error(this, "Can't load the nodes because : 
"+e.toString());
+                       return;
+               }
+
+               /* === */
+
+               plugin.setProgress(1);
+               Logger.info(this, "1) Loading links ...");
+
+               try {
+                       synchronized(db.dbLock) {
+                               PreparedStatement st;
+
+                               st = 
db.getConnection().prepareStatement("SELECT publicKey FROM links WHERE 
indexParent = ?");
+
+                               for (Iterator it = (new 
Vector(graphPanel.getNodeList())).iterator();
+                                    it.hasNext(); ) {
+                                       Node node = (Node)it.next();
+
+                                       st.setInt(1, node.getIndexId());
+
+                                       ResultSet set = st.executeQuery();
+
+                                       while(set.next()) {
+                                               String lnk = 
set.getString("publicKey");
+
+                                               Node target = 
graphPanel.getNode(lnk);
+
+                                               if (target == null) {
+                                                       target = new 
Node(graphPanel.getLastUsedId()+1,
+                                                                         -1 /* 
indexId */,
+                                                                         
FreenetURIHelper.getFilenameFromKey(lnk).replaceAll(".frdx", ""),
+                                                                         lnk,
+                                                                         
graphPanel);
+                                               }
+
+                                               node.setLinkTo(target);
+                                       }
+                               }
+                       }
+               } catch(SQLException e) {
+                       Logger.error(this, "Can't load the links because : 
"+e.toString());
+                       return;
+               }
+
+
+               /* === */
+
+               plugin.setProgress(2);
+               Logger.info(this, "2) Sorting the nodes according to their 
number of links ...");
+
+               Vector nodes = new Vector(graphPanel.getNodeList());
+               java.util.Collections.sort(nodes);
+
+
+               /* === */
+
+               plugin.setProgress(3);
+               Logger.info(this, "3) Initial placing of the nodes ...");
+
+               double x = 0.0;
+
+               for (Iterator it = nodes.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+                       if (!node.isPositionSet()) {
+                               node.setPosition(x, 0.0);
+                               node.setInitialNeightboorPositions();
+                               x += (node.getLinkCount()+1);
+                       }
+               }
+
+               /* === */
+
+               plugin.setProgress(4);
+               Logger.info(this, "4) Optimizing placement ...");
+
+               for (int i = 0 ; i < 100 ; i++) {
+                       for (Iterator it = nodes.iterator();
+                            it.hasNext();) {
+                               Node node = (Node)it.next();
+                               node.computeVelocity(nodes);
+                       }
+
+                       boolean move = false;
+
+                       for (Iterator it = nodes.iterator();
+                            it.hasNext();) {
+                               Node node = (Node)it.next();
+                               move |= node.applyVelocity();
+                       }
+
+                       if (!move) {
+                               Logger.info(this, "Wow, fully optimized ?!");
+                               break;
+                       }
+               }
+
+               /* === */
+
+               plugin.setProgress(9);
+               Logger.info(this, "Drawing ...");
+
+               graphPanel.guessZoom();
+               graphPanel.refresh();
+
+               /* === */
+
+               plugin.setProgress(10);
+               Logger.info(this, "== Pouf, done ==");
+       } /* /run */
+
+}

Added: trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java            
                (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/GraphPanel.java    
2007-08-25 16:15:52 UTC (rev 14878)
@@ -0,0 +1,203 @@
+package thaw.plugins.indexWebGrapher;
+
+import javax.swing.JPanel;
+import javax.swing.JComponent;
+import java.awt.Graphics;
+import java.awt.Dimension;
+
+import java.awt.event.MouseListener;
+import java.awt.event.MouseEvent;
+
+import java.util.Hashtable;
+import java.util.Vector;
+import java.util.Iterator;
+
+import thaw.plugins.IndexWebGrapher;
+
+
+public class GraphPanel extends JComponent implements MouseListener {
+
+       public final static int BORDER = 50;
+
+       private Hashtable nodeHashtable;
+       private Vector nodeList;
+
+       private int lastId;
+
+       private double zoom;
+
+       private IndexWebGrapher plugin;
+
+       private Node lastSelectedNode;
+
+       public GraphPanel(IndexWebGrapher plugin) {
+               super();
+               this.plugin = plugin;
+               nodeHashtable = null;
+               nodeList = null;
+               lastId = 0;
+               setPreferredSize(new Dimension(10, 10));
+               this.addMouseListener(this);
+       }
+
+       public void reinit() {
+               lastSelectedNode = null;
+               nodeHashtable = new Hashtable();
+               nodeList = new Vector();
+               lastId = 0;
+       }
+
+       public void registerNode(Node node) {
+               nodeHashtable.put(node.getIndexKey().substring(4, 40),
+                                 node);
+               nodeList.add(node);
+
+               if (node.getId() > lastId)
+                       lastId = node.getId();
+       }
+
+       public Node getNode(String key) {
+               return (Node)nodeHashtable.get(key.substring(4, 40));
+       }
+
+       public Vector getNodeList() {
+               return nodeList;
+       }
+
+       public int getLastUsedId() {
+               return lastId;
+       }
+
+
+       public void setZoom(double zoom) {
+               this.zoom = zoom;
+       }
+
+       private double minX = 0;
+       private double maxX = 0;
+       private double minY = 0;
+       private double maxY = 0;
+
+
+       public void guessZoom() {
+               minX = 0;
+               maxX = 0;
+               minY = 0;
+               maxY = 0;
+
+               for (Iterator it = nodeList.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+
+                       if (node.getX() < minX) minX = node.getX();
+                       if (node.getX() > maxX) maxX = node.getX();
+                       if (node.getY() < minY) minY = node.getY();
+                       if (node.getY() > maxY) maxY = node.getY();
+               }
+
+               Dimension size = plugin.getScrollPane().getSize();
+
+               double zoomX = (size.getWidth()-(2*BORDER)) / (maxX - minX);
+               double zoomY = (size.getHeight()-(2*BORDER)) / (maxY - minY);
+
+               zoom = ((zoomX > zoomY) ? zoomY : zoomX);
+       }
+
+       public void zoomIn() {
+               zoom = zoom * 2.0;
+               refresh();
+       }
+
+       public void zoomOut() {
+               zoom = zoom / 2.0;
+               refresh();
+       }
+
+       public void refresh() {
+               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));
+               plugin.getScrollPane().revalidate();
+               repaint();
+       }
+
+
+       public void paintComponent(Graphics g) {
+               super.paintComponent(g);
+
+               Dimension d = getSize();
+               g.setColor(java.awt.Color.WHITE);
+               g.fillRect(0, 0, (int)d.getWidth(), (int)d.getHeight());
+
+               if (nodeList == null)
+                       return;
+
+               int zeroX = (-1 * (int)(minX * zoom)) + BORDER;
+               int zeroY = (-1 * (int)(minY * zoom)) + BORDER;
+
+               for (Iterator it = nodeList.iterator();
+                    it.hasNext();) {
+                       ((Node)it.next()).paintTaNodeFaceDeNoeud(g, zoom, 
zeroX, zeroY);
+               }
+       }
+
+
+       public void clicked(int x, int y) {
+               int zeroX = (-1 * (int)(minX * zoom)) + BORDER;
+               int zeroY = (-1 * (int)(minY * zoom)) + BORDER;
+
+               if (lastSelectedNode != null)
+                       lastSelectedNode.setSelected(false);
+
+               Node bestPlaced = null;
+               double bestDist = 0.0;
+
+               for (Iterator it = nodeList.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+
+                       if (bestPlaced == null) {
+                               bestPlaced = node;
+                               double diffBestX = 
Math.abs(bestPlaced.getXPixel(zoom, zeroX)-x);
+                               double diffBestY = 
Math.abs(bestPlaced.getYPixel(zoom, zeroY)-y);
+
+                               bestDist = Math.sqrt(Math.pow(diffBestX, 
2)+Math.pow(diffBestY, 2));
+                       } else {
+                               double diffNodeX = 
Math.abs(node.getXPixel(zoom, zeroX)-x);
+                               double diffNodeY = 
Math.abs(node.getYPixel(zoom, zeroY)-y);
+
+                               double distNode = Math.sqrt(Math.pow(diffNodeX, 
2) + Math.pow(diffNodeY, 2));
+
+                               if (distNode < bestDist) {
+                                       bestPlaced = node;
+                                       bestDist = distNode;
+                               }
+                       }
+               }
+
+               if (bestPlaced != null) {
+                       bestPlaced.setSelected(true);
+                       lastSelectedNode = bestPlaced;
+               }
+
+               repaint();
+       }
+
+       public void mouseClicked(final MouseEvent e) {
+               clicked(e.getX(), e.getY());
+       }
+
+       public void mouseEntered(final MouseEvent e) { }
+       public void mouseExited(final MouseEvent e) { }
+
+       public void mousePressed(final MouseEvent e) {
+               clicked(e.getX(), e.getY());
+       }
+
+       public void mouseReleased(final MouseEvent e) {
+               clicked(e.getX(), e.getY());
+       }
+}

Added: trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java                  
        (rev 0)
+++ trunk/apps/Thaw/src/thaw/plugins/indexWebGrapher/Node.java  2007-08-25 
16:15:52 UTC (rev 14878)
@@ -0,0 +1,316 @@
+package thaw.plugins.indexWebGrapher;
+
+import java.util.Vector;
+import java.util.Iterator;
+
+import java.awt.Graphics;
+import java.awt.Color;
+
+import thaw.core.Logger;
+
+
+public class Node implements Comparable {
+
+       public final static int RADIUS = 4;
+
+       private int id;
+       private int indexId;
+       private String indexName;
+       private String indexKey;
+       private GraphPanel graphPanel;
+
+       private Vector linkTo;
+       private Vector linkedFrom;
+
+       /**
+        * @param indexId -1 if none
+        */
+       public Node(int id,
+                   int indexId,
+                   String indexName,
+                   String indexKey,
+                   GraphPanel graphPanel) {
+               this.id = id;
+               this.indexId = indexId;
+               this.indexName = indexName;
+               this.indexKey = indexKey;
+               this.graphPanel = graphPanel;
+
+               linkTo = new Vector();
+               linkedFrom = new Vector();
+
+               graphPanel.registerNode(this);
+       }
+
+
+       public int getId() {
+               return id;
+       }
+
+       public int getIndexId() {
+               return indexId;
+       }
+
+       public String getIndexKey() {
+               return indexKey;
+       }
+
+       public String getIndexName() {
+               return indexName;
+       }
+
+       public void setLinkTo(Node node) {
+               linkTo.add(node);
+               node.setLinkedFrom(this);
+       }
+
+       private void setLinkedFrom(Node node) {
+               linkedFrom.add(node);
+       }
+
+       public Vector getLinkList() {
+               return linkTo;
+       }
+
+       public int getLinkCount() {
+               return linkTo.size() + linkedFrom.size();
+       }
+
+       /**
+        * we want the nodes with the higher number of
+        * links first => we consider them smaller
+        */
+       public int compareTo(final Object o) {
+               final Node node = (Node)o;
+
+               if (node.getLinkCount() < getLinkCount())
+                       return -1;
+               if (node.getLinkCount() > getLinkCount())
+                       return 1;
+
+               return 0;
+       }
+
+
+       private boolean posSet = false;
+       private double x = -1;
+       private double y = -1;
+
+       public boolean isPositionSet() {
+               return posSet;
+       }
+
+
+       public void setPosition(double x, double y) {
+               posSet = true;
+               this.x = x;
+               this.y = y;
+       }
+
+       public double getX() {
+               return x;
+       }
+
+       public double getY() {
+               return y;
+       }
+
+
+       private double velocityX = 0.0;
+       private double velocityY = 0.0;
+
+       public final static double TIMESTEP = 0.1;
+
+       private double[] attraction(Node node) {
+               return new double[] {0, 0};
+       }
+
+       private double[] repulsion(Node node) {
+               return new double[] {0, 0};
+       }
+
+       /**
+        * see http://en.wikipedia.org/wiki/Force-based_algorithms
+        */
+       public void computeVelocity(Vector nodeList) {
+               double netForceX = 0.0;
+               double netForceY = 0.0;
+
+               /* repulsion */
+               for (Iterator it = nodeList.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+
+                       if (node == this
+                           || linkTo.indexOf(node) >= 0
+                           || linkedFrom.indexOf(node) >= 0)
+                               continue;
+
+                       double[] repuls = repulsion(node);
+                       netForceX += repuls[0];
+                       netForceY += repuls[1];
+               }
+
+               /* attraction */
+               for (Iterator it = linkTo.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+
+                       if (node == this)
+                               continue;
+
+                       double[] attr = attraction(node);
+                       netForceX += attr[0];
+                       netForceY += attr[1];
+               }
+
+               /* attraction */
+               for (Iterator it = linkedFrom.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+
+                       if (node == this)
+                               continue;
+
+                       double[] attr = attraction(node);
+                       netForceX += attr[0];
+                       netForceY += attr[1];
+               }
+
+               velocityX += netForceX;
+               velocityY += netForceY;
+       }
+
+       /**
+        * @return true if moved
+        */
+       public boolean applyVelocity() {
+               if (velocityX == 0 && velocityY == 0)
+                       return false;
+
+               x += velocityX * TIMESTEP;
+               y += velocityY * TIMESTEP;
+
+               return true;
+       }
+
+
+       /**
+        * Recursivity : Dirty, but easier :P
+        */
+       public void setInitialNeightboorPositions() {
+               int unplaced = 0;
+
+               for (Iterator it = linkTo.iterator();
+                    it.hasNext(); ) {
+                       Node node = (Node)it.next();
+
+                       if (!node.isPositionSet())
+                               unplaced++;
+               }
+
+               if (unplaced == 0)
+                       return;
+
+               double step = (2*Math.PI) / unplaced;
+
+               double current = 0;
+
+               for (Iterator it = linkTo.iterator();
+                    it.hasNext();) {
+                       Node node = (Node)it.next();
+
+                       if (!node.isPositionSet()) {
+                               double diffX = Math.cos(current) * (unplaced+1);
+                               double diffY = Math.sin(current) * (unplaced+1);
+
+                               node.setPosition(x + diffX,
+                                                y + diffY);
+
+                               node.setInitialNeightboorPositions();
+
+                               current += step;
+                       }
+               }
+
+               return;
+       }
+
+
+       public boolean linkTo(Node node) {
+               return (linkTo.indexOf(node) >= 0);
+       }
+
+       private boolean selected = false;
+
+       public void setSelected(boolean sel) {
+               this.selected = sel;
+       }
+
+       public boolean isSelected() {
+               return selected;
+       }
+
+       public double getXPixel(double zoom, int zeroX) {
+               return (double)((int)(x*zoom) + zeroX);
+       }
+
+       public double getYPixel(double zoom, int zeroY) {
+               return (double)((int)(y*zoom) + zeroY);
+       }
+
+
+       public void paintTaNodeFaceDeNoeud(Graphics g, double zoom,
+                                          int zeroX, int zeroY) {
+
+               int realX = (int)(x*zoom);
+               int realY = (int)(y*zoom);
+
+               if (selected)
+                       g.setColor(Color.ORANGE);
+               else
+                       g.setColor(Color.GRAY);
+
+               for (Iterator it = linkTo.iterator();
+                    it.hasNext();) {
+                       Node target = (Node)it.next();
+
+                       int targetX = (int)(target.getX()*zoom);
+                       int targetY = (int)(target.getY()*zoom);
+
+                       if (target.isSelected()) {
+                               g.setColor(Color.CYAN);
+                       }
+
+                       if ( (target.isSelected() || selected)
+                            && target.linkTo(this) ) {
+                               g.setColor(Color.PINK);
+                       }
+
+                       g.drawLine(realX+zeroX, realY+zeroY, targetX+zeroX, 
targetY+zeroY);
+
+                       if (target.isSelected())
+                               g.setColor(Color.GRAY);
+               }
+
+
+               if (selected)
+                       g.setColor(Color.RED);
+               else
+                       g.setColor(Color.GREEN);
+
+               g.fillOval( realX - RADIUS + zeroX,
+                           realY - RADIUS + zeroY,
+                           2*RADIUS,
+                           2*RADIUS);
+
+
+               if (selected) {
+                       g.setColor(Color.BLACK);
+
+                       g.drawString(indexName,
+                                    realX + zeroX,
+                                    realY + zeroY - 10);
+               }
+       }
+}

Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java   
2007-08-25 02:17:41 UTC (rev 14877)
+++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKBoard.java   
2007-08-25 16:15:52 UTC (rev 14878)
@@ -534,38 +534,41 @@
        }

        protected void endOfRefresh() {
-               Logger.info(this, "End of refresh");
+               synchronized(this) {
+                       Logger.info(this, "End of refresh");

-               try {
-                       Hsqldb db = factory.getDb();
+                       try {
+                               Hsqldb db = factory.getDb();

-                       synchronized(db.dbLock) {
-                               PreparedStatement st;
+                               synchronized(db.dbLock) {
+                                       PreparedStatement st;

-                               st = 
db.getConnection().prepareStatement("UPDATE frostKSKBoards "+
-                                                                        "SET 
lastUpdate = ? "+
-                                                                        "WHERE 
id = ?");
-                               st.setDate(1, new java.sql.Date(new 
java.util.Date().getTime()));
-                               st.setInt(2, id);
-                               st.execute();
+                                       st = 
db.getConnection().prepareStatement("UPDATE frostKSKBoards "+
+                                                                               
 "SET lastUpdate = ? "+
+                                                                               
 "WHERE id = ?");
+                                       st.setDate(1, new java.sql.Date(new 
java.util.Date().getTime()));
+                                       st.setInt(2, id);
+                                       st.execute();
+                               }
+                       } catch(SQLException e) {
+                               Logger.error(this, "Unable to update the 
lastUpdate date :"+e.toString());
                        }
-               } catch(SQLException e) {
-                       Logger.error(this, "Unable to update the lastUpdate 
date :"+e.toString());
-               }

-               int newMsgs = getNewMessageNumber();
+                       int newMsgs = getNewMessageNumber();

-               if (newMsgs > 0) {
-                       String announce = 
I18n.getMessage("thaw.plugin.miniFrost.newMsgAnnounce");
-                       announce = announce.replaceAll("X", 
Integer.toString(newMsgs));
-                       announce = announce.replaceAll("Y", toString());
+                       if (newMsgs > 0) {
+                               String announce = 
I18n.getMessage("thaw.plugin.miniFrost.newMsgAnnounce");
+                               announce = announce.replaceAll("X", 
Integer.toString(newMsgs));
+                               announce = announce.replaceAll("Y", toString());

-                       
thaw.plugins.TrayIcon.popMessage(factory.getCore().getPluginManager(),
-                                                        "MiniFrost",
-                                                        announce);
+                               
thaw.plugins.TrayIcon.popMessage(factory.getCore().getPluginManager(),
+                                                                "MiniFrost",
+                                                                announce);
+                       }
+
+                       refreshing = false;
                }

-               refreshing = false;
                notifyChange();
        }

@@ -744,7 +747,11 @@

                this.maxDaysInThePast = maxDaysInThePast;

-               refreshing = true;
+               synchronized(this) {
+                       lastDate = getNextRefreshDate(null);
+                       lastRev = -1;
+                       refreshing = true;
+               }

                notifyChange();

@@ -756,8 +763,6 @@

                //lastDate = new Date((new Date()).getTime()
                //                  + (MIN_DAYS_IN_THE_FUTURE * (24 * 60 * 60 * 
1000 /* 1 day */)));
-               lastDate = getNextRefreshDate(null);
-               lastRev = -1;

                synchronized(runningDownloads) {
                        lastSuccessfulRev = getLastDownloadedRev(lastDate);

Modified: trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKDraft.java
===================================================================
--- trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKDraft.java   
2007-08-25 02:17:41 UTC (rev 14877)
+++ trunk/apps/Thaw/src/thaw/plugins/miniFrost/frostKSK/KSKDraft.java   
2007-08-25 16:15:52 UTC (rev 14878)
@@ -205,7 +205,7 @@
                    || (board.getCurrentlyRefreshedDate() != null
                        && 
(KSKBoard.getMidnight(board.getCurrentlyRefreshedDate()).getTime()
                            < KSKBoard.getMidnight(date).getTime()) )) {
-                       Logger.info(this, "Board: 
"+Long.toString(KSKBoard.getMidnight(board.getCurrentlyRefreshedDate()).getTime()));
+                       //Logger.info(this, "Board: 
"+Long.toString(KSKBoard.getMidnight(board.getCurrentlyRefreshedDate()).getTime()));
                        Logger.info(this, "Draft: 
"+KSKBoard.getMidnight(date).getTime());
                        return true;
                }


Reply via email to