You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pp...@apache.org on 2010/10/05 21:22:19 UTC

svn commit: r1004775 [2/3] - in /openjpa/tools/trunk/openjpa-tools/src/main: java/org/apache/openjpa/swing/ java/org/apache/openjpa/swing/graph/ java/org/apache/openjpa/swing/layout/ java/org/apache/openjpa/swing/print/ java/org/apache/openjpa/tools/ j...

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRenderer.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRenderer.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRenderer.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRenderer.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,61 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+import java.awt.Graphics2D;
+import java.awt.geom.Path2D;
+
+import javax.swing.JLabel;
+
+
+
+
+/**
+ * Renders an edge with decorations such as arrows or line styles.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public interface EdgeRenderer<V> {
+    /**
+     * Render the given edge as the given path.
+     * Decorate with annotations or arrows, if possible.
+     * @param g the graphics context
+     * @param edgePath the coordinates for the edge.
+     * @param edge that actual edge instance being rendered
+     * @return true if Graphics context has been modified.
+     */
+    public void render(Graphics2D g, Path2D edgePath, Edge<V,V> edge);
+    
+    /**
+     * Gets the text for the edge label.
+     * 
+     * @param edge
+     * @return null if no label is to be printed. The text string should be returned without any 
+     * HTML tags. Because the text is used to determine the bounds and position where the label
+     * can be displayed.
+     */
+    public String getLabelText(Edge<V,V> edge);
+    
+    /**
+     * Gets the JLabel for the edge label text.
+     * 
+     * @param text The text obtained in a {@link #getLabelText(Edge)} method.
+     * It is done in two steps so that the label can be created with HTML decoration.
+     *  
+     * @return a JLabel to be displayed as edge label
+     */
+    public JLabel getLabel(String text);
+
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRenderer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRenderer.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRouter.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRouter.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRouter.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRouter.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,45 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+import java.awt.geom.Path2D;
+
+
+/**
+ * Computes the path for an edge between two vertices. The
+ * {@linkplain PlacementPlanner} provides the layout information such as the
+ * {@linkplain PlacementPlanner#getBounds(Object) geometric bounds} for the
+ * terminal nodes of a graph or whether a region of the layout is
+ * {@linkplain PlacementPlanner#isReachable(java.awt.geom.Point2D) occupied}.
+ * 
+ * @author Pinaki Poddar
+ * 
+ * @param <V>
+ *            the type of the nodes.
+ */
+public interface EdgeRouter<V> {
+    /**
+     * Compute a path for the given edge in consultation with the placement of
+     * the nodes as provided by the {@linkplain PlacementPlanner planner}.
+     * 
+     * @param edge
+     *            an edge for which the path is to be computed.
+     * @param source
+     *            holds the information about where the nodes are located.
+     * @param target
+     *            TODO
+     * @return a path for the edge.
+     */
+    Path2D route(Edge<V, V> edge, Connectable<V> source, Connectable<V> target);
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRouter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/EdgeRouter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphModel.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphModel.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphModel.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphModel.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,78 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+import java.util.Set;
+
+
+/**
+ * A model for a graph. 
+ * 
+ * @author Pinaki Poddar
+ *
+ * @param <V> the type of vertex
+ */
+public interface GraphModel<V> {
+    /**
+     * Add a vertex.
+     */
+    void addVertex(V v);
+    
+    /**
+     * Gets the vertices.
+     */
+    Iterable<V> getNodes();
+    
+    /**
+     * Gets the edges.
+     */
+    Iterable<Edge<V,V>> getEdges();
+    
+    /**
+     * Gets the outgoing edges of the given node.
+     */
+    Set<Edge<V,V>> getOutEdges(V v);
+    
+    /**
+     * Links two vertices.
+     * 
+     * @return an edge created by the current edge factory.
+     */
+    Edge<V,V> link(V v1, V v2);
+    
+    /**
+     * Adds an edge.
+     */
+    <V1 extends V,V2 extends V> void link(Edge<V1, V2> edge);
+    
+    /**
+     * Affirms if an edge exists between the given vertices.
+     */
+    boolean isLinked(V v1, V v2);
+    
+    /**
+     * Gets the edge between the vertices, if any.
+     */
+    Edge<V,V> getEdge(V v1, V v2);
+    
+    /**
+     * Sets the factory to create edges.
+     */
+    void setEdgeFactory(EdgeFactory<V,V> factory);
+    
+    /**
+     * Sets the factory to create edges.
+     */
+    EdgeFactory<V,V> getEdgeFactory();
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphModel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphModel.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphPanel.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphPanel.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphPanel.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphPanel.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,515 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Cursor;
+import java.awt.FontMetrics;
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Insets;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import java.awt.event.MouseMotionListener;
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+import javax.swing.BorderFactory;
+import javax.swing.CellRendererPane;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.border.Border;
+
+import org.apache.openjpa.swing.Geometry;
+import org.apache.openjpa.swing.layout.FRLayoutManager;
+
+/**
+ * Swing component for visualization of graph. The graph state is represented via {@linkplain GraphModel}
+ * interface. 
+ * <br>
+ * This implementation uses configurable factories to convert the vertices and edges
+ * to visual component and shape respectively. The vertices are converted to Swing components
+ * via {@link NodeViewFactory#getComponent(Object)}. The nodes of different types can be produced by 
+ * one or more registered factories. A {@link DefaultNodeFactory default factory} is used by default
+ * to simply a vertex as a JLabel.  
+ * <p>
+ * <B>Painting</B>: The Swing components for the vertices are added as children of this container   
+ * and hence their painting is controlled by the AWT painting framework itself. 
+ * <br>
+ * The shapes are likewise produced by a {@link EdgeViewFactory}. However, unlike vertices, the edge 
+ * shapes and annotations are rendered directly by this component via its {@link EdgeRenderer} interface.
+ * <br>
+ * This component lays out, by default, through a {@link FRLayoutManager experimental Layout Manager} that
+ * employs fore-directed spring layout algorithm for absolute positioning of the nodes. 
+ * 
+ * <p>
+ * <B>Event Management</B>: The vertices can be dragged around with mouse. The edges will be redrawn
+ * when a component is moved.
+ *  
+ * <B>Important:</B>Set node/edge factory before setting the graph model.
+ *  
+ * @author Pinaki Poddar
+ *
+ * @param <V> the type of graph nodes
+ */
+@SuppressWarnings("serial")
+public class GraphPanel<V> extends JPanel implements MouseListener, MouseMotionListener {
+    // the underlying graph data model
+    private GraphModel<V> model;
+    private Map<V, Connectable<V>> components = new HashMap<V, Connectable<V>>();
+    private Map<Edge<V,V>, Path2D> edgePaths = new HashMap<Edge<V,V>, Path2D>();
+    
+    private Map<Class<V>,NodeViewFactory<V>> nodeFactories;
+    protected NodeViewFactory<V> defaultNodeFactory;
+    
+    private Map<Class<? extends Edge<?,?>>, EdgeRenderer<V>> edgeRenderers;
+    private Map<Class<? extends Edge<?,?>>, EdgeRouter<V>> edgeRouters;
+    private EdgeRenderer<V> defaultEdgeRenderer;
+    private EdgeRouter<V> defaultEdgeRouter;
+    private List<Mask<V>> nodeMasks;
+    private List<Mask<Edge<V,V>>> edgeMasks;
+    private boolean showEdgeLabels = true;
+    private Rectangle dimension = new Rectangle(0,0,0,0);
+    private Rectangle cdimension = new Rectangle(0,0,0,0);
+    private Insets insets = new Insets(0,0,0,0);
+    
+    private static final String USER_OBJECT = "vertex";
+    
+    public GraphPanel() {
+        super(true);
+        setLayout(new FRLayoutManager(this));
+        setBorder(BorderFactory.createEmptyBorder(20, 20, 20, 20));
+        setOpaque(true);
+        setBackground(Color.WHITE);
+        defaultNodeFactory  = new DefaultNodeFactory<V>();
+        defaultEdgeRenderer = new DefaultEdgeRenderer<V>();
+        defaultEdgeRouter   = new RectilinearEdgeRouter<V>();
+        nodeMasks = new ArrayList<Mask<V>>();
+        edgeMasks = new ArrayList<Mask<Edge<V,V>>>();
+        addMouseListener(this);
+        addMouseMotionListener(this);
+    }
+    
+    public void setModel(GraphModel<V> graph) {
+        components.clear();
+        edgePaths.clear();
+        this.model = graph;
+        initialize();
+    }
+    
+    public GraphModel<V> getModel() {
+        return model;
+    }
+    
+    
+    /**
+     * Initializes the view.
+     * Creates the visual components for each graph node if they have not been created before.
+     */
+    private void initialize() {
+        if (model == null)
+            return;
+        for (V v : model.getNodes()) {
+            if (!components.containsKey(v)) {
+                if (mask(v)) continue;
+                Connectable<V> c = getNodeFactory(v).createComponent(v,null);
+                c.asComponent().putClientProperty(USER_OBJECT, v);
+                components.put(v,c);
+            }
+        }  
+        for (V v : model.getNodes()) {
+            if (mask(v)) continue;
+            Connectable<V> c = components.get(v);
+            Set<Edge<V,V>> edges = model.getOutEdges(v);
+            List<Connectable<V>> links = new ArrayList<Connectable<V>>();
+            for (Edge<V,V> e : edges) {
+                if (mask(e)) continue;
+                links.add(components.get(e.getTarget()));
+            }
+            add(c.asComponent(), links);
+        }
+    }
+    
+    /**
+     * Registers a factory to create visual widget for the given type of node.
+     * 
+     */
+    public void setNodeFactory(Class<V> type, NodeViewFactory<V> creator) {
+        if (nodeFactories == null) {
+            nodeFactories = new HashMap<Class<V>, NodeViewFactory<V>>();
+        }
+        nodeFactories.put(type, creator);
+    }
+    
+    /**
+     * Sets the node factory to be used as default.
+     * @param creator can not be null.
+     */
+    public void setDefaultNodeFactory(NodeViewFactory<V> creator) {
+        if (creator != null) {
+            defaultNodeFactory = creator;
+        } else {
+            throw new IllegalArgumentException("Can not set null factory as default");
+        }
+    }
+    
+    /**
+     * Gets the factory that creates widgets for the given node.
+     * If no specific factory has been registered for the type of the given node
+     * returns a default factory.
+     */
+    public NodeViewFactory<V> getNodeFactory(V node) {
+        if (nodeFactories != null && nodeFactories.containsKey(node.getClass()))
+            return nodeFactories.get(node.getClass());
+        return defaultNodeFactory;
+    }
+    
+    /**
+     * Gets the renderer that will draw the given edge.
+     */
+    public EdgeRenderer<V> getEdgeRenderer(Edge<V,V> edge) {
+        if (edgeRenderers != null && edgeRenderers.containsKey(edge.getClass()))
+            return edgeRenderers.get(edge.getClass());
+        return defaultEdgeRenderer;
+    }
+    
+    public void setEdgeRenderer(Class<? extends Edge<?,?>> edgeType, EdgeRenderer<V> renderer) {
+        if (edgeRenderers == null) {
+            edgeRenderers = new HashMap<Class<? extends Edge<?,?>>, EdgeRenderer<V>>();
+        }
+        edgeRenderers.put(edgeType, renderer);
+    }
+    
+    /**
+     * Gets the route that will find route for the given edge.
+     */
+    public EdgeRouter<V> getEdgeRouter(Edge<V,V> edge) {
+        if (edgeRouters != null && edgeRouters.containsKey(edge.getClass()))
+            return edgeRouters.get(edge.getClass());
+        return defaultEdgeRouter;
+    }
+    
+    public void setEdgeRouter(Class<Edge<?,?>> edgeType, EdgeRouter<V> router) {
+        if (edgeRouters == null) {
+            edgeRouters = new HashMap<Class<? extends Edge<?,?>>, EdgeRouter<V>>();
+        }
+        edgeRouters.put(edgeType, router);
+    }
+    
+    /**
+     * Sets the default renderer to be used for drawing edges.
+     * 
+     * @param renderer can not be null.
+     */
+    public void setDefaultEdgeRenderer(EdgeRenderer<V> renderer) {
+        if (renderer != null) {
+            defaultEdgeRenderer = renderer;
+        } else {
+            throw new IllegalArgumentException("Can not set null edge renderer as default");
+        }
+    }
+    
+    /**
+     * Gets the component corresponding to the given node.
+     */
+    private Connectable<V> getConnectable(V node) {
+        return components.get(node);
+    }
+    
+   
+    /**
+     * Overrides painting by drawing the edges directly.
+     */
+    @Override
+    public void paintComponent(Graphics g) {
+        if (model == null)
+            return;
+        super.paintComponent(g);  // paints the nodes as child components 
+        drawEdges((Graphics2D)g); // edges are drawn directly on the graphics surface
+    }
+    
+    private void drawEdges(Graphics2D g2) {
+        if (g2 == null)
+            return;
+        CellRendererPane labelRenderer = new CellRendererPane();
+        EdgeRouter<V> router = null;
+        for (Edge<V,V> edge : model.getEdges()) {
+            if (mask(edge)) continue;
+            router = getEdgeRouter(edge);
+            if (router == null) continue;
+            Path2D path = router.route(edge, 
+                    getConnectable(edge.getSource()), getConnectable(edge.getTarget()));
+            edgePaths.put(edge, path);
+            EdgeRenderer<V> edgeRenderer = getEdgeRenderer(edge);
+            if (edgeRenderer != null) {
+                Graphics2D gcopy = (Graphics2D)g2.create();
+                edgeRenderer.render(gcopy, path, edge);
+                if (showEdgeLabels) {
+                    String text = edgeRenderer.getLabelText(edge);
+                    Rectangle position = getTextPositionOnPath(gcopy, path, text);
+                    JLabel label = edgeRenderer.getLabel(text);
+                    labelRenderer.paintComponent(gcopy, label, this, position);
+                }
+            }
+        }
+    }
+    
+    Rectangle getTextPositionOnPath(Graphics g, Path2D path, String text) {
+        List<Point2D> pts = Geometry.getLineSegments(path);
+        Point2D p1 = null;
+        Point2D p2 = null; 
+        FontMetrics fm = g.getFontMetrics();
+        Rectangle2D S = fm.getStringBounds(text, g);
+        double sw = S.getWidth()*1.2; // if the text is rendered bold, will take more space
+        double sh = S.getHeight();
+        double dmax = 0;
+        Rectangle2D r = null;
+        for (int i = 0; i < pts.size()-1; i++) {
+            p1 = pts.get(i);
+            p2 = pts.get(i+1);
+            double dx = Math.abs(p1.getX() - p2.getX());
+            double dy = Math.abs(p1.getY() - p2.getY());
+            double d  = Math.max(dx, dy);
+            if (d > S.getWidth()) {
+                if (d > dmax) {
+                    dmax = d;
+                    r = new Rectangle2D.Double((p1.getX()+p2.getX()-sw)/2, 
+                            (p1.getY()+p2.getY())/2, sw, sh);
+                }
+            }
+        }
+        if (r == null) {
+            r = new Rectangle2D.Double((p1.getX()+p2.getX()-sw)/2, (p1.getY()+p2.getY()-sh)/2, sw, sh);
+        } 
+        return new Rectangle((int)r.getX(), (int)r.getY(), (int)r.getWidth(), (int)r.getHeight());
+    }
+    
+    /**
+     * Sets if the labels will be shown on the edges.
+     * 
+     */
+    public void setShowEdgeLabels(boolean flag) {
+        showEdgeLabels = flag;
+        repaint();
+    }
+    
+    /**
+     * Affirms if edge labels will be drawn.
+     * 
+     */
+    public boolean showEdgeLabels() {
+        return showEdgeLabels;
+    }
+
+    /** ------------------------------------------------------------------------------------
+     * Event management
+     * ------------------------------------------------------------------------------------
+     */
+    private Component _selected; // the currently selected node
+    private Point _dragStart;
+    private Point _selectedLocation;
+    private Border _preselectionBorder;
+    private Border BORDER_SELECTED = BorderFactory.createLineBorder(Color.RED, 3);
+    
+    boolean isSeleceted(Component c) {
+        return c == _selected;
+    }
+    
+    @Override
+    public void mouseClicked(MouseEvent evt) {
+        deselect();
+
+        Component c = select(evt.getPoint());
+        if (c != null) {
+             c.dispatchEvent(evt);
+        } else {
+            Edge<V,V> edge = findPathUnderMouse(evt);
+            if (edge != null) {
+                JOptionPane.showMessageDialog(this, "Clicked on " + edge);
+            }
+        }
+        
+    }
+
+    @Override
+    public void mouseEntered(MouseEvent e) {
+    }
+
+    @Override
+    public void mouseExited(MouseEvent e) {
+    }
+
+    @Override
+    public void mousePressed(MouseEvent evt) {
+        deselect();
+        Component c = select(evt.getPoint());
+        if (c != null) {
+            _selected = c;
+            _selectedLocation = c.getLocation();
+            _dragStart = evt.getPoint();
+        }
+    }
+
+    @Override
+    public void mouseReleased(MouseEvent evt) {
+        deselect();
+        this.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+    }
+
+    @Override
+    public void mouseDragged(MouseEvent evt) {
+        this.setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+        Point p = evt.getPoint();
+        if (_selected != null) {
+            Graphics g = getGraphics();
+            g.setClip(_dragStart.x, _dragStart.y, _dragStart.x-p.x, _dragStart.y - p.y);
+            p.translate(_selectedLocation.x-_dragStart.x, _selectedLocation.y-_dragStart.y);
+            setLocation(_selected, p.x, p.y);
+            repaint();
+        }
+    }
+
+    @Override
+    public void mouseMoved(MouseEvent evt) {
+    }
+    
+    Edge<V, V> findPathUnderMouse(MouseEvent evt) {
+        Point p = evt.getPoint();
+        for (Map.Entry<Edge<V,V>, Path2D> path : edgePaths.entrySet()) {
+            if (path.getValue().contains(p)) {
+                deselect();
+                return path.getKey();
+            }
+        }
+        return null;
+    }
+    
+    Component select(Point p) {
+        int n = getComponentCount();
+        for (int i = 0; i < n; i ++) {
+            Component c = getComponent(i);
+            if (c.getBounds().contains(p)) {
+                _selected = c;
+                if (c instanceof JComponent) {
+                    _preselectionBorder = ((JComponent)c).getBorder();
+                    ((JComponent)c).setBorder(BORDER_SELECTED);
+                }
+                return c;
+            }
+        }
+        return null;
+    }
+    
+    void deselect() {
+        if (_selected == null)
+            return;
+        if (_selected instanceof JComponent) {
+            ((JComponent)_selected).setBorder(_preselectionBorder);
+        }
+        _selected = null;
+    }
+    
+    void setLocation(Component c, int px, int py) {
+        dimension = getBounds(dimension);
+        insets = getInsets(insets);
+        cdimension = c.getBounds(cdimension);
+        c.setLocation(Math.min(Math.max(px, insets.left), dimension.width - insets.right - cdimension.width),
+                      Math.min(Math.max(py, insets.top), dimension.height - insets.bottom - cdimension.height));
+    }
+    
+    // Masking
+    
+    boolean mask(V v) {
+        for (Mask<V> mask : nodeMasks) {
+            if (mask.apply(v)) 
+                return true;
+        }
+        return false;
+    }
+    
+    boolean mask(Edge<V,V> e) {
+        for (Mask<Edge<V,V>> mask : edgeMasks) {
+            if (mask.apply(e)) 
+                return true;
+        }
+        return false;
+    }
+    
+    public GraphPanel<V> addNodeMask(Mask<V> mask) {
+        nodeMasks.add(mask);
+        repaint();
+        return this;
+    }
+    
+    public GraphPanel<V> removeNodeMask(Mask<V> mask) {
+        nodeMasks.add(mask);
+        repaint();
+        return this;
+    }
+    
+    public List<Mask<V>> getNodeMasks() {
+        return Collections.unmodifiableList(nodeMasks);
+    }
+    public GraphPanel<V> addEdgeMask(Mask<Edge<V,V>> mask) {
+        edgeMasks.add(mask);
+        repaint();
+        return this;
+    }
+    public GraphPanel<V> removeEdgeMask(Mask<Edge<V,V>> mask) {
+        edgeMasks.add(mask);
+        repaint();
+        return this;
+    }
+    
+    public List<Mask<Edge<V,V>>> getEdgeMasks() {
+        return Collections.unmodifiableList(edgeMasks);
+    }
+    
+    /**
+     * Create a default model of 24 simple JLabel with random edges 
+     * for testing.
+     */
+    public static GraphModel<Object> createDefaultGraphModel() {
+        GraphModel<Object> model = new DefaultGraphModel<Object>();
+        Random random = new Random(System.currentTimeMillis());
+        int N = 24;
+        
+        String[] nodes = new String[N];
+        for (int i = 1; i <= N; i++) {
+            nodes[i-1] = "Label-"+i;
+        }
+        model.link(nodes[0], nodes[1]);
+        for (int i = 0; i < N; i++) {
+            for (int j = 0; j < N; j++) {
+                if (i != j && random.nextDouble() < 0.1) {
+                    model.link(nodes[i], nodes[j]);
+                }
+            }
+        }
+        return model;
+    }
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphPanel.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/GraphPanel.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/Mask.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/Mask.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/Mask.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/Mask.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,25 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+/**
+ * A predicate that can be applied to nodes/edges of the graph.
+ * 
+ * @author Pinaki Poddar
+ *
+ * @param <V>
+ */
+public interface Mask<V> {
+    boolean apply(V v);
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/Mask.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/Mask.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/NodeViewFactory.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/NodeViewFactory.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/NodeViewFactory.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/NodeViewFactory.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,34 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+import java.awt.Graphics;
+
+
+/**
+ * Responsible for creating a Swing component out of a node.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public interface NodeViewFactory<V> {
+    
+    /**
+     * Create a lightweight Swing component as a visual representation of the given node.
+     * @param node
+     * @param g
+     * @return
+     */
+    Connectable<V> createComponent(V node, Graphics g);
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/NodeViewFactory.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/NodeViewFactory.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/RectilinearEdgeRouter.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/RectilinearEdgeRouter.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/RectilinearEdgeRouter.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/RectilinearEdgeRouter.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,70 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.graph;
+
+import java.awt.geom.Line2D;
+import java.awt.geom.Path2D;
+import java.awt.geom.Rectangle2D;
+
+import org.apache.openjpa.swing.Geometry;
+
+/**
+ * This implementation computes a rectilinear path between the terminal
+ * nodes.
+ * 
+ * @see Geometry#getConnector(Rectangle2D, Rectangle2D)
+ * 
+ * @param <V>
+ */
+
+public class RectilinearEdgeRouter<V> implements EdgeRouter<V> {
+    
+    public Path2D route(Edge<V, V> edge, Connectable<V> source, Connectable<V> target) {
+        Line2D[] exitPins = null;
+        Line2D[] entryPins = null;
+
+        exitPins = source.getExitPins(edge, target);
+        entryPins = target.getEntryPins(edge, source);
+
+        Line2D[] pair = matchClosestEntryExitPinPair(exitPins, entryPins);
+        return Geometry.getConnector(pair[0], pair[1]);
+    }
+
+    /**
+     * Finds the exit-entry pin pair that are closest to each other.
+     * 
+     * @param exitPins
+     *            array of exit pins (must contain at least one element)
+     * @param entryPins
+     *            array of entry pins (must contain at least one element)
+     * @return 2 line segments, 0-the elements in the exit pin, 1-st element
+     *         is the entry pin.
+     */
+    Line2D[] matchClosestEntryExitPinPair(Line2D[] exitPins, Line2D[] entryPins) {
+        double dmin = Double.MAX_VALUE;
+        Line2D[] closest = new Line2D[2];
+        for (Line2D exit : exitPins) {
+            for (Line2D entry : entryPins) {
+                double d = exit.getP2().distance(entry.getP1());
+                if (d < dmin) {
+                    closest[0] = exit;
+                    closest[1] = entry;
+                    dmin = d;
+                }
+            }
+        }
+        return closest;
+    }
+
+}
\ No newline at end of file

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/RectilinearEdgeRouter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/graph/RectilinearEdgeRouter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/FRLayoutManager.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/FRLayoutManager.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/FRLayoutManager.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/FRLayoutManager.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,573 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.LayoutManager2;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Rectangle2D;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+
+
+/**
+ * A layout manager to position the components absolutely using 
+ * <A HRE="http://www.cs.brown.edu/~rt/gdhandbook/chapters/force-directed.pdf">
+ * Fruchterman-Reingold force-directed algorithm</A>. 
+ * 
+ * This algorithm determines placement of the components by repulsive and attractive forces.
+ * Repulsive force exists between any two components and is inversely proportional to the
+ * {@link #distance(Rectangle2D, Rectangle2D) distance} between them.
+ * <br>
+ * Attractive force exists between connected components. The connection between the
+ * components can be added by the caller {@linkplain #addNeighbours(Component, Collection) directly} 
+ * or {@linkplain #addLayoutComponent(Component, Object) implicitly} while adding the component
+ * to the container.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class FRLayoutManager implements LayoutManager2, Serializable {
+    /**
+     * Each component knows which other component it is connected to
+     */
+    private Map<Component, List<Component>> layout;
+    
+    /**
+     * Cache of each component's bounds during last layout computation.
+     */
+    private Map<Component, Rectangle2D> bounds;
+    
+    private boolean _dirty;
+    private Dimension maxSize;
+    private Dimension minSize;
+    private Dimension preferredSize;
+    private Dimension size;
+    private double aspect = 1.5;
+    private double coefficient;
+    private double relax;
+    private boolean randomInitialization = true;
+    
+    private static final double EPSILON = 1.0E-06;
+    
+    public FRLayoutManager(Container c) {
+        layout = new HashMap<Component, List<Component>>();
+        bounds = new HashMap<Component, Rectangle2D>();
+        coefficient = 0.75;
+        relax = 1.2;
+    }
+    
+    public void addNeighbours(Component comp, Collection<Component> neighbours) {
+        List<Component> list = layout.get(comp);
+        if (list == null) {
+            list = new ArrayList<Component>();
+            layout.put(comp, list);
+        }
+        list.addAll(neighbours);
+    }
+    
+    /**
+     * Adds a component to be laid out. The constraints must be in the form of
+     * list of other components in the same container.
+     */
+    @Override
+    public void addLayoutComponent(Component comp, Object constraints) {
+        log("addLayoutComponent: " + comp + " constraints " + constraints);
+        layout.put(comp, (List<Component>)constraints);
+        _dirty = true;
+    }
+
+    @Override
+    public float getLayoutAlignmentX(Container target) {
+        log("getLayoutAlignmentX: " + target);
+        return 0;
+    }
+
+    @Override
+    public float getLayoutAlignmentY(Container target) {
+        log("getLayoutAlignmentY: " + target);
+        return 0;
+    }
+
+    @Override
+    public void invalidateLayout(Container target) {
+        info("FRLayoutManager.invalidateLayout");
+        _dirty = true;
+    }
+
+    @Override
+    public void addLayoutComponent(String name, Component comp) {
+        log("addLayoutComponent: " + comp + " name " + name);
+        _dirty = true;
+        layout.put(comp, null);
+    }
+    
+    private Map<Component,Rectangle2D> initializeBoundsRandom(Container parent) {
+        Set<Component> components = layout.keySet();
+        size = parent.getSize();
+        Insets insets = parent.getInsets();
+        info("initializeBoundsRandom: " + toString("Parent Area ", size) + " No of components " 
+                + components.size() + " Layout components " + layout.size());
+        Random rng = new Random(System.currentTimeMillis());
+        Map<Component,Rectangle2D> bounds = new HashMap<Component,Rectangle2D>();
+        for (Component c : components) {
+            Point location = c.getLocation();
+            Dimension dc = c.getPreferredSize();
+            if (location.x == 0 && location.y == 0) {
+                double x0 = 0.0;
+                double y0 = 0.0;
+                Rectangle2D b = new Rectangle2D.Double(x0,y0, dc.width, dc.height);
+                int trial = 0;
+                do {
+                    x0 = rng.nextDouble()*(size.width-insets.left-insets.right);
+                    y0 = rng.nextDouble()*(size.height-insets.top-insets.bottom);
+                    b.setRect(x0, y0, dc.width, dc.height);
+                    trial++;
+                } while (trial < 10 && !overlaps(b, bounds.values()));
+                bounds.put(c, b);
+                log(toString("Initialize bounds ", b));
+            } else {
+                bounds.put(c, new Rectangle2D.Double(location.x, location.y, dc.width, dc.height));
+            }
+        }
+        return bounds;
+    }
+    
+    boolean overlaps(Rectangle2D b, Collection<Rectangle2D> other) {
+        for (Rectangle2D o : other) {
+            if (o.intersects(b)) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    
+    private Map<Component,Rectangle2D> initializeBoundsGrid(Container parent) {
+        Set<Component> components = layout.keySet();
+        size = parent.getSize();
+        Insets insets = parent.getInsets();
+        info("initializeBoundsGrid:" + toString("Parent Area ", size));
+        Map<Component,Rectangle2D> bounds = new HashMap<Component,Rectangle2D>();
+        
+        int T = components.size();
+        double W = size.width-insets.left-insets.right;
+        double H = size.height-insets.top-insets.bottom;
+        double w = 0.0;
+        double h = 0.0;
+        
+        for (Component c : components) {
+            Dimension dc = c.getPreferredSize();
+            w += w + dc.getWidth();
+            h += h + dc.getHeight();
+        }
+        w = w/T;
+        h = h/T;
+        
+        double M = W/w;
+        double N = H/h;
+        double f = Math.sqrt(T/(M*N));
+        
+        long iM = (long)Math.ceil(M*f);
+        long iN = (long)Math.ceil(N*f);
+
+        double gx = W/iM;
+        double gy = H/iN;
+        
+        int i = 0;
+        for (Component c : components) {
+            Dimension dc = c.getPreferredSize();
+            double x0 = gx*(i%iM) + insets.left + (gx-dc.width)/2;
+            double y0 = gy*(i/iN) + insets.top  + (gy-dc.height)/2;
+            i++;
+            bounds.put(c, new Rectangle2D.Double(x0, y0, dc.width, dc.height));
+            log(toString("Initialized bounds ",bounds.get(c)));
+        }
+        return bounds;
+    }
+
+    double[] layoutQuality(Map<Component,Rectangle2D> bounds) {
+        double overlap = 0.0;
+        double wirelength = 0.0;
+        int nOverlap = 0;
+        int nEdge = 0;
+        for (Component c1 : bounds.keySet()) {
+            Rectangle2D r1 = bounds.get(c1);
+            for (Component c2 : bounds.keySet()) {
+                if (c1 == c2) continue;
+                Rectangle2D r2 = bounds.get(c2);
+                if (r1.intersects(r2)) {
+                    Rectangle2D o = r1.createIntersection(r2);
+                    overlap += o.getWidth()*o.getHeight();
+                    nOverlap++;
+                }
+                
+            }
+            List<Component> neighbours = getNeighbours(c1);
+            if (neighbours == null)
+                continue;
+            for (Component c2 : neighbours) {
+                Rectangle2D r2 = bounds.get(c2);
+                wirelength += new Vector2D(r1.getCenterX()-r2.getCenterX(), r1.getCenterY()-r2.getCenterY()).norm();
+                nEdge++;
+            }
+        }
+        return new double[]{nOverlap, overlap, nEdge, wirelength/Math.max(1, nEdge)};
+    }
+    
+    
+    private boolean isInitialized() {
+        Set<Component> components = layout.keySet();
+        for (Component c : components) {
+            Point location = c.getLocation();
+            if (location.x != 0 || location.y != 0) {
+                return true;
+            }
+        }
+        info("Initializing layout....");
+        return false;
+    }
+    
+    void resize(Dimension newSize, Dimension oldSize, Insets insets) {
+        double scalex = newSize.getWidth()/oldSize.width;
+        double scaley = newSize.getHeight()/oldSize.height;
+        if (Math.abs(scalex-1.0) < 0.01 && Math.abs(scaley - 1) < 0.01) 
+            return;
+        AffineTransform transform = new AffineTransform();
+        info("Resizing from " + toString("old size ",oldSize) + " to " + toString(" new size ", newSize));
+        double dx = insets.left*(1-scalex);
+        double dy = insets.top*(1-scaley);
+        transform.scale(scalex, scaley);
+        transform.translate(dx,dy);
+        info("Transform " + transform);
+        Set<Component> components = layout.keySet();
+        for (Component c : components) {
+            Point oldPoint = c.getLocation();
+            Point newPoint = new Point(0,0);
+            transform.transform(oldPoint, newPoint);
+            Dimension oldDim = c.getSize();
+            c.setBounds(newPoint.x, newPoint.y, oldDim.width, oldDim.height);
+            bounds.put(c, new Rectangle2D.Double(newPoint.x, newPoint.y, oldDim.width, oldDim.height));
+        }
+    }
+    
+    void find(Container parent) {
+        if (!equals(size, parent.getSize())) {
+//            System.err.println("Container size changed " + toString("Container ",parent.getSize()) + toString(" Cached ", size));
+        }
+        for (Component c : layout.keySet()) {
+            Rectangle actual = c.getBounds();
+            Rectangle2D cached = bounds.get(c);
+            if (cached == null) {
+//                System.err.println("No cached data");
+                continue;
+            }
+            if (actual.x == 0 && actual.y == 0) {
+//                System.err.println("No location assigned : " + c);
+            }
+            if (!equalsLocation(actual, cached)) {
+//                System.err.println("Location different : " + toString("Actual ",actual) + toString(" Cached", cached));
+            }
+            if (!equalsSize(actual, cached)) {
+//                System.err.println("Dimension different : " + toString("Actual ",actual) + toString(" Cached", cached));
+            }
+        }
+    }
+    
+    boolean equals(Dimension a, Dimension b) {
+        if (a == null) {
+            return b == null;
+        } else {
+            if (b == null) {
+                return false;
+            } else {
+                return a.width == b.width && a.height == b.height;
+            }
+        }
+    }
+    
+    boolean equalsLocation(Rectangle a, Rectangle2D b) {
+        if (a == null) {
+            return b == null;
+        } else {
+            if (b == null) {
+                return false;
+            } else {
+                return Math.abs(a.x - b.getX()) < 1 && Math.abs(a.y-b.getY()) < 1;
+            }
+        }
+    }
+    boolean equalsSize(Rectangle a, Rectangle2D b) {
+        if (a == null) {
+            return b == null;
+        } else {
+            if (b == null) {
+                return false;
+            } else {
+                return Math.abs(a.width - b.getWidth()) < 1 && Math.abs(a.height-b.getHeight()) < 1;
+            }
+        }
+    }
+    
+    /**
+     * Determines the location and dimension of the components in this layout.
+     * First compares the cached data against the parent's components to determine
+     * why the layout operation has been triggered -- for example the parent may have
+     * been resized, or a new component has been added(removed) to(from) the container or
+     * one or more component size has been changed. Once the cause has been determined,
+     * invokes appropriate subroutine to recompute the bounds of the current set of
+     * components. 
+     * 
+     */
+    @Override
+    public void layoutContainer(Container parent) {
+//        find(parent);
+        if (isInitialized()) {
+            resize(parent.getSize(),size, parent.getInsets());
+            size = new Dimension(parent.getSize());
+            _dirty = false;
+            return;
+        } 
+        
+        bounds = randomInitialization 
+                ? initializeBoundsRandom(parent)
+                : initializeBoundsGrid(parent);
+                
+        double[] quality = layoutQuality(bounds);                
+        info("Initial layout quality " + quality[0] + " Overlap = " + quality[1] + 
+                " average edge length " + quality[3] + " of " + quality[2] + " edges");                
+        coefficient = Math.sqrt(area(parent.getSize())/layout.size());
+        boolean done = false;
+        double temperature = 100;//area(parent.getSize())/Math.sqrt(components.length);
+        int max = 20;
+        for (int i = 0; !done ; i++) {
+            double displacement = step(parent, bounds, temperature);
+            log("------------------ Step " + i + " Displacement = " + displacement + " --------------------");
+            done = i > max || displacement < 10 || layoutQuality(bounds)[0] <= 1;
+            temperature = Math.max(1.0, temperature*0.99);
+        }
+        Set<Component> components = layout.keySet();
+        for (Component c : components) {
+            Rectangle2D r = bounds.get(c);
+            c.setBounds((int)r.getX(), (int)r.getY(), (int)r.getWidth(), (int)r.getHeight());
+        }
+        quality = layoutQuality(bounds);                
+        info("Final layout quality " + quality[0] + " Overlap = " + quality[1] + 
+                " average edge length " + quality[3] + " of " + quality[2] + " edges");                
+        _dirty = false;
+    }
+    
+    /**
+     * Arrange the components by their constraints. 
+     * @param parent
+     * @return
+     */
+    private double step(Container parent, Map<Component,Rectangle2D> bounds, double stepSize) {
+        Set<Component> components = layout.keySet();
+        Map<Component, Vector2D> displacements = new HashMap<Component, Vector2D>();
+        for (Component c1 : components) {
+            Vector2D disp = new Vector2D(0,0);
+            displacements.put(c1, disp);
+            Rectangle2D r1 = bounds.get(c1);
+            for (Component c2 : components) {
+                if (c1 == c2) continue;
+                Rectangle2D r2 = bounds.get(c2);
+                Vector2D delta = distance(r1,r2);
+                Vector2D repulsion = delta.copy().times(coefficient*coefficient/Math.max(EPSILON, delta.normSq()));
+                log("Distance " + delta + " Repulsion = " + repulsion);
+                disp.add(repulsion);
+            }
+        }
+        
+        for (Component c1 : components) {
+            List<Component> neighbours = getNeighbours(c1);
+            if (neighbours == null || neighbours.isEmpty()) continue;
+            Rectangle2D r1 = bounds.get(c1);
+            for (int j = 0; j < neighbours.size(); j++) {
+                Component c2 = neighbours.get(j);
+                if (c1 == c2) continue;
+                Rectangle2D r2 = bounds.get(c2);
+                Vector2D delta = distance(r1,r2);
+                Vector2D attraction = delta.copy().times(delta.norm()/coefficient);
+                log("Distance " + delta + " Attraction = " + attraction);
+                displacements.get(c1).add(attraction.minus());
+                displacements.get(c1).add(attraction.minus().minus());
+            }
+        }
+        double totalDisplacement = normalize(displacements, stepSize);
+        Rectangle R = parent.getBounds();
+        Insets insets = parent.getInsets();
+        for (Component c : components) {
+            Rectangle2D r = bounds.get(c);
+            Vector2D disp = displacements.get(c);
+            Vector2D newPosition = new Vector2D(r.getX() + disp.x, r.getY() + disp.y);
+            Dimension dc = c.getPreferredSize();
+            newPosition.x = bound(newPosition.x, insets.left, R.width - insets.right - dc.width);
+            newPosition.y = bound(newPosition.y, insets.top,  R.height - insets.bottom - dc.height);
+            bounds.put(c, new Rectangle2D.Double(newPosition.x, newPosition.y, r.getWidth(), r.getHeight()));
+            log("Component Displacement " + disp + "Position new : " + newPosition + " Old " + r.getX() + "," + r.getY());
+        }
+        return totalDisplacement;
+    }
+    
+    double normalize(Map<Component, Vector2D> displacements, double limit) {
+        double sumx = 0.0;
+        double sumy = 0.0;
+        int N = displacements.size();
+        
+        for (Map.Entry<Component, Vector2D> e : displacements.entrySet()) {
+            Vector2D d = e.getValue();
+            sumx += Math.abs(d.x);
+            sumy += Math.abs(d.y);
+        }
+        double total = 0.0;
+        log("Total displacement X= " + sumx + " Y=" + sumy + " Limit " + limit*N);
+        boolean normalize = (sumx > limit*N || sumy > limit*N);
+        double factor = normalize ? limit*N/Math.max(sumx, sumy) : 1.0;
+        for (Map.Entry<Component, Vector2D> e : displacements.entrySet()) {
+            Vector2D d = e.getValue();
+            if (normalize)
+                d.times(factor);
+            total += d.norm();
+        }
+        return total;
+    }
+    
+    List<Component> getNeighbours(Component c) {
+        return layout.get(c);
+    }
+    
+    @Override
+    public Dimension maximumLayoutSize(Container target) {
+        double area = 0.0;
+        if (_dirty || maxSize == null) {
+            info("Computing maximumLayoutSize: current value " + maxSize);
+            for (Component c : layout.keySet()) {
+                area += area(c.getMaximumSize());
+            }
+            maxSize = calculateDimension(area);
+        }
+        info("maximumLayoutSize: " + maxSize);
+        return maxSize;
+    }
+
+    @Override
+    public Dimension minimumLayoutSize(Container parent) {
+        double area = 0.0;
+        if (_dirty || minSize == null) {
+            info("Computing minimumLayoutSize: current value " + minSize);
+            for (Component c : layout.keySet()) {
+                area += area(c.getMinimumSize());
+            }
+            minSize = calculateDimension(area);
+        }
+        info("minimumLayoutSize: " + minSize);
+        return minSize;
+    }
+
+    @Override
+    public Dimension preferredLayoutSize(Container parent) {
+        double area = 0.0;
+        if (_dirty || preferredSize == null) {
+            info("Computing preferredLayoutSize: " + toString("current value ", preferredSize));
+            for (Component c : layout.keySet()) {
+                area += area(c.getPreferredSize());
+            }
+            preferredSize = calculateDimension(area);
+        }
+        log(toString("preferredLayoutSize: ", preferredSize));
+        return preferredSize;
+    }
+
+    @Override
+    public void removeLayoutComponent(Component comp) {
+        log("removeLayoutComponent: " + comp);
+        _dirty = true;
+        layout.remove(comp);
+    }
+    
+    private double area(Dimension d) {
+        return d.width * d.height;
+    }
+    
+    private Vector2D distance(Rectangle2D r1, Rectangle2D r2) {
+        double dx = r1.getCenterX() - r2.getCenterX();
+        double dy = r1.getCenterY() - r2.getCenterY();
+        r1.intersects(r2);
+        double fx = 1.0;
+        double fy = 1.0;
+        if (r1.intersects(r2)) {
+            Rectangle2D ir = r1.createIntersection(r2);
+            fx *= ir.getWidth();
+            fy *= ir.getHeight();
+        }
+        return new Vector2D(dx/fx,dy/fy).nudge(EPSILON);
+    }
+    
+    Dimension calculateDimension(double area) {
+        double w = Math.sqrt(area*aspect)*relax;
+        double h = Math.sqrt(area/aspect)*relax;
+        return new Dimension((int)w,(int)h);
+    }
+    double attraction(double x) {
+        return x*x/coefficient;
+    }
+    
+    double repulsion(double x) {
+        return coefficient*coefficient/x;
+    }
+    
+    double bound(double a, double min, double max) {
+        if (min > max) {
+//            throw new IllegalArgumentException("Min = " + min + " Max = " + max);
+            return a;
+        }
+        if (a < min) a = min;
+        if (a > max) a = max;
+        return a;
+    }
+    
+    private void log(String s) {
+//      System.err.println(s);
+    }
+    private void info(String s) {
+//      System.err.println(s);
+    }
+    private String toString(String s, Dimension d) {
+        if (d == null) return s + ":" + d;
+        return s + "[" + d.width + "X" + d.height + "]";
+    }
+    private String toString(String s, Rectangle d) {
+        if (d == null) return s + ":" + d;
+        return s + "[" + d.x + "," + d.y + ":" + d.width + "X" + d.height + "]";
+    }
+    private String toString(String s, Rectangle2D d) {
+        if (d == null) return s + ":" + d;
+        return s + "[" + d.getX() + "," + d.getY() + ":" + d.getWidth() + "X" + d.getHeight() + "]";
+    }
+  
+
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/FRLayoutManager.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/FRLayoutManager.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/Vector2D.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/Vector2D.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/Vector2D.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/Vector2D.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,143 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.layout;
+
+import java.text.DecimalFormat;
+
+/**
+ * A utility for two-dimensional vector operations.
+ * @author Pinaki Poddar
+ *
+ */
+public class Vector2D {
+    DecimalFormat fmt = new DecimalFormat("####.#");
+    double x;
+    double y;
+    
+    /**
+     * Construct vector of zero length.
+     */
+    public Vector2D() {
+        this(0,0);
+    }
+    
+    /**
+     * Construct a vector of given dimensions.
+     */
+    public Vector2D(double x, double y) {
+        this.x = x;
+        this.y = y;
+    }
+    
+    public Vector2D nudge(double epsilon) {
+        if (x == 0) x = epsilon;
+        if (y == 0) y = epsilon;
+        return this;
+    }
+    
+    /**
+     * Create a new unit vector for this vector. 
+     * 
+     * @return a new vector of unit magnitude
+     */
+    public Vector2D unit() {
+        double norm = this.norm();
+        
+        return copy().times(1.0/norm);
+    }
+    
+    /**
+     * Translate this vector by the given displacement.
+     * 
+     * @return this vector
+     */
+    public Vector2D add(double dx, double dy) {
+        x += dx;
+        y += dy;
+        return this;
+    }
+    
+    /**
+     * Add the given vector to this vector.
+     * 
+     * @return this vector
+     */
+    public Vector2D add(Vector2D other) {
+        return add(other.x, other.y);
+    }
+    
+    /**
+     * Turn this vector around.
+     * 
+     * @return this vector
+     */
+    public Vector2D minus() {
+        return times(-1);
+    }
+    
+    /**
+     * Copy to a new vector.
+     * @return
+     */
+    public Vector2D copy() {
+        return new Vector2D(x,y);
+    }
+    
+    public Vector2D times(double c) {
+        x *= c;
+        y *= c;
+        return this;
+    }
+    
+    /**
+     * Limit both dimension of this vector within (-box, +box)
+     * @param box must be positive.
+     * @return this vector.
+     */
+    public Vector2D limit(double box) {
+        return limit(-box, box);
+    }
+    
+    /**
+     * Limit both dimension of this vector within (min, max)
+     * @param box
+     * @return
+     */
+    public Vector2D limit(double min, double max) {
+        x = bound(x, min, max);
+        y = bound(y, min, max);
+        return this;
+    }
+    
+    double bound(double a, double min, double max) {
+        if (min > max)
+            throw new IllegalArgumentException("Minimum bound " + min + " is not less that maximum " + max);
+        if (a < min) a = min;
+        if (a > max) a = max;
+        return a;
+    }
+    
+    /**
+     * Gets the L2-norm of this vector.
+     */
+    public double norm() {
+        return Math.sqrt(x*x + y*y);
+    }
+    public double normSq() {
+        return x*x + y*y;
+    }
+    public String toString() {
+        return "(" + fmt.format(x) + "," + fmt.format(y) + ")";
+    }
+}
\ No newline at end of file

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/Vector2D.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/Vector2D.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/VerticalLayout.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/VerticalLayout.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/VerticalLayout.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/VerticalLayout.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,132 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+ */
+
+package org.apache.openjpa.swing.layout;
+
+import java.awt.Component;
+import java.awt.Container;
+import java.awt.Dimension;
+import java.awt.Insets;
+import java.awt.LayoutManager2;
+
+/**
+ * Lays out componets vertically. Differs from BoxLayout because invisible components
+ * are left out from size computation.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+public class VerticalLayout implements LayoutManager2 {
+    private Container _target;
+    private double   _width, _height;
+    private double   _minWidth, _minHeight;
+    private double   _maxWidth, _maxHeight;
+    
+    public VerticalLayout(Container target) {
+        _target = target;
+    }
+    
+    public void addLayoutComponent(Component comp, Object constraints) {
+        invalidateLayout(_target);
+    }
+
+    public Dimension maximumLayoutSize(Container target) {
+        int n = _target.getComponentCount();
+        _maxHeight = 0;
+        for (int i = 0; i < n; i++) {
+            Component c = _target.getComponent(i);
+            if (!c.isVisible()) continue;
+            Dimension size = c.getMaximumSize();
+            _maxWidth = Math.max(_maxWidth, size.getWidth());
+            _maxHeight += size.getHeight();
+        }
+        Insets inset = _target.getInsets();
+        Dimension d = new Dimension((int)(_maxWidth + inset.left + inset.right), 
+                             (int)(_maxHeight + inset.top + inset.bottom));
+//        System.err.println("Maximum Layout " + (int)d.getWidth() + "x" + (int)d.getHeight());
+        return d;
+    }
+
+    public Dimension preferredLayoutSize(Container parent) {
+        int n = _target.getComponentCount();
+        _width = _minWidth;
+        _height = 0;
+        for (int i = 0; i < n; i++) {
+            Component c = _target.getComponent(i);
+            Dimension size = c.getPreferredSize();
+            _width = Math.max(_width, size.getWidth());
+            if (!c.isVisible()) continue;
+            _height += size.getHeight();
+        }
+        Insets inset = _target.getInsets();
+        Dimension d =  new Dimension((int)(_width + inset.left + inset.right), 
+                             (int)(_height + inset.top + inset.bottom));
+//        System.err.println("Preferred Layout " + (int)d.getWidth() + "x" + (int)d.getHeight());
+        return d;
+    }
+
+    public Dimension minimumLayoutSize(Container parent) {
+        int n = _target.getComponentCount();
+        for (int i = 0; i < n; i++) {
+            Component c = _target.getComponent(i);
+            if (!c.isVisible()) continue;
+            Dimension size = c.getMinimumSize();
+            _minWidth = Math.max(_minWidth, size.getWidth());
+            _minHeight += size.getHeight();
+        }
+        Insets inset = _target.getInsets();
+        Dimension d =  new Dimension((int)(_minWidth + inset.left + inset.right), 
+                             (int)(_minHeight + inset.top + inset.bottom));
+//        System.err.println("Minimum Layout " + (int)d.getWidth() + "x" + (int)d.getHeight());
+        return d;
+    }
+
+    public float getLayoutAlignmentX(Container target) {
+        return Component.LEFT_ALIGNMENT;
+    }
+
+    public float getLayoutAlignmentY(Container target) {
+        return Component.TOP_ALIGNMENT;
+    }
+
+    public void invalidateLayout(Container target) {
+    }
+
+    public void addLayoutComponent(String name, Component comp) {
+        invalidateLayout(_target);
+    }
+
+    public void removeLayoutComponent(Component comp) {
+        invalidateLayout(_target);
+    }
+
+    public void layoutContainer(Container parent) {
+        int n = parent.getComponentCount();
+        Insets inset = parent.getInsets();
+        int w = inset.left;
+        int h = inset.top;
+        for (int i = 0; i < n; i++) {
+            Component c = _target.getComponent(i);
+            if (!c.isVisible()) continue;
+            Dimension size = c.getPreferredSize();
+            c.setBounds(w,h, (int)size.getWidth(), (int)size.getHeight());
+            h += size.getHeight();
+        }
+    }
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/VerticalLayout.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/layout/VerticalLayout.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/package.html
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/package.html?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/package.html (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/package.html Tue Oct  5 19:22:16 2010
@@ -0,0 +1,23 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<html>
+<body>
+Few extended Swing widgets and utilities. 
+</body>
+</html>

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/package.html
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/PrintableDelegateComponent.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/PrintableDelegateComponent.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/PrintableDelegateComponent.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/PrintableDelegateComponent.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,63 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.print;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.Rectangle;
+import java.awt.print.PageFormat;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+
+import javax.swing.JComponent;
+
+
+public class PrintableDelegateComponent extends Vista implements Printable {
+    private final JComponent _del;
+    private double scale = 1.0;
+    
+    public PrintableDelegateComponent(JComponent del, PageFormat format) {
+        super();
+        this.format = format;
+        this.printable = this;
+        setPageSize(del.getWidth(), del.getHeight());
+        _del = del;
+        Rectangle componentBounds = _del.getBounds(null);
+        setPageSize(componentBounds.width, componentBounds.height);
+        setScale(1);    
+    }
+    
+    public PrintableDelegateComponent setScale(double s) {
+        scale = s;
+        setPageSize(s*_del.getWidth(), s*_del.getHeight());
+        return this;
+    }
+
+    @Override
+    public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
+        if (pageIndex >= getNumberOfPages())
+            return NO_SUCH_PAGE;
+        System.err.println(this.getClass().getSimpleName()+".print Page " + pageIndex);
+        Graphics2D g2 = (Graphics2D) graphics;
+        
+        g2.translate(pageFormat.getImageableX(), pageFormat.getImageableY());
+        Rectangle componentBounds = _del.getBounds(null);
+        g2.translate(-componentBounds.x, -componentBounds.y);
+        g2.scale(scale, scale);
+        boolean wasBuffered = _del.isDoubleBuffered();
+        _del.paint(g2);
+        _del.setDoubleBuffered(wasBuffered);
+        return PAGE_EXISTS;    }
+
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/PrintableDelegateComponent.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/PrintableDelegateComponent.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/Vista.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/Vista.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/Vista.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/Vista.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,82 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.swing.print;
+
+import java.awt.Graphics;
+import java.awt.Graphics2D;
+import java.awt.geom.Point2D;
+import java.awt.print.PageFormat;
+import java.awt.print.Pageable;
+import java.awt.print.Printable;
+import java.awt.print.PrinterException;
+
+public abstract class Vista implements Pageable {
+    protected PageFormat format;
+    protected Printable printable;
+    private int totalPages = -1;
+    private int xPages = -1;
+    private int yPages = -1;
+
+    protected Vista() {
+        
+    }
+
+    @Override
+    public int getNumberOfPages() {
+        return totalPages;
+    }
+
+    @Override
+    public PageFormat getPageFormat(int pageIndex) throws IndexOutOfBoundsException {
+        if (pageIndex > totalPages) {
+            throw new IndexOutOfBoundsException();
+        }
+        return format;
+    }
+
+    @Override
+    public Printable getPrintable(int pageIndex) throws IndexOutOfBoundsException {
+        if (pageIndex > totalPages) {
+            throw new IndexOutOfBoundsException();
+        }
+        double x0 = (pageIndex % xPages) * format.getImageableWidth();
+        double y0 = (pageIndex / xPages) * format.getImageableHeight();
+        Point2D.Double origin = new Point2D.Double(x0, y0);
+        return new PrintableSinglePage(printable, origin);
+
+    }
+
+    protected void setPageSize(double width, double height) {
+        xPages = (int) ((width + format.getImageableWidth() - 1) / format.getImageableWidth());
+        yPages = (int) ((height + format.getImageableHeight() - 1) / format.getImageableHeight());
+        totalPages = xPages * yPages;
+    }
+
+    private class PrintableSinglePage implements Printable {
+        private final Point2D origin;
+        private final Printable singlePage;
+        public PrintableSinglePage(Printable page, Point2D origin) {
+            super();
+            this.singlePage = page;
+            this.origin = origin;
+        }
+
+        public int print(Graphics graphics, PageFormat pageFormat, int pageIndex) throws PrinterException {
+            Graphics2D g2 = (Graphics2D) graphics;
+            g2.translate(-origin.getX(), -origin.getY());
+            singlePage.print(g2, pageFormat, 1);
+            return PAGE_EXISTS;
+        }
+    }
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/Vista.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/swing/print/Vista.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/MigrationTool.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/MigrationTool.java?rev=1004775&r1=1004774&r2=1004775&view=diff
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/MigrationTool.java (original)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/MigrationTool.java Tue Oct  5 19:22:16 2010
@@ -20,12 +20,10 @@ package org.apache.openjpa.tools;
 
 import java.io.File;
 import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Date;

Added: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/metamodel/AttributeLegendView.java
URL: http://svn.apache.org/viewvc/openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/metamodel/AttributeLegendView.java?rev=1004775&view=auto
==============================================================================
--- openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/metamodel/AttributeLegendView.java (added)
+++ openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/metamodel/AttributeLegendView.java Tue Oct  5 19:22:16 2010
@@ -0,0 +1,60 @@
+/*
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+*/
+package org.apache.openjpa.tools.metamodel;
+
+import java.awt.Color;
+import java.awt.GridLayout;
+import java.awt.image.BufferedImage;
+
+import javax.persistence.metamodel.Attribute;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JComponent;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+
+
+
+/**
+ * Displays color codes of each attribute type.
+ * 
+ * @author Pinaki Poddar
+ *
+ */
+@SuppressWarnings("serial")
+public class AttributeLegendView extends JPanel {
+    
+    public AttributeLegendView() {
+        super(true);
+        setBorder(BorderFactory.createTitledBorder("Attribute Legends"));
+        setLayout(new GridLayout(0,3));
+        add(createColoredLabel("IDENTITY", MetamodelUIManager.getColor(MetamodelUIManager.COLOR_ATTR_ID)));
+        add(createColoredLabel("VERSION",  MetamodelUIManager.getColor(MetamodelUIManager.COLOR_ATTR_VERSION)));
+        for (Attribute.PersistentAttributeType type : Attribute.PersistentAttributeType.values()) {
+          add(createColoredLabel(type.toString().replace('_', ' '), MetamodelUIManager.getColor(type)));
+      }        
+    }
+    
+    JComponent createColoredLabel(String text, Color c) {
+        int width  = 40;
+        int height = 20;
+        BufferedImage bimage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); 
+        for (int i = 0; i < width; i++)
+            for (int j = 0; j < height; j++)
+                bimage.setRGB(i, j, c.getRGB());
+        JLabel label = new JLabel(text, new ImageIcon(bimage), JLabel.LEADING);
+        return label;
+    }
+
+}

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/metamodel/AttributeLegendView.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: openjpa/tools/trunk/openjpa-tools/src/main/java/org/apache/openjpa/tools/metamodel/AttributeLegendView.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain