[jboss-cvs] JBossAS SVN: r90896 - in projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher: graph and 2 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Jul 7 12:33:41 EDT 2009


Author: alesj
Date: 2009-07-07 12:33:41 -0400 (Tue, 07 Jul 2009)
New Revision: 90896

Added:
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AbstractGraphCreator.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AllGraphCreator.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/BeanGraphCreator.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/Colorable.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/ColorableGraphCell.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphCreator.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphSettings.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/GIFRenderer.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/JPGRenderer.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/SVGRenderer.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GIFOutputStream.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GraphUtilities.java
Removed:
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AbstractRenderer.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AllRenderer.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/BeanRenderer.java
Modified:
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/GrapherServlet.java
   projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/Renderer.java
Log:
Separate rendering from graph creation.

Modified: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/GrapherServlet.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/GrapherServlet.java	2009-07-07 13:30:44 UTC (rev 90895)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/GrapherServlet.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -22,7 +22,11 @@
 package org.jboss.mctools.grapher;
 
 import java.io.IOException;
-import java.io.PrintWriter;
+import java.io.OutputStream;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
 import javax.servlet.ServletConfig;
 import javax.servlet.ServletContext;
 import javax.servlet.ServletException;
@@ -33,26 +37,47 @@
 import org.jboss.kernel.spi.dependency.KernelController;
 import org.jboss.logging.Logger;
 import org.jboss.mc.servlet.vdf.api.KernelControllerVDFConnector;
-import org.jboss.mctools.grapher.render.AllRenderer;
-import org.jboss.mctools.grapher.render.BeanRenderer;
+import org.jboss.mctools.grapher.graph.AllGraphCreator;
+import org.jboss.mctools.grapher.graph.BeanGraphCreator;
+import org.jboss.mctools.grapher.graph.GraphCreator;
+import org.jboss.mctools.grapher.graph.GraphSettings;
+import org.jboss.mctools.grapher.render.GIFRenderer;
+import org.jboss.mctools.grapher.render.JPGRenderer;
 import org.jboss.mctools.grapher.render.Renderer;
+import org.jboss.mctools.grapher.render.SVGRenderer;
+import org.jgraph.JGraph;
+import org.jgraph.graph.AttributeMap;
+import org.jgraph.graph.ConnectionSet;
+import org.jgraph.graph.DefaultGraphModel;
+import org.jgraph.graph.GraphCell;
+import org.jgraph.graph.GraphModel;
 
 /**
  * Grapher servlet.
- *
+ * <p/>
  * It knows how to render all of MC components,
  * or you can specify just a single bean via parameter.
  * e.g. grapher/?bean=TransactionManager
+ * <p/>
+ * You can also change the type of rendering.
+ * Currently we're supporting svg, jpg and gif.
  *
  * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
  */
 public class GrapherServlet extends HttpServlet
 {
    private Logger log = Logger.getLogger(getClass());
-   
+
    private KernelController controller;
-   private Renderer ALL = new AllRenderer();
 
+   private static final String DEFAULT_FORMAT = "gif";
+   /**
+    * The default renderer
+    */
+   private Renderer renderer;
+   private Map<String, Renderer> renderers;
+   private GraphCreator ALL = new AllGraphCreator();
+
    @Override
    public void init(ServletConfig config) throws ServletException
    {
@@ -62,32 +87,71 @@
          throw new ServletException("Illegal VDF component, no MC Kernel present.");
 
       controller = connector.getUtility();
+
+      renderers = new HashMap<String, Renderer>();
+      renderers.put("svg", new SVGRenderer());
+      renderers.put("jpg", new JPGRenderer());
+      renderers.put("gif", new GIFRenderer());
+
+      String defaultRenderer = config.getInitParameter("renderer");
+      if (defaultRenderer != null)
+         renderer = renderers.get(defaultRenderer);
+
+      if (renderer == null)
+         renderer = renderers.get(DEFAULT_FORMAT);
    }
 
    /**
+    * Get renderer.
+    *
+    * @param key the key
+    * @return current renderer
+    */
+   protected Renderer getRenderer(String key)
+   {
+      if (key == null)
+         return renderer;
+
+      Renderer current = renderers.get(key);
+      if (current == null)
+         current = renderer;
+
+      return current;
+   }
+
+   /**
     * Do render MC graph.
     *
-    * @param request the http request
+    * @param request  the http request
     * @param response the http response
     * @throws ServletException the servlet exception
-    * @throws IOException the io exception
+    * @throws IOException      the io exception
     */
    protected void doRenderGraph(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
       String bean = request.getParameter("bean");
-      Renderer renderer;
+      GraphCreator creator;
       if (bean != null)
-         renderer = new BeanRenderer(bean);
+         creator = new BeanGraphCreator(bean);
       else
-         renderer = ALL;
+         creator = ALL;
 
-      if (log.isTraceEnabled())
-         log.trace("Invoking renderer: " + renderer);
+      //if (log.isTraceEnabled())
+         log.info("Invoking creator: " + creator);
 
-      PrintWriter writer = response.getWriter();
+      Map attributes = new HashMap();
+      ConnectionSet cs = new ConnectionSet();
+      Object[] cells = creator.createCells(controller, attributes, cs);
+      JGraph graph = createGraph(cells, attributes, cs);
+
+      Renderer current = getRenderer(request.getParameter("renderer"));
+      //if (log.isTraceEnabled())
+         log.info("Using renderer: " + current);
+
+      OutputStream writer = response.getOutputStream();
       try
       {
-         renderer.render(controller, writer);
+         current.render(graph, writer, 10);
       }
       finally
       {
@@ -95,6 +159,27 @@
       }
    }
 
+   /**
+    * Create graph.
+    *
+    * @param cells      the graph cells
+    * @param attributes the graph attributes
+    * @param cs         the connection set
+    * @return new jgraph instance
+    */
+   protected JGraph createGraph(Object[] cells, Map attributes, ConnectionSet cs)
+   {
+      //if (log.isTraceEnabled())
+         log.info("Creating graph from " + cells.length + " objects: " + Arrays.asList(cells));
+
+      GraphModel model = new ModifiedGraphModel();
+      //create simple layout
+      GraphSettings.layout(cells, attributes);
+      // insert cells
+      model.insert(cells, attributes, cs, null, null);
+      return new JGraph(model);
+   }
+
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
    {
@@ -106,4 +191,47 @@
    {
       doRenderGraph(request, response);
    }
+
+   private class ModifiedGraphModel extends DefaultGraphModel
+   {
+      protected Map handleAttributes(Map attributes)
+      {
+         if (attributes != null)
+         {
+            Hashtable undo = new Hashtable();
+            for (Object o : attributes.entrySet())
+            {
+               Map.Entry entry = (Map.Entry)o;
+               Object cell = entry.getKey();
+               Object value = entry.getValue();
+               if (value instanceof Map)
+               {
+                  Map deltaNew = (Map)entry.getValue();
+                  //System.out.println("deltaNew="+deltaNew);
+                  //System.out.println("stateOld="+getAttributes(cell));
+                  if (cell instanceof GraphCell)
+                  {
+                     Map deltaOld = ((GraphCell)cell).changeAttributes(deltaNew);
+                     //System.out.println("stateNew=" + getAttributes(cell));
+                     //System.out.println("deltaOld=" + deltaOld);
+                     undo.put(cell, deltaOld);
+                  }
+                  else
+                  {
+                     AttributeMap attr = getAttributes(cell);
+                     if (attr != null)
+                     {
+                        Map deltaOld = attr.applyMap(deltaNew);
+                        //System.out.println("stateNew="+getAttributes(cell));
+                        //System.out.println("deltaOld="+deltaOld);
+                        undo.put(cell, deltaOld);
+                     }
+                  }
+               }
+            }
+            return undo;
+         }
+         return null;
+      }
+   }
 }

Copied: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AbstractGraphCreator.java (from rev 90862, projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AbstractRenderer.java)
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AbstractGraphCreator.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AbstractGraphCreator.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,193 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.dependency.spi.ControllerContext;
+import org.jboss.dependency.spi.DependencyInfo;
+import org.jboss.dependency.spi.DependencyItem;
+import org.jboss.kernel.spi.dependency.KernelController;
+import org.jboss.logging.Logger;
+import org.jgraph.graph.DefaultEdge;
+import org.jgraph.graph.DefaultGraphCell;
+import org.jgraph.graph.Edge;
+import org.jgraph.graph.GraphConstants;
+import org.jgraph.graph.ConnectionSet;
+
+/**
+ * Abstract MC components renderer.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public abstract class AbstractGraphCreator implements GraphCreator
+{
+   protected Logger log = Logger.getLogger(getClass());
+
+   public Object[] createCells(KernelController controller, Map attributes, ConnectionSet cs)
+   {
+      Map<Object, DefaultGraphCell> cells = new HashMap<Object, DefaultGraphCell>();
+      Set<Object> objects = new HashSet<Object>();
+      createCells(controller, cells, objects, attributes, cs);
+
+      // change to array
+      Object[] graph = new Object[objects.size()];
+      int i = 0;
+      for (Object object : objects)
+         graph[i++] = object;
+
+      return graph;
+   }
+
+   /**
+    * Do create cells.
+    *
+    * @param controller the controller
+    * @param cells the cells
+    * @param objects the graph's objects
+    * @param attributes the graph attributes
+    * @param cs the connection set
+    */
+   protected abstract void createCells(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects, Map attributes, ConnectionSet cs);
+
+   /**
+    * Create the cell.
+    *
+    * @param label the cell's label
+    * @return new cell instance
+    */
+   protected DefaultGraphCell createCell(Object label)
+   {
+      DefaultGraphCell cell = new ColorableGraphCell(label, Color.BLUE);
+      GraphConstants.setBounds(cell.getAttributes(), new Rectangle2D.Double(20,20,30,15));
+      GraphConstants.setGradientColor(cell.getAttributes(), Color.orange);
+      GraphConstants.setOpaque(cell.getAttributes(), true);
+
+      cell.addPort();
+
+      // TODO - add html link
+      return cell;
+   }
+
+   /**
+    * Handle single context.
+    *
+    * @param controller the controller
+    * @param cells the cells
+    * @param objects the graph's objects
+    * @param attributes the graph attributes
+    * @param cs the connection set
+    * @param context the context to render
+    */
+   protected void handleContext(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects, Map attributes, ConnectionSet cs, ControllerContext context)
+   {
+      DefaultGraphCell owner = getCell(cells, objects, context);
+
+      DependencyInfo info = context.getDependencyInfo();
+      Set<DependencyItem> items = info.getIDependOn(null);
+      if (items != null && items.isEmpty() == false)
+      {
+         for(DependencyItem item : items)
+         {
+            DefaultGraphCell dependency;
+
+            Object iDependOn = item.getIDependOn();
+            if (iDependOn instanceof Class)
+            {
+               ControllerContext cc = controller.getContextByClass(Class.class.cast(iDependOn));
+               dependency = getCell(cells, objects, cc);
+            }
+            else
+            {
+               dependency = cells.get(iDependOn);
+               if (dependency == null)
+               {
+                  dependency = createCell(iDependOn);
+                  cells.put(iDependOn, dependency);
+                  objects.add(dependency);
+               }
+            }
+
+            Edge edge = new DefaultEdge();
+            cs.connect(edge, owner.getChildAt(0), dependency.getChildAt(0));
+
+            int arrow = GraphConstants.ARROW_CLASSIC;
+            GraphConstants.setLineEnd(edge.getAttributes(), arrow);
+            GraphConstants.setEndFill(edge.getAttributes(), true);
+
+            objects.add(edge);
+         }
+      }
+   }
+
+   /**
+    * Get the cell for the param context.
+    *
+    * @param cells the current cells
+    * @param objects all of graph's objects
+    * @param context the context
+    * @return context's cell
+    */
+   protected DefaultGraphCell getCell(Map<Object, DefaultGraphCell> cells, Set<Object> objects, ControllerContext context)
+   {
+      Object name = context.getName();
+      DefaultGraphCell cell = cells.get(name);
+      if (cell == null)
+      {
+         cell = createCell(name);
+         cells.put(name, cell);
+         objects.add(cell);
+         // fill in aliases as well
+         Set<Object> aliases = context.getAliases();
+         if (aliases != null && aliases.isEmpty() == false)
+         {
+            for(Object alias : aliases)
+            {
+               if (cells.containsKey(alias) == false)
+               {
+                  cells.put(alias, cell);
+               }
+            }
+         }
+      }
+
+      enhanceCell(cell, context);
+
+      return cell;
+   }
+
+   /**
+    * Enhance cell rendering.
+    *
+    * @param cell the cell to enhance
+    * @param context the context to get info from
+    */
+   protected void enhanceCell(DefaultGraphCell cell, ControllerContext context)
+   {
+      // TODO - enhance cell rendering with context's info
+   }
+}
\ No newline at end of file

Copied: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AllGraphCreator.java (from rev 90851, projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AllRenderer.java)
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AllGraphCreator.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/AllGraphCreator.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,53 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.dependency.spi.ControllerContext;
+import org.jboss.dependency.spi.ControllerState;
+import org.jboss.dependency.spi.ControllerStateModel;
+import org.jboss.kernel.spi.dependency.KernelController;
+import org.jgraph.graph.DefaultGraphCell;
+import org.jgraph.graph.ConnectionSet;
+
+/**
+ * Render all MC components.
+ * 
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class AllGraphCreator extends AbstractGraphCreator
+{
+   protected void createCells(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects, Map attributes, ConnectionSet cs)
+   {
+      ControllerStateModel model = controller.getStates();
+      for (ControllerState state : model)
+      {
+         Set<ControllerContext> contexts = controller.getContextsByState(state);
+         for (ControllerContext context : contexts)
+         {
+            handleContext(controller, cells, objects, attributes, cs, context);
+         }
+      }
+   }
+}

Copied: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/BeanGraphCreator.java (from rev 90863, projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/BeanRenderer.java)
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/BeanGraphCreator.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/BeanGraphCreator.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,63 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jboss.dependency.spi.ControllerContext;
+import org.jboss.kernel.spi.dependency.KernelController;
+import org.jgraph.graph.DefaultGraphCell;
+import org.jgraph.graph.ConnectionSet;
+
+/**
+ * Render single bean.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class BeanGraphCreator extends AbstractGraphCreator
+{
+   private Object bean;
+
+   public BeanGraphCreator(Object bean)
+   {
+      if (bean == null)
+         throw new IllegalArgumentException("Null bean name");
+
+      this.bean = bean;
+   }
+
+   protected void createCells(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects, Map attributes, ConnectionSet cs)
+   {
+      ControllerContext context = controller.getContext(bean, null);
+      if (context == null)
+         throw new IllegalArgumentException("No such context: " + bean);
+
+      handleContext(controller, cells, objects, attributes, cs, context);
+   }
+
+   @Override
+   public String toString()
+   {
+      return super.toString() + "[bean=" + bean + "]";
+   }
+}
\ No newline at end of file

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/Colorable.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/Colorable.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/Colorable.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.awt.*;
+
+/**
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public interface Colorable
+{
+   /**
+    * Get color.
+    *
+     * @return the color
+    */
+   Color color();
+}

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/ColorableGraphCell.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/ColorableGraphCell.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/ColorableGraphCell.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,57 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.awt.*;
+
+import org.jgraph.graph.DefaultGraphCell;
+
+/**
+ * Colorable graph cell.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class ColorableGraphCell extends DefaultGraphCell implements Colorable
+{
+   private Color color;
+
+   public ColorableGraphCell(Color color)
+   {
+      this.color = color;
+   }
+
+   public ColorableGraphCell(Object userObject, Color color)
+   {
+      super(userObject);
+      this.color = color;
+   }
+
+   public Color color()
+   {
+      return color;
+   }
+
+   public void setColor(Color color)
+   {
+      this.color = color;
+   }
+}

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphCreator.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphCreator.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphCreator.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,47 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.util.Map;
+
+import org.jboss.kernel.spi.dependency.KernelController;
+import org.jgraph.graph.ConnectionSet;
+
+/**
+ * Graph creator.
+ *
+ * It knows how to create JGraph cells.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public interface GraphCreator
+{
+   /**
+    * Create graph cells.
+    *
+    * @param controller the controller
+    * @param attributes the attributes
+    * @param cs the connections set
+    * @return graph's cells
+    */
+   Object[] createCells(KernelController controller, Map attributes, ConnectionSet cs);
+}

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphSettings.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphSettings.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/graph/GraphSettings.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,88 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.graph;
+
+import java.awt.*;
+import java.util.HashMap;
+import java.util.Map;
+import javax.swing.*;
+
+import org.jgraph.graph.GraphConstants;
+
+/**
+ * Graph settings.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class GraphSettings
+{
+   /**
+    * Create layout.
+    *
+    * @param cells the cells
+    * @param attributes the attributes
+    */
+   public static void layout(Object[] cells, Map attributes)
+   {
+      int count = cells.length;
+      int square = (int)Math.sqrt(count) + 1; //never zero
+      int nodesperrow = count / square;
+
+      int row = 0;
+      int col = 0;
+      for (int p = 0; p < count; p++)
+      {
+         col++;
+         Object obj = cells[p];
+         if (obj instanceof Colorable)
+         {
+            Colorable cell = (Colorable)obj;
+            attributes.put(cell, createBounds(col * 70, row * 70, cell.color()));
+         }
+         if (col >= nodesperrow)
+         {
+            col = 0;
+            row++;
+         }
+      }
+   }
+
+   /**
+    * Create bounds.
+    *
+    * @param x the x
+    * @param y the y
+    * @param c the color
+    * @return bounds map
+    */
+   private static Map createBounds(int x, int y, Color c)
+   {
+      Map map = new HashMap();
+      GraphConstants.setBounds(map, new Rectangle(x, y, 30, 30));
+      GraphConstants.setBorder(map, BorderFactory.createRaisedBevelBorder());
+      GraphConstants.setBackground(map, c.brighter());
+      GraphConstants.setForeground(map, Color.white);
+      GraphConstants.setFont(map, GraphConstants.DEFAULTFONT.deriveFont(Font.BOLD, 12));
+      GraphConstants.setOpaque(map, true);
+      return map;
+   }
+}

Deleted: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AbstractRenderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AbstractRenderer.java	2009-07-07 13:30:44 UTC (rev 90895)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AbstractRenderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -1,228 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.mctools.grapher.render;
-
-import java.awt.geom.Rectangle2D;
-import java.io.IOException;
-import java.io.Writer;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import javax.swing.*;
-
-import org.apache.batik.dom.GenericDOMImplementation;
-import org.apache.batik.svggen.SVGGraphics2D;
-import org.jboss.dependency.spi.ControllerContext;
-import org.jboss.dependency.spi.DependencyInfo;
-import org.jboss.dependency.spi.DependencyItem;
-import org.jboss.kernel.spi.dependency.KernelController;
-import org.jboss.logging.Logger;
-import org.jgraph.JGraph;
-import org.jgraph.graph.DefaultEdge;
-import org.jgraph.graph.DefaultGraphCell;
-import org.jgraph.graph.Edge;
-import org.jgraph.graph.GraphConstants;
-import org.w3c.dom.DOMImplementation;
-import org.w3c.dom.Document;
-
-/**
- * Abstract MC components renderer.
- *
- * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
- */
-public abstract class AbstractRenderer implements Renderer
-{
-   protected Logger log = Logger.getLogger(getClass());
-
-   public void render(KernelController controller, Writer writer) throws IOException
-   {
-      Map<Object, DefaultGraphCell> cells = new HashMap<Object, DefaultGraphCell>();
-      Set<Object> objects = new HashSet<Object>();
-      render(controller, cells, objects);
-
-      // change to array
-      Object[] graph = new Object[objects.size()];
-      int i = 0;
-      for (Object object : objects)
-         graph[i++] = object;
-
-      if (log.isTraceEnabled())
-         log.trace("Rendering " + graph.length + " objects.");
-
-      render(graph, writer, 0);
-   }
-
-   /**
-    * Do render.
-    *
-    * @param controller the controller
-    * @param cells the cells
-    * @param objects the graph's objects
-    * @throws IOException for any IO exception
-    */
-   protected abstract void render(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects) throws IOException;
-
-   /**
-    * Create the cell.
-    *
-    * @param label the cell's label
-    * @return new cell instance
-    */
-   protected DefaultGraphCell createCell(Object label)
-   {
-      DefaultGraphCell cell = new DefaultGraphCell(label);
-      cell.addPort();
-      // TODO - add html link
-      return cell;
-   }
-
-   /**
-    * Render single context.
-    *
-    * @param controller the controller
-    * @param cells the cells
-    * @param objects the graph's objects
-    * @param context the context to render
-    */
-   protected void renderContext(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects, ControllerContext context)
-   {
-      DefaultGraphCell owner = getCell(cells, objects, context);
-
-      DependencyInfo info = context.getDependencyInfo();
-      Set<DependencyItem> items = info.getIDependOn(null);
-      if (items != null && items.isEmpty() == false)
-      {
-         for(DependencyItem item : items)
-         {
-            DefaultGraphCell dependency;
-
-            Object iDependOn = item.getIDependOn();
-            if (iDependOn instanceof Class)
-            {
-               ControllerContext cc = controller.getContextByClass(Class.class.cast(iDependOn));
-               dependency = getCell(cells, objects, cc);
-            }
-            else
-            {
-               dependency = cells.get(iDependOn);
-               if (dependency == null)
-               {
-                  dependency = createCell(iDependOn);
-                  cells.put(iDependOn, dependency);
-                  objects.add(dependency);
-               }
-            }
-
-            Edge edge = new DefaultEdge();
-            edge.setSource(owner.getChildAt(0));
-            edge.setTarget(dependency.getChildAt(0));
-
-            int arrow = GraphConstants.ARROW_CLASSIC;
-            GraphConstants.setLineEnd(edge.getAttributes(), arrow);
-            GraphConstants.setEndFill(edge.getAttributes(), true);
-
-            objects.add(edge);
-         }
-      }
-   }
-
-   /**
-    * Get the cell for the param context.
-    *
-    * @param cells the current cells
-    * @param objects all of graph's objects
-    * @param context the context
-    * @return context's cell
-    */
-   protected DefaultGraphCell getCell(Map<Object, DefaultGraphCell> cells, Set<Object> objects, ControllerContext context)
-   {
-      Object name = context.getName();
-      DefaultGraphCell cell = cells.get(name);
-      if (cell == null)
-      {
-         cell = createCell(name);
-         cells.put(name, cell);
-         objects.add(cell);
-         // fill in aliases as well
-         Set<Object> aliases = context.getAliases();
-         if (aliases != null && aliases.isEmpty() == false)
-         {
-            for(Object alias : aliases)
-            {
-               if (cells.containsKey(alias) == false)
-               {
-                  cells.put(alias, cell);
-               }
-            }
-         }
-      }
-
-      enhanceCell(cell, context);
-
-      return cell;
-   }
-
-   /**
-    * Enhance cell rendering.
-    *
-    * @param cell the cell to enhance
-    * @param context the context to get info from
-    */
-   protected void enhanceCell(DefaultGraphCell cell, ControllerContext context)
-   {
-      // TODO - enhance cell rendering with context's info
-   }
-
-   /**
-    * Do render graph.
-    *
-    * @param cells the cells
-    * @param writer the writter
-    * @param inset the inset
-    * @throws IOException for any IO error
-    */
-   protected static void render(Object[] cells, Writer writer, int inset) throws IOException
-   {
-      JGraph graph = new JGraph();
-      graph.getGraphLayoutCache().insert(cells);
-
-      Object[] roots = graph.getRoots();
-      Rectangle2D bounds = graph.toScreen(graph.getCellBounds(roots));
-      if (bounds != null)
-      {
-         // Constructs the svg generator used for painting the graph to
-         DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
-         Document document = domImpl.createDocument(null, "svg", null);
-         SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
-         svgGenerator.translate(-bounds.getX() + inset, -bounds.getY() + inset);
-         // Paints the graph to the svg generator with no double
-         // buffering enabled to make sure we get a vector image.
-         RepaintManager currentManager = RepaintManager.currentManager(graph);
-         currentManager.setDoubleBufferingEnabled(false);
-         graph.paint(svgGenerator);
-         // Writes the graph to the specified file as an SVG stream
-         svgGenerator.stream(writer, false);
-         currentManager.setDoubleBufferingEnabled(true);
-      }
-   }
-}
\ No newline at end of file

Deleted: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AllRenderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AllRenderer.java	2009-07-07 13:30:44 UTC (rev 90895)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/AllRenderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -1,53 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.mctools.grapher.render;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.kernel.spi.dependency.KernelController;
-import org.jboss.dependency.spi.ControllerStateModel;
-import org.jboss.dependency.spi.ControllerState;
-import org.jboss.dependency.spi.ControllerContext;
-import org.jgraph.graph.DefaultGraphCell;
-
-/**
- * Render all MC components.
- * 
- * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
- */
-public class AllRenderer extends AbstractRenderer
-{
-   protected void render(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects) throws IOException
-   {
-      ControllerStateModel model = controller.getStates();
-      for (ControllerState state : model)
-      {
-         Set<ControllerContext> contexts = controller.getContextsByState(state);
-         for (ControllerContext context : contexts)
-         {
-            renderContext(controller, cells, objects, context);
-         }
-      }
-   }
-}

Deleted: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/BeanRenderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/BeanRenderer.java	2009-07-07 13:30:44 UTC (rev 90895)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/BeanRenderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -1,63 +0,0 @@
-/*
- * JBoss, Home of Professional Open Source.
- * Copyright 2008, Red Hat Middleware LLC, and individual contributors
- * as indicated by the @author tags. See the copyright.txt file in the
- * distribution for a full listing of individual contributors.
- *
- * This is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as
- * published by the Free Software Foundation; either version 2.1 of
- * the License, or (at your option) any later version.
- *
- * This software 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
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this software; if not, write to the Free
- * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
- */
-package org.jboss.mctools.grapher.render;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-
-import org.jboss.dependency.spi.ControllerContext;
-import org.jboss.kernel.spi.dependency.KernelController;
-import org.jgraph.graph.DefaultGraphCell;
-
-/**
- * Render single bean.
- *
- * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
- */
-public class BeanRenderer extends AbstractRenderer
-{
-   private Object bean;
-
-   public BeanRenderer(Object bean)
-   {
-      if (bean == null)
-         throw new IllegalArgumentException("Null bean name");
-
-      this.bean = bean;
-   }
-
-   protected void render(KernelController controller, Map<Object, DefaultGraphCell> cells, Set<Object> objects) throws IOException
-   {
-      ControllerContext context = controller.getContext(bean, null);
-      if (context == null)
-         throw new IllegalArgumentException("No such context: " + bean);
-
-      renderContext(controller, cells, objects, context);
-   }
-
-   @Override
-   public String toString()
-   {
-      return super.toString() + "[bean=" + bean + "]";
-   }
-}
\ No newline at end of file

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/GIFRenderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/GIFRenderer.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/GIFRenderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,65 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.render;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.jboss.mctools.grapher.render.utils.GIFOutputStream;
+import org.jboss.mctools.grapher.render.utils.GraphUtilities;
+import org.jgraph.JGraph;
+
+/**
+ * Render gif image.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class GIFRenderer implements Renderer
+{
+   public void render(JGraph graph, OutputStream writer, int inset) throws IOException
+   {
+      if (graph.getModel().getRootCount() > 0)
+      {
+         BufferedImage img = GraphUtilities.toImage(graph, null, inset);
+         writer.write(convertToGif(img));
+         // Write to file
+         writer.flush();
+      }
+   }
+
+   /**
+    * Convert Image to GIF-encoded data, reducing the number of colors if needed
+    *
+    * @param image the image
+    * @return image bytes
+    * @throws IOException for any io error
+    */
+   protected static byte[] convertToGif(Image image) throws IOException
+   {
+      ByteArrayOutputStream out = new ByteArrayOutputStream();
+      GIFOutputStream.writeGIF(out, image);
+      return out.toByteArray();
+   }
+}

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/JPGRenderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/JPGRenderer.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/JPGRenderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,48 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.render;
+
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.io.OutputStream;
+import javax.imageio.ImageIO;
+
+import org.jgraph.JGraph;
+import org.jboss.mctools.grapher.render.utils.GraphUtilities;
+
+/**
+ * Render jpg image.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class JPGRenderer implements Renderer
+{
+   public void render(JGraph graph, OutputStream writer, int inset) throws IOException
+   {
+      if (graph.getModel().getRootCount() > 0)
+      {
+         BufferedImage img = GraphUtilities.toImage(graph, Color.WHITE, 5);
+         ImageIO.write(img, "jpg", writer);
+      }
+   }
+}
\ No newline at end of file

Modified: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/Renderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/Renderer.java	2009-07-07 13:30:44 UTC (rev 90895)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/Renderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -22,9 +22,9 @@
 package org.jboss.mctools.grapher.render;
 
 import java.io.IOException;
-import java.io.Writer;
+import java.io.OutputStream;
 
-import org.jboss.kernel.spi.dependency.KernelController;
+import org.jgraph.JGraph;
 
 /**
  * Renderer interface.
@@ -36,9 +36,10 @@
    /**
     * Do render.
     *
-    * @param controller the MC controller
-    * @param writer the writer to rende into
+    * @param graph the current graph
+    * @param writer the writer to render into
+    * @param inset the inset
     * @throws IOException for any error
     */
-   void render(KernelController controller, Writer writer) throws IOException;
+   void render(JGraph graph, OutputStream writer, int inset) throws IOException;
 }

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/SVGRenderer.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/SVGRenderer.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/SVGRenderer.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,66 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.render;
+
+import java.awt.geom.Rectangle2D;
+import java.io.IOException;
+import java.io.Writer;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import javax.swing.*;
+
+import org.apache.batik.dom.GenericDOMImplementation;
+import org.apache.batik.svggen.SVGGraphics2D;
+import org.jgraph.JGraph;
+import org.w3c.dom.DOMImplementation;
+import org.w3c.dom.Document;
+
+/**
+ * Render SVG image.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class SVGRenderer implements Renderer
+{
+   public void render(JGraph graph, OutputStream out, int inset) throws IOException
+   {
+      Object[] roots = graph.getRoots();
+      Rectangle2D bounds = graph.toScreen(graph.getCellBounds(roots));
+      if (bounds != null)
+      {
+         // Constructs the svg generator used for painting the graph to
+         DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
+         Document document = domImpl.createDocument(null, "svg", null);
+         SVGGraphics2D svgGenerator = new SVGGraphics2D(document);
+         svgGenerator.translate(-bounds.getX() + inset, -bounds.getY() + inset);
+         // Paints the graph to the svg generator with no double
+         // buffering enabled to make sure we get a vector image.
+         RepaintManager currentManager = RepaintManager.currentManager(graph);
+         currentManager.setDoubleBufferingEnabled(false);
+         graph.paint(svgGenerator);
+         // Writes the graph to the specified file as an SVG stream
+         Writer writer = new OutputStreamWriter(out);
+         svgGenerator.stream(writer, false);
+         currentManager.setDoubleBufferingEnabled(true);
+      }
+   }
+}

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GIFOutputStream.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GIFOutputStream.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GIFOutputStream.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,1071 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.render.utils;
+
+import java.awt.*;
+import java.awt.image.ImageObserver;
+import java.awt.image.PixelGrabber;
+import java.io.FilterOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+/**
+ * GifOutputStream.
+ * See code for the actual ownership and credits.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public class GIFOutputStream extends FilterOutputStream
+{
+   public static final int ORIGINAL_COLOR = 0;
+   public static final int BLACK_AND_WHITE = 1;
+   public static final int GRAYSCALE_16 = 2;
+   public static final int GRAYSCALE_256 = 3;
+   public static final int STANDARD_16_COLORS = 4;
+   public static final int STANDARD_256_COLORS = 5;
+   public static final int DITHERED_216_COLORS = 6;
+
+   public static final int NO_ERROR = 0;
+   public static final int IMAGE_LOAD_FAILED = 1;
+   public static final int TOO_MANY_COLORS = 2;
+   public static final int INVALID_COLOR_MODE = 3;
+
+   protected static final int BLACK_INDEX = 0;
+   protected static final int WHITE_INDEX = 1;
+
+   protected static final int[] standard16 =
+         {
+               0x000000,
+               0xFF0000, 0x00FF00, 0x0000FF,
+               0x00FFFF, 0xFF00FF, 0xFFFF00,
+               0x800000, 0x008000, 0x000080,
+               0x008080, 0x800080, 0x808000,
+               0x808080, 0xC0C0C0,
+               0xFFFFFF
+         };
+
+   protected static final int[] standard256 = new int[256];
+
+   protected static int ditherPattern[][] = {
+         {8, 184, 248, 216},
+         {120, 56, 152, 88},
+         {40, 232, 24, 200},
+         {168, 104, 136, 72}
+   };
+
+   protected int errorStatus = NO_ERROR;
+
+   static
+   {
+      // Set up a standard 256-color table.
+
+      int n, j, r, g, b;
+
+      standard256[0] = 0x000000;
+
+      n = 40;
+
+      // 0x33 multiples, starting at index 41 (black stored at index 40 gets replaced with 0xEE0000
+      for (r = 0; r < 6; ++r)
+         for (g = 0; g < 6; ++g)
+            for (b = 0; b < 6; ++b)
+               standard256[n++] = 0x330000 * r | 0x003300 * g | 0x000033 * b;
+
+      n = 1;
+
+      for (j = 0; j < 10; ++j)
+      {
+         // Shades of gray w/o 0x33 multiples, starting at index 1
+         standard256[j + 1] = 0x111111 * n;
+         // Shades of blue w/o 0x33 multiples, starting at index 11
+         standard256[j + 11] = 0x000011 * n;
+         // Shades of green w/o 0x33 multiples, starting at index 21
+         standard256[j + 21] = 0x001100 * n;
+         // Shades of red w/o 0x33 multiples, starting at index 31
+         standard256[j + 31] = 0x110000 * n;
+
+         ++n;
+
+         if (n % 3 == 0)
+            ++n;
+      }
+   }
+
+   public static int writeGIF(OutputStream out, Image image) throws IOException
+   {
+      return writeGIF(out, image, ORIGINAL_COLOR, null);
+   }
+
+   public static int writeGIF(OutputStream out, Image image, int colorMode) throws IOException
+   {
+      return writeGIF(out, image, colorMode, null);
+   }
+
+   public static int writeGIF(OutputStream out,
+                              Image image,
+                              int colorMode,
+                              Color transparentColor) throws IOException
+   {
+      GIFOutputStream gifOut = new GIFOutputStream(out);
+
+      gifOut.write(image, colorMode, transparentColor);
+
+      return gifOut.getErrorStatus();
+   }
+
+   public GIFOutputStream(OutputStream out)
+   {
+      super(out);
+   }
+
+   public int getErrorStatus()
+   {
+      return errorStatus;
+   }
+
+   public void write(Image image) throws IOException
+   {
+      write(image, ORIGINAL_COLOR, null);
+   }
+
+   public void write(Image image, int colorMode) throws IOException
+   {
+      write(image, colorMode, null);
+   }
+
+   public void write(Image image, Color transparentColor) throws IOException
+   {
+      write(image, ORIGINAL_COLOR, transparentColor);
+   }
+
+   public void write(Image image, int colorMode, Color transparentColor) throws IOException
+   {
+      errorStatus = NO_ERROR;
+
+      if (image == null)
+         return;
+
+      PixelGrabber pg = new PixelGrabber(image, 0, 0, -1, -1, true);
+
+      try
+      {
+         pg.grabPixels();
+      }
+      catch (InterruptedException e)
+      {
+         errorStatus = IMAGE_LOAD_FAILED;
+         return;
+      }
+
+      if ((pg.status() & ImageObserver.ABORT) != 0)
+      {
+         errorStatus = IMAGE_LOAD_FAILED;
+         return;
+      }
+
+      int[] pixels = (int[])pg.getPixels();
+      int width = pg.getWidth();
+      int height = pg.getHeight();
+      int colorCount = 0;
+      int[] colorTable = null;
+      byte[] bytePixels = null;
+
+      switch (colorMode)
+      {
+         case ORIGINAL_COLOR:
+            Hashtable colorSet = getColorSet(pixels);
+            colorCount = colorSet.size();
+            if (colorCount > 256)
+            {
+               errorStatus = TOO_MANY_COLORS;
+               return;
+            }
+            colorTable = createColorTable(colorSet, colorCount);
+            bytePixels = createBytePixels(pixels, colorSet);
+            break;
+
+         case BLACK_AND_WHITE:
+            colorCount = 2;
+            colorTable = createBWTable();
+            bytePixels = createBWBytePixels(pixels);
+            break;
+
+         case GRAYSCALE_16:
+            colorCount = 16;
+            colorTable = create16GrayTable();
+            bytePixels = create16GrayBytePixels(pixels);
+            break;
+
+         case GRAYSCALE_256:
+            colorCount = 256;
+            colorTable = create256GrayTable();
+            bytePixels = create256GrayBytePixels(pixels);
+            break;
+
+         case STANDARD_16_COLORS:
+            colorCount = 16;
+            colorTable = createStd16ColorTable();
+            bytePixels = createStd16ColorBytePixels(pixels);
+            break;
+
+         case STANDARD_256_COLORS:
+            colorCount = 256;
+            colorTable = createStd256ColorTable();
+            bytePixels = createStd256ColorBytePixels(pixels, width, false);
+            break;
+
+         case DITHERED_216_COLORS:
+            colorCount = 216;
+            colorTable = createStd216ColorTable();
+            bytePixels = createStd256ColorBytePixels(pixels, width, true);
+            break;
+
+         default:
+            errorStatus = INVALID_COLOR_MODE;
+            return;
+      }
+
+      pixels = null;
+
+      int cc1 = colorCount - 1;
+      int bitsPerPixel = 0;
+
+      while (cc1 != 0)
+      {
+         ++bitsPerPixel;
+         cc1 >>= 1;
+      }
+
+      writeGIFHeader(width, height, bitsPerPixel);
+
+      writeColorTable(colorTable, bitsPerPixel);
+
+      if (transparentColor != null)
+         writeGraphicControlExtension(transparentColor, colorTable);
+
+      writeImageDescriptor(width, height);
+
+      writeCompressedImageData(bytePixels, bitsPerPixel);
+
+      write(0x00); // Terminate picture data.
+
+      write(0x3B); // GIF file terminator.
+   }
+
+   protected Hashtable getColorSet(int[] pixels)
+   {
+      Hashtable colorSet = new Hashtable();
+      boolean[] checked = new boolean[pixels.length];
+      int needsChecking = pixels.length;
+      int color;
+      int colorIndex = 0;
+      Integer key;
+
+      for (int j = 0; j < pixels.length && needsChecking > 0; ++j)
+      {
+         if (!checked[j])
+         {
+            color = pixels[j] & 0x00FFFFFF;
+            checked[j] = true;
+            --needsChecking;
+
+            key = new Integer(color);
+            colorSet.put(key, new Integer(colorIndex));
+            if (++colorIndex > 256)
+               break;
+
+            for (int j2 = j + 1; j2 < pixels.length; ++j2)
+            {
+               if ((pixels[j2] & 0x00FFFFFF) == color)
+               {
+                  checked[j2] = true;
+                  --needsChecking;
+               }
+            }
+         }
+      }
+
+      if (colorIndex == 1)
+      {
+         if (colorSet.get(new Integer(0)) == null)
+            colorSet.put(new Integer(0), new Integer(1));
+         else
+            colorSet.put(new Integer(0xFFFFFF), new Integer(1));
+      }
+
+      return colorSet;
+   }
+
+   protected int[] createColorTable(Hashtable colorSet, int colorCount)
+   {
+      int[] colorTable = new int[colorCount];
+      Integer key;
+
+      for (Enumeration e = colorSet.keys(); e.hasMoreElements();)
+      {
+         key = (Integer)e.nextElement();
+         colorTable[((Integer)colorSet.get(key)).intValue()] = key.intValue();
+      }
+
+      return colorTable;
+   }
+
+   protected byte[] createBytePixels(int[] pixels, Hashtable colorSet)
+   {
+      byte[] bytePixels = new byte[pixels.length];
+      Integer key;
+      int colorIndex;
+
+      for (int j = 0; j < pixels.length; ++j)
+      {
+         key = new Integer(pixels[j] & 0x00FFFFFF);
+         colorIndex = ((Integer)colorSet.get(key)).intValue();
+         bytePixels[j] = (byte)colorIndex;
+      }
+
+      return bytePixels;
+   }
+
+   protected int[] createBWTable()
+   {
+      int[] colorTable = new int[2];
+
+      colorTable[BLACK_INDEX] = 0x000000;
+      colorTable[WHITE_INDEX] = 0xFFFFFF;
+
+      return colorTable;
+   }
+
+   protected byte[] createBWBytePixels(int[] pixels)
+   {
+      byte[] bytePixels = new byte[pixels.length];
+
+      for (int j = 0; j < pixels.length; ++j)
+      {
+         if (grayscaleValue(pixels[j]) < 0x80)
+            bytePixels[j] = (byte)BLACK_INDEX;
+         else
+            bytePixels[j] = (byte)WHITE_INDEX;
+      }
+
+      return bytePixels;
+   }
+
+   protected int[] create16GrayTable()
+   {
+      int[] colorTable = new int[16];
+
+      for (int j = 0; j < 16; ++j)
+         colorTable[j] = 0x111111 * j;
+
+      return colorTable;
+   }
+
+   protected byte[] create16GrayBytePixels(int[] pixels)
+   {
+      byte[] bytePixels = new byte[pixels.length];
+
+      for (int j = 0; j < pixels.length; ++j)
+      {
+         bytePixels[j] = (byte)(grayscaleValue(pixels[j]) / 16);
+      }
+
+      return bytePixels;
+   }
+
+   protected int[] create256GrayTable()
+   {
+      int[] colorTable = new int[256];
+
+      for (int j = 0; j < 256; ++j)
+         colorTable[j] = 0x010101 * j;
+
+      return colorTable;
+   }
+
+   protected byte[] create256GrayBytePixels(int[] pixels)
+   {
+      byte[] bytePixels = new byte[pixels.length];
+
+      for (int j = 0; j < pixels.length; ++j)
+      {
+         bytePixels[j] = (byte)grayscaleValue(pixels[j]);
+      }
+
+      return bytePixels;
+   }
+
+   protected int[] createStd16ColorTable()
+   {
+      int[] colorTable = new int[16];
+
+      for (int j = 0; j < 16; ++j)
+         colorTable[j] = standard16[j];
+
+      return colorTable;
+   }
+
+   protected byte[] createStd16ColorBytePixels(int[] pixels)
+   {
+      byte[] bytePixels = new byte[pixels.length];
+      int color;
+      int minError = 0;
+      int error;
+      int minIndex;
+
+      for (int j = 0; j < pixels.length; ++j)
+      {
+         color = pixels[j] & 0xFFFFFF;
+         minIndex = -1;
+
+         for (int k = 0; k < 16; ++k)
+         {
+            error = colorMatchError(color, standard16[k]);
+            if (error < minError || minIndex < 0)
+            {
+               minError = error;
+               minIndex = k;
+            }
+         }
+
+         bytePixels[j] = (byte)minIndex;
+      }
+
+      return bytePixels;
+   }
+
+   protected int[] createStd256ColorTable()
+   {
+      int[] colorTable = new int[256];
+
+      for (int j = 0; j < 256; ++j)
+         colorTable[j] = standard256[j];
+
+      return colorTable;
+   }
+
+   protected int[] createStd216ColorTable()
+   {
+      int[] colorTable = new int[216];
+
+      colorTable[0] = 0x000000;
+
+      for (int j = 1; j < 216; ++j)
+         colorTable[j] = standard256[j + 40];
+
+      return colorTable;
+   }
+
+   protected byte[] createStd256ColorBytePixels(int[] pixels, int width, boolean dither)
+   {
+      byte[] bytePixels = new byte[pixels.length];
+      int color;
+      int minError = 0;
+      int error;
+      int minIndex;
+      int sampleIndex;
+      int r, g, b;
+      int r2, g2, b2;
+      int x, y;
+      int threshold;
+
+      for (int j = 0; j < pixels.length; ++j)
+      {
+         color = pixels[j] & 0xFFFFFF;
+         minIndex = -1;
+
+         r = (color & 0xFF0000) >> 16;
+         g = (color & 0x00FF00) >> 8;
+         b = color & 0x0000FF;
+
+         r2 = r / 0x33;
+         g2 = g / 0x33;
+         b2 = b / 0x33;
+
+         if (dither)
+         {
+            x = j % width;
+            y = j / width;
+            threshold = ditherPattern[x % 4][y % 4] / 5;
+
+            if (r2 < 5 && r % 0x33 >= threshold)
+               ++r2;
+
+            if (g2 < 5 && g % 0x33 >= threshold)
+               ++g2;
+
+            if (b2 < 5 && b % 0x33 >= threshold)
+               ++b2;
+
+            bytePixels[j] = (byte)(r2 * 36 + g2 * 6 + b2);
+         }
+         else
+         {
+            // Try to match color to a 0x33-multiple color.
+
+            for (int r0 = r2; r0 <= r2 + 1 && r0 < 6; ++r0)
+            {
+               for (int g0 = g2; g0 <= g2 + 1 && g0 < 6; ++g0)
+               {
+                  for (int b0 = b2; b0 <= b2 + 1 && b0 < 6; ++b0)
+                  {
+                     sampleIndex = 40 + r0 * 36 + g0 * 6 + b0;
+                     if (sampleIndex == 40)
+                        sampleIndex = 0;
+
+                     error = colorMatchError(color, standard256[sampleIndex]);
+                     if (error < minError || minIndex < 0)
+                     {
+                        minError = error;
+                        minIndex = sampleIndex;
+                     }
+                  }
+               }
+            }
+
+            int shadeBase;
+            int shadeIndex;
+
+            // Try to match color to a 0x11-multiple pure primary shade.
+
+            if (r > g && r > b)
+            {
+               shadeBase = 30;
+               shadeIndex = (r + 8) / 0x11;
+            }
+            else if (g > r && g > b)
+            {
+               shadeBase = 20;
+               shadeIndex = (g + 8) / 0x11;
+            }
+            else
+            {
+               shadeBase = 10;
+               shadeIndex = (b + 8) / 0x11;
+            }
+
+            if (shadeIndex > 0)
+            {
+               shadeIndex -= (shadeIndex / 3);
+               sampleIndex = shadeBase + shadeIndex;
+               error = colorMatchError(color, standard256[sampleIndex]);
+               if (error < minError || minIndex < 0)
+               {
+                  minError = error;
+                  minIndex = sampleIndex;
+               }
+            }
+
+            // Try to match color to a 0x11-multiple gray.
+
+            shadeIndex = (grayscaleValue(color) + 8) / 0x11;
+            if (shadeIndex > 0)
+            {
+               shadeIndex -= (shadeIndex / 3);
+               sampleIndex = shadeIndex;
+               error = colorMatchError(color, standard256[sampleIndex]);
+               if (error < minError || minIndex < 0)
+               {
+                  minError = error;
+                  minIndex = sampleIndex;
+               }
+            }
+
+            bytePixels[j] = (byte)minIndex;
+         }
+      }
+
+      return bytePixels;
+   }
+
+   protected int grayscaleValue(int color)
+   {
+      int r = (color & 0xFF0000) >> 16;
+      int g = (color & 0x00FF00) >> 8;
+      int b = color & 0x0000FF;
+
+      return (r * 30 + g * 59 + b * 11) / 100;
+   }
+
+   protected int colorMatchError(int color1, int color2)
+   {
+      int r1 = (color1 & 0xFF0000) >> 16;
+      int g1 = (color1 & 0x00FF00) >> 8;
+      int b1 = color1 & 0x0000FF;
+      int r2 = (color2 & 0xFF0000) >> 16;
+      int g2 = (color2 & 0x00FF00) >> 8;
+      int b2 = color2 & 0x0000FF;
+      int dr = (r2 - r1) * 30;
+      int dg = (g2 - g1) * 59;
+      int db = (b2 - b1) * 11;
+
+      return (dr * dr + dg * dg + db * db) / 100;
+   }
+
+   protected void writeGIFHeader(int width, int height, int bitsPerPixel) throws IOException
+   {
+      write((int)'G');
+      write((int)'I');
+      write((int)'F');
+      write((int)'8');
+      write((int)'9');
+      write((int)'a');
+
+      writeGIFWord(width);
+      writeGIFWord(height);
+
+      int packedBits = 0x80; // Yes, there is a global color table, not ordered.
+
+      packedBits |= ((bitsPerPixel - 1) << 4) | (bitsPerPixel - 1);
+
+      write(packedBits);
+
+      write(0); // Background color index -- not used.
+
+      write(0); // Aspect ratio index -- not specified.
+   }
+
+   protected void writeColorTable(int[] colorTable, int bitsPerPixel) throws IOException
+   {
+      int colorCount = 1 << bitsPerPixel;
+
+      for (int j = 0; j < colorCount; ++j)
+      {
+         if (j < colorTable.length)
+            writeGIFColor(colorTable[j]);
+         else
+            writeGIFColor(0);
+      }
+   }
+
+   protected void writeGraphicControlExtension(Color transparentColor,
+                                               int[] colorTable) throws IOException
+   {
+      for (int j = 0; j < colorTable.length; ++j)
+      {
+         if (colorTable[j] == (transparentColor.getRGB() & 0xFFFFFF))
+         {
+            write(0x21); // Extension identifier.
+            write(0xF9); // Graphic Control Extension identifier.
+            write(0x04); // Block size, always 4.
+            write(0x01); // Sets transparent color bit. Other bits in this
+            //   packed field should be zero.
+            write(0x00); // Two bytes of delay time -- not used.
+            write(0x00);
+            write(j);    // Index of transparent color.
+            write(0x00); // Block terminator.
+         }
+      }
+   }
+
+   protected void writeImageDescriptor(int width, int height) throws IOException
+   {
+      write(0x2C); // Image descriptor identifier;
+
+      writeGIFWord(0); // left postion;
+      writeGIFWord(0); // top postion;
+      writeGIFWord(width);
+      writeGIFWord(height);
+
+      write(0); // No local color table, not interlaced.
+   }
+
+   protected void writeGIFWord(short word) throws IOException
+   {
+      writeGIFWord((int)word);
+   }
+
+   protected void writeGIFWord(int word) throws IOException
+   {
+      write(word & 0xFF);
+      write((word & 0xFF00) >> 8);
+   }
+
+   protected void writeGIFColor(Color color) throws IOException
+   {
+      writeGIFColor(color.getRGB());
+   }
+
+   protected void writeGIFColor(int color) throws IOException
+   {
+      write((color & 0xFF0000) >> 16);
+      write((color & 0xFF00) >> 8);
+      write(color & 0xFF);
+   }
+
+
+   /**
+    * *****************************************************************\
+    * |                                                                    |
+    * |  The following code is based on C code for GIF compression         |
+    * |  obtained from http://www.boutell.com                              |
+    * |                                                                    |
+    * |  Based on GIFENCOD by David Rowley <mgardi at watdscu.waterloo.edu>   |
+    * |  Modified by Marcel Wijkstra <wijkstra at fwi.uva.nl>                 |
+    * |  One version, Copyright (C) 1989 by Jef Poskanzer.                 |
+    * |  Heavily modified by Mouse, 1998-02-12.                            |
+    * |                                                                    |
+    * |  And now, modified and rendered in Java by Kerry Shetline, 2000,   |
+    * |  kerry at shetline.com                                                |
+    * |                                                                    |
+    * \*******************************************************************
+    */
+
+   protected int rl_pixel;
+   protected int rl_basecode;
+   protected int rl_count;
+   protected int rl_table_pixel;
+   protected int rl_table_max;
+   protected boolean just_cleared;
+   protected int out_bits;
+   protected int out_bits_init;
+   protected int out_count;
+   protected int out_bump;
+   protected int out_bump_init;
+   protected int out_clear;
+   protected int out_clear_init;
+   protected int max_ocodes;
+   protected int code_clear;
+   protected int code_eof;
+   protected int obuf;
+   protected int obits;
+   protected byte[] oblock = new byte[256];
+   protected int oblen;
+
+   protected final static int GIFBITS = 12;
+
+   protected void writeCompressedImageData(byte[] bytePixels, int bitsPerPixel)
+         throws IOException
+   {
+      int init_bits = bitsPerPixel;
+
+      if (init_bits < 2)
+         init_bits = 2;
+
+      write(init_bits);
+
+      int c;
+
+      obuf = 0;
+      obits = 0;
+      oblen = 0;
+      code_clear = 1 << init_bits;
+      code_eof = code_clear + 1;
+      rl_basecode = code_eof + 1;
+      out_bump_init = (1 << init_bits) - 1;
+      /* for images with a lot of runs, making out_clear_init larger will
+   give better compression. */
+      out_clear_init = (init_bits <= 2) ? 9 : (out_bump_init - 1);
+      out_bits_init = init_bits + 1;
+      max_ocodes = (1 << GIFBITS) - ((1 << (out_bits_init - 1)) + 3);
+      did_clear();
+      output(code_clear);
+      rl_count = 0;
+
+      for (int j = 0; j < bytePixels.length; ++j)
+      {
+         c = (int)bytePixels[j];
+         if (c < 0)
+            c += 256;
+
+         if ((rl_count > 0) && (c != rl_pixel))
+            rl_flush();
+
+         if (rl_pixel == c)
+         {
+            rl_count++;
+         }
+         else
+         {
+            rl_pixel = c;
+            rl_count = 1;
+         }
+      }
+
+      if (rl_count > 0)
+         rl_flush();
+
+      output(code_eof);
+      output_flush();
+   }
+
+
+   protected void write_block() throws IOException
+   {
+      write(oblen);
+      write(oblock, 0, oblen);
+      oblen = 0;
+   }
+
+   protected void block_out(int c) throws IOException
+   {
+      oblock[oblen++] = (byte)c;
+      if (oblen >= 255)
+         write_block();
+   }
+
+   protected void block_flush() throws IOException
+   {
+      if (oblen > 0)
+         write_block();
+   }
+
+   protected void output(int val) throws IOException
+   {
+      obuf |= val << obits;
+      obits += out_bits;
+      while (obits >= 8)
+      {
+         block_out(obuf & 0xFF);
+         obuf >>= 8;
+         obits -= 8;
+      }
+   }
+
+   protected void output_flush() throws IOException
+   {
+      if (obits > 0)
+         block_out(obuf);
+      block_flush();
+   }
+
+   protected void did_clear() throws IOException
+   {
+      out_bits = out_bits_init;
+      out_bump = out_bump_init;
+      out_clear = out_clear_init;
+      out_count = 0;
+      rl_table_max = 0;
+      just_cleared = true;
+   }
+
+   protected void output_plain(int c) throws IOException
+   {
+      just_cleared = false;
+      output(c);
+      out_count++;
+      if (out_count >= out_bump)
+      {
+         out_bits++;
+         out_bump += 1 << (out_bits - 1);
+      }
+      if (out_count >= out_clear)
+      {
+         output(code_clear);
+         did_clear();
+      }
+   }
+
+   protected int isqrt(int x)
+   {
+      int r;
+      int v;
+
+      if (x < 2)
+         return x;
+
+      for (v = x, r = 1; v != 0; v >>= 2, r <<= 1)
+         ;
+
+      while (true)
+      {
+         v = ((x / r) + r) / 2;
+         if ((v == r) || (v == r + 1))
+            return r;
+         r = v;
+      }
+   }
+
+   protected int compute_triangle_count(int count, int nrepcodes)
+   {
+      int perrep;
+      int cost;
+
+      cost = 0;
+      perrep = (nrepcodes * (nrepcodes + 1)) / 2;
+      while (count >= perrep)
+      {
+         cost += nrepcodes;
+         count -= perrep;
+      }
+      if (count > 0)
+      {
+         int n = isqrt(count);
+         while ((n * (n + 1)) >= 2 * count)
+            n--;
+         while ((n * (n + 1)) < 2 * count)
+            n++;
+         cost += n;
+      }
+
+      return cost;
+   }
+
+   protected void max_out_clear()
+   {
+      out_clear = max_ocodes;
+   }
+
+   protected void reset_out_clear() throws IOException
+   {
+      out_clear = out_clear_init;
+      if (out_count >= out_clear)
+      {
+         output(code_clear);
+         did_clear();
+      }
+   }
+
+   protected void rl_flush_fromclear(int count) throws IOException
+   {
+      int n;
+
+      max_out_clear();
+      rl_table_pixel = rl_pixel;
+      n = 1;
+      while (count > 0)
+      {
+         if (n == 1)
+         {
+            rl_table_max = 1;
+            output_plain(rl_pixel);
+            count--;
+         }
+         else if (count >= n)
+         {
+            rl_table_max = n;
+            output_plain(rl_basecode + n - 2);
+            count -= n;
+         }
+         else if (count == 1)
+         {
+            rl_table_max++;
+            output_plain(rl_pixel);
+            count = 0;
+         }
+         else
+         {
+            rl_table_max++;
+            output_plain(rl_basecode + count - 2);
+            count = 0;
+         }
+
+         if (out_count == 0)
+            n = 1;
+         else
+            n++;
+      }
+
+      reset_out_clear();
+   }
+
+   protected void rl_flush_clearorrep(int count) throws IOException
+   {
+      int withclr;
+
+      withclr = 1 + compute_triangle_count(count, max_ocodes);
+      if (withclr < count)
+      {
+         output(code_clear);
+         did_clear();
+         rl_flush_fromclear(count);
+      }
+      else
+      {
+         for (; count > 0; count--)
+            output_plain(rl_pixel);
+      }
+   }
+
+   protected void rl_flush_withtable(int count) throws IOException
+   {
+      int repmax;
+      int repleft;
+      int leftover;
+
+      repmax = count / rl_table_max;
+      leftover = count % rl_table_max;
+      repleft = (leftover != 0 ? 1 : 0);
+      if (out_count + repmax + repleft > max_ocodes)
+      {
+         repmax = max_ocodes - out_count;
+         leftover = count - (repmax * rl_table_max);
+         repleft = 1 + compute_triangle_count(leftover, max_ocodes);
+      }
+
+      if (1 + compute_triangle_count(count, max_ocodes) < repmax + repleft)
+      {
+         output(code_clear);
+         did_clear();
+         rl_flush_fromclear(count);
+         return;
+      }
+
+      max_out_clear();
+      for (; repmax > 0; repmax--)
+         output_plain(rl_basecode + rl_table_max - 2);
+      if (leftover != 0)
+      {
+         if (just_cleared)
+         {
+            rl_flush_fromclear(leftover);
+         }
+         else if (leftover == 1)
+         {
+            output_plain(rl_pixel);
+         }
+         else
+         {
+            output_plain(rl_basecode + leftover - 2);
+         }
+      }
+      reset_out_clear();
+   }
+
+   protected void rl_flush() throws IOException
+   {
+      if (rl_count == 1)
+      {
+         output_plain(rl_pixel);
+         rl_count = 0;
+         return;
+      }
+      if (just_cleared)
+      {
+         rl_flush_fromclear(rl_count);
+      }
+      else if ((rl_table_max < 2) || (rl_table_pixel != rl_pixel))
+      {
+         rl_flush_clearorrep(rl_count);
+      }
+      else
+      {
+         rl_flush_withtable(rl_count);
+      }
+
+      rl_count = 0;
+   }
+
+   /******** END OF IMPORTED GIF COMPRESSION CODE ********/
+}
\ No newline at end of file

Added: projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GraphUtilities.java
===================================================================
--- projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GraphUtilities.java	                        (rev 0)
+++ projects/mc-tools/grapher/trunk/src/main/java/org/jboss/mctools/grapher/render/utils/GraphUtilities.java	2009-07-07 16:33:41 UTC (rev 90896)
@@ -0,0 +1,79 @@
+/*
+ * JBoss, Home of Professional Open Source.
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags. See the copyright.txt file in the
+ * distribution for a full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jboss.mctools.grapher.render.utils;
+
+import java.awt.*;
+import java.awt.geom.Rectangle2D;
+import java.awt.image.BufferedImage;
+import javax.swing.*;
+
+import org.jgraph.JGraph;
+
+/**
+ * Graph utils.
+ *
+ * @author <a href="mailto:ales.justin at jboss.org">Ales Justin</a>
+ */
+public final class GraphUtilities
+{
+   /**
+    * Conver graph to image.
+    *
+    * @param graph the graph
+    * @param bg the bg color
+    * @param inset the inset
+    * @return new image
+    */
+   public static BufferedImage toImage(JGraph graph, Color bg, int inset)
+   {
+      Object[] cells = graph.getRoots();
+      Rectangle2D bounds = graph.getCellBounds(cells);
+      if (bounds != null)
+      {
+         graph.toScreen(bounds);
+//         ColorSpace cs = ColorSpace.getInstance(ColorSpace.CS_sRGB);
+//         ColorModel cm = new ComponentColorModel(cs, false, true, Transparency.OPAQUE, DataBuffer.TYPE_BYTE);
+         BufferedImage img = new BufferedImage((int)bounds.getWidth() + 2 * inset, (int)bounds.getHeight() + 2 * inset,
+               (bg != null) ? BufferedImage.TYPE_INT_RGB : BufferedImage.TYPE_INT_ARGB);
+         Graphics2D graphics = img.createGraphics();
+         if (bg != null)
+         {
+            graphics.setColor(bg);
+            graphics.fillRect(0, 0, img.getWidth(), img.getHeight());
+         }
+         else
+         {
+            graphics.setComposite(AlphaComposite.getInstance(AlphaComposite.CLEAR, 0.0f));
+            graphics.fillRect(0, 0, img.getWidth(), img.getHeight());
+            graphics.setComposite(AlphaComposite.SrcOver);
+         }
+         graphics.translate((int)(-bounds.getX() + inset), (int)(-bounds.getY() + inset));
+         boolean tmp = graph.isDoubleBuffered();
+         RepaintManager currentManager = RepaintManager.currentManager(graph);
+         currentManager.setDoubleBufferingEnabled(false);
+         graph.paint(graphics);
+         currentManager.setDoubleBufferingEnabled(tmp);
+         return img;
+      }
+      return null;
+   }
+}
\ No newline at end of file




More information about the jboss-cvs-commits mailing list