You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2006/08/07 03:52:04 UTC

svn commit: r429228 [2/3] - in /incubator/cayenne/soc/trunk/cayenne-rop/rop-browser: ./ icons/ src/org/apache/cayenne/ropbrowser/ src/org/apache/cayenne/ropbrowser/actions/ src/org/apache/cayenne/ropbrowser/commands/ src/org/apache/cayenne/ropbrowser/f...

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CollectionFigure.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CollectionFigure.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CollectionFigure.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CollectionFigure.java Sun Aug  6 18:52:01 2006
@@ -18,39 +18,46 @@
 import java.util.Iterator;
 
 import org.apache.cayenne.ropbrowser.ROPBrowserPlugin;
-import org.apache.cayenne.ropbrowser.figures.CompartmentFigure.CompartmentFigureBorder;
 import org.apache.cayenne.ropbrowser.model.AbstractObject;
 import org.apache.cayenne.ropbrowser.model.CollectionModelElement;
-import org.apache.cayenne.ropbrowser.model.ModelElement;
 import org.apache.cayenne.ropbrowser.parts.CollectionEditPart;
-import org.apache.cayenne.ropbrowser.parts.SingleEditPart;
 import org.eclipse.draw2d.ActionEvent;
 import org.eclipse.draw2d.ActionListener;
 import org.eclipse.draw2d.Button;
-import org.eclipse.draw2d.Clickable;
 import org.eclipse.draw2d.ColorConstants;
-import org.eclipse.draw2d.CompoundBorder;
-import org.eclipse.draw2d.Figure;
-import org.eclipse.draw2d.FlowLayout;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.LineBorder;
 import org.eclipse.draw2d.MarginBorder;
 import org.eclipse.draw2d.ToolbarLayout;
 import org.objectstyle.cayenne.map.Attribute;
 
+/**
+ * Figure representing a {@link CollectionEditPart}.
+ * Attributes are buttons which insert a dropdown below
+ * with the collection's objects when pressed.
+ * 
+ * @author Marcel Gordon
+ */
 public class CollectionFigure extends ElementFigure implements ActionListener {
 	
-	private CompartmentFigure navFigure;
-	private String lastNavAttribute = null;
+	// TODO neaten up class separation
 	
+	/**
+	 * Figure to act as a dropdown box to allow quick navigation through objects.
+	 */
+	private DropdownFigure navFigure;
+	/**
+	 * The name of the attribute that was last displayed in the nav figure.
+	 */
+	private String lastNavAttribute = null;
+
 	public CollectionFigure(CollectionEditPart part) {
 		super(part);
 	}
 	
+	@Override
 	protected void addComponents() {
 		super.addComponents();
 		
-		navFigure = new CompartmentFigure();
+		navFigure = new DropdownFigure();
 		ToolbarLayout layout = new ToolbarLayout();
 		layout.setMinorAlignment(ToolbarLayout.ALIGN_TOPLEFT);
 		layout.setStretchMinorAxis(false);
@@ -59,6 +66,7 @@
 		navFigure.setBorder(null);
 	}
 	
+	@Override
 	protected void setBackgroundColour() {
 		// root figure should be a different colour
 		if (getElementCast().isRoot()) {
@@ -69,11 +77,19 @@
 		}
 	}
 
-	private CollectionModelElement getElementCast() {
+	CollectionModelElement getElementCast() {
 		return (CollectionModelElement) part.getModel();
 	}
 	
+	CollectionEditPart getPartCast() {
+		return (CollectionEditPart) part;
+	}
+	
+	@Override
 	protected void setName() {
+		// set the name to the name of the object plus the number in the collection
+		// or null if no name is available
+		
 		CollectionModelElement element = getElementCast();
 		String modelName = element.getName();
 		if (modelName != null) {
@@ -84,14 +100,27 @@
 		}
 	}
 	
+	/**
+	 * Extends {@link ElementFigure#setAttributes(AbstractObject)
+	 * to make each attribute a button and insert a dropdown if
+	 * a button has been pressed.
+	 */
+	@Override
 	protected void setAttributes(AbstractObject model) {
+		for (Object child : getAttributeCompartment().getChildren()) {
+			if (child instanceof Button) {
+				((Button) child).removeActionListener(this);
+			}
+		}
 		getAttributeCompartment().removeAll();
 		
+		// create a button for each attribute		
 		if (model != null) {			
 			Iterator i = model.getAttributes().iterator();
 			while (i.hasNext()) {
 				Attribute a = (Attribute) i.next();
 				Button b;
+				// if expanded, use open icon, else closed
 				if (lastNavAttribute != null && a.getName().equals(lastNavAttribute)) {
 					b = new Button(a.getName() + " : " + model.getPropertyValue(a.getName()) + " ", ROPBrowserPlugin.getDefault().getImageRegistry().get(ROPBrowserPlugin.IMG_DROP_OPEN));
 				}
@@ -104,16 +133,27 @@
 				b.setBorder(null);
 				b.setOpaque(false);
 				b.addActionListener(this);
+				// set the user data to the attribute name for the action listener
 				b.getModel().setUserData(a.getName());
 				getAttributeCompartment().add(b);
 				
+				// if this is in an expanded state, insert the nav figure like a dropdown
 				if (lastNavAttribute != null && a.getName().equals(lastNavAttribute)) {
-					insertDropdown(a.getName());
+					Iterator<AbstractObject> iterator = getElementCast().getSortedObjectIterator(a.getName());
+					navFigure.populateDropdown(a.getName(), getPartCast(), iterator);
+					// add the navFigure to the attribute compartment
+					getAttributeCompartment().add(navFigure);
 				}
 			}	
 		}
 	}
 	
+	/**
+	 * Handle button presses from the attribute buttons.
+	 * On open, set the lastNavAttribute to the name of the attribute pressed
+	 * and refresh the figure.
+	 * On close, remove the navFigure and set the lastNavAttribute to null
+	 */
 	public void actionPerformed(ActionEvent event) {
 		
 		Button buttonPressed = (Button) event.getSource();
@@ -121,7 +161,6 @@
 		
 		if (lastNavAttribute != null && lastNavAttribute.equals(pressed)) {
 			lastNavAttribute = null;
-			navFigure.removeAll();
 			getAttributeCompartment().remove(navFigure);
 		}
 		else {
@@ -130,23 +169,31 @@
 		
 		refresh();
 	}
+}
+
+class DropdownFigure extends CompartmentFigure {
 	
-	protected void insertDropdown(String pressed) {
-		
-		navFigure.removeAll();
-		getAttributeCompartment().add(navFigure);
-		
-		// TODO sort values
-		
-		Iterator<AbstractObject> i = getElementCast().getObjectIterator();
-		while (i.hasNext()) {
-			AbstractObject o = i.next();
-			Button b = new Button(o.getPropertyValue(pressed).toString());
+	public void populateDropdown(String attributeName, ActionListener actionListener, Iterator<AbstractObject> iterator) {
+		// remove any existing buttons from the navFigure
+		for (Object child : getChildren()) {
+			if (child instanceof Button) {
+				((Button) child).removeActionListener(actionListener);
+			}
+		}
+		removeAll();
+		
+		// add a button for each object
+		while (iterator.hasNext()) {
+			AbstractObject o = iterator.next();
+			// label the button with the attribute's value for this object
+			Button b = new Button(o.getPropertyValue(attributeName).toString());
 			b.setBorder(new MarginBorder(0, 10, 0, 0));
 			b.setOpaque(false);
+			// set the user data to the object for use by the action listener
 			b.getModel().setUserData(o);
-			b.addActionListener((CollectionEditPart) part);
-			navFigure.add(b);
+			b.addActionListener(actionListener);
+			add(b);
 		}
 	}
+	
 }

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CompartmentFigure.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CompartmentFigure.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CompartmentFigure.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/CompartmentFigure.java Sun Aug  6 18:52:01 2006
@@ -17,7 +17,6 @@
 package org.apache.cayenne.ropbrowser.figures;
 
 import org.eclipse.draw2d.AbstractBorder;
-import org.eclipse.draw2d.Border;
 import org.eclipse.draw2d.Figure;
 import org.eclipse.draw2d.Graphics;
 import org.eclipse.draw2d.IFigure;
@@ -26,7 +25,9 @@
 
 /**
  * A sub-figure for use in other figures as a container.
+ * Adapted from Daniel Lee's <a href="http://www.eclipse.org/articles/Article-GEF-Draw2d/GEF-Draw2d.html">UML example</a>.
  *  
+ * @author Daniel Lee
  * @author Marcel Gordon
  */
 public class CompartmentFigure extends Figure {

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/ElementFigure.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/ElementFigure.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/ElementFigure.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/ElementFigure.java Sun Aug  6 18:52:01 2006
@@ -27,14 +27,11 @@
 import org.eclipse.draw2d.Label;
 import org.eclipse.draw2d.LineBorder;
 import org.eclipse.draw2d.ToolbarLayout;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.graphics.Font;
-import org.eclipse.swt.widgets.Display;
 import org.objectstyle.cayenne.map.Attribute;
 
 /**
- * A Figure representing a CollectionEditPart in the editor. Contains two compartments,
- * for relationships and attributes, and a name to describe the object.
+ * A superclass for figures representing parts which extend
+ * {@link ElementEditPart}.
  * 
  * @author Marcel Gordon
  */
@@ -42,11 +39,12 @@
 	
 	/** sub-figure for displaying the object's attributes */ 
 	protected CompartmentFigure attributeFigure = new CompartmentFigure();
-	/** name of the object, or MSG_NULL_RESULT if none can be obtained */
+	/** name of the object */
 	protected Label name;
 	/** name to be used where no name can be located */
 	public static final String MSG_NULL_RESULT = "NULL"; 
 	
+	/** the part which the figure represents */
 	protected ElementEditPart part;
 	
 	public ElementFigure(ElementEditPart part) {
@@ -63,6 +61,10 @@
 		refresh();
 	}
 	
+	/**
+	 * Add the component compartments for this figure.
+	 * Extended by subclasses to add their specific compartments.
+	 */
 	protected void addComponents() {
 		name = new Label();
 		add(name);
@@ -72,8 +74,14 @@
 		add(attributeFigure);
 	}
 	
+	/**
+	 * Set the background colour of the figure and its children
+	 */
 	protected abstract void setBackgroundColour();
 	
+	/**
+	 * Set the name displayed in the name label
+	 */
 	protected abstract void setName();
 	
 	/**
@@ -91,6 +99,10 @@
 		return attributeFigure;
 	}
 
+	/**
+	 * Fill the attribute compartment with the attributes for the
+	 * object to be displayed and their values.
+	 */
 	protected void setAttributes(AbstractObject model) {
 		getAttributeCompartment().removeAll();
 		

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/SingleFigure.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/SingleFigure.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/SingleFigure.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/figures/SingleFigure.java Sun Aug  6 18:52:01 2006
@@ -24,6 +24,13 @@
 import org.eclipse.draw2d.MarginBorder;
 import org.objectstyle.cayenne.map.Relationship;
 
+/**
+ * Figure representing a {@link SingleEditPart}.
+ * This figure has a compartment with a button for each
+ * relationship.
+ * 
+ * @author Marcel Gordon
+ */
 public class SingleFigure extends ElementFigure {
 	
 	/** sub-figure for displaying the object's relationships */
@@ -33,7 +40,12 @@
 		super(part);
 	}
 	
+	@Override
 	protected void setBackgroundColour() {
+		
+		// for deleted objects, name should have a red background
+		// otherwise, green
+		
 		if (getElementCast().getCurrentObject() != null &&
 				getElementCast().getCurrentObject().isDeleted()) {
 			name.setBackgroundColor(ColorConstants.red);
@@ -43,6 +55,7 @@
 		}
 	}
 
+	@Override
 	protected void addComponents() {
 		super.addComponents();
 		
@@ -57,11 +70,22 @@
 		return relationshipFigure;
 	}
 	
+	/**
+	 * Sets up the relationships compartment, filling it with buttons
+	 * representing the element's relationships
+	 */
 	protected void setRelationships() {
+		for (Object child : relationshipFigure.getChildren()) {
+			if (child instanceof Button) {
+				((Button) child).removeActionListener((SingleEditPart) part);
+			}
+		}
 		relationshipFigure.removeAll();
 		
 		if (getElementCast().getCurrentObject() == null) return;
 		
+		// for each relationship, make a button with the name
+		// of the relationship
 		Button relButton;
 		for (Object o : getElementCast().getCurrentObject().getRelationships()) {
 			Relationship relationship = (Relationship) o;
@@ -86,10 +110,7 @@
 		name.setText(getElementCast().getName());
 	}
 	
-	/**
-	 * Set or change the data which is being displayed in this figure's
-	 * relationship and attribute sub-figures
-	 */
+	@Override
 	protected void setContents() {
 		super.setContents();
 		setRelationships();

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DelegatingLayoutManager.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DelegatingLayoutManager.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DelegatingLayoutManager.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DelegatingLayoutManager.java Sun Aug  6 18:52:01 2006
@@ -1,10 +1,20 @@
 /*
- * Created on Jul 13, 2004
+ *  Copyright 2006 The Apache Software Foundation
+ *
+ *  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.cayenne.ropbrowser.layout;
 
-import java.util.Map;
-
 import org.apache.cayenne.ropbrowser.parts.ElementDiagramEditPart;
 import org.apache.cayenne.ropbrowser.policies.ElementXYLayoutEditPolicy;
 import org.apache.cayenne.ropbrowser.policies.SelectionHandlesEditPolicy;
@@ -17,7 +27,11 @@
 
 /**
  * Used to delegate between the GraphyLayoutManager and the GraphXYLayout classes
+ * 
+ * Adapted from Phil Zoio's <a href="http://www.eclipse.org/articles/Article-GEF-editor/gef-schema-editor.html">Schema Editor example</a>.
+ * 
  * @author Phil Zoio
+ * @author Marcel Gordon
  */
 public class DelegatingLayoutManager implements LayoutManager
 {
@@ -32,7 +46,7 @@
 	{
 		this.diagram = diagram;
 		this.graphLayoutManager = new GraphLayoutManager(diagram);
-		this.xyLayoutManager = new GraphXYLayout(diagram);
+		this.xyLayoutManager = new GraphXYLayout();
 
 		//use the graph layout manager as the initial delegate
 		this.activeLayoutManager = this.graphLayoutManager;
@@ -45,7 +59,7 @@
 	{
 		if (!diagram.isAutoLayoutDesired())
 		{
-			diagram.setTableFigureBounds(true);
+			diagram.setElementFigureBounds(true);
 			setLayoutManager(container, xyLayoutManager);
 			activeLayoutManager.layout(container);
 		}

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DirectedGraphLayoutVisitor.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DirectedGraphLayoutVisitor.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DirectedGraphLayoutVisitor.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/DirectedGraphLayoutVisitor.java Sun Aug  6 18:52:01 2006
@@ -1,21 +1,29 @@
 /*
- * Created on Jul 15, 2004
+ *  Copyright 2006 The Apache Software Foundation
+ *
+ *  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.cayenne.ropbrowser.layout;
 
-import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
 import org.apache.cayenne.ropbrowser.figures.ElementFigure;
-import org.apache.cayenne.ropbrowser.model.ModelElement;
 import org.apache.cayenne.ropbrowser.parts.ConnectionEditPart;
 import org.apache.cayenne.ropbrowser.parts.ElementDiagramEditPart;
 import org.apache.cayenne.ropbrowser.parts.ElementEditPart;
-import org.eclipse.draw2d.AbsoluteBendpoint;
-import org.eclipse.draw2d.IFigure;
 import org.eclipse.draw2d.PolylineConnection;
 import org.eclipse.draw2d.geometry.Insets;
 import org.eclipse.draw2d.geometry.Rectangle;
@@ -23,17 +31,21 @@
 import org.eclipse.draw2d.graph.DirectedGraphLayout;
 import org.eclipse.draw2d.graph.Edge;
 import org.eclipse.draw2d.graph.Node;
-import org.eclipse.draw2d.graph.NodeList;
+import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
 
 /**
  * Visitor with support for populating nodes and edges of DirectedGraph
  * from model objects
+ * 
+ * Adapted from Phil Zoio's <a href="http://www.eclipse.org/articles/Article-GEF-editor/gef-schema-editor.html">Schema Editor example</a>.
+ * 
  * @author Phil Zoio
+ * @author Marcel Gordon
  */
 public class DirectedGraphLayoutVisitor
 {
 
-	Map partToNodesMap;
+	Map<AbstractGraphicalEditPart, Object> partToNodesMap;
 	DirectedGraph graph;
 
 	/**
@@ -42,7 +54,7 @@
 	public void layoutDiagram(ElementDiagramEditPart diagram)
 	{
 
-		partToNodesMap = new HashMap();
+		partToNodesMap = new HashMap<AbstractGraphicalEditPart, Object>();
 		
 		graph = new DirectedGraph();
 		addNodes(diagram);
@@ -59,12 +71,10 @@
 
 	protected void addNodes(ElementDiagramEditPart diagram)
 	{
-		//GraphAnimation.recordInitialState(diagram.getFigure());
-		IFigure fig = diagram.getFigure();
 		for (int i = 0; i < diagram.getChildren().size(); i++)
 		{
-			ElementEditPart tp = (ElementEditPart) diagram.getChildren().get(i);
-			addNodes(tp);
+			ElementEditPart editPart = (ElementEditPart) diagram.getChildren().get(i);
+			addNodes(editPart);
 		}
 	}
 
@@ -106,7 +116,6 @@
 
 	protected void addEdges(ConnectionEditPart relationshipPart)
 	{
-		//GraphAnimation.recordInitialState((Connection) relationshipPart.getFigure());
 		Node source = (Node) partToNodesMap.get(relationshipPart.getSource());
 		Node target = (Node) partToNodesMap.get(relationshipPart.getTarget());
 		Edge e = new Edge(relationshipPart, source, target);
@@ -141,11 +150,11 @@
 	{
 
 		Node n = (Node) partToNodesMap.get(element);
-		ElementFigure tableFigure = (ElementFigure) element.getFigure();
+		ElementFigure elementFigure = (ElementFigure) element.getFigure();
 
-		Rectangle bounds = new Rectangle(n.x, n.y, tableFigure.getPreferredSize().width, tableFigure.getPreferredSize().height);
+		Rectangle bounds = new Rectangle(n.x, n.y, elementFigure.getPreferredSize().width, elementFigure.getPreferredSize().height);
 		
-		tableFigure.setBounds(bounds);
+		elementFigure.setBounds(bounds);
 
 		for (int i = 0; i < element.getSourceConnections().size(); i++)
 		{

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphLayoutManager.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphLayoutManager.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphLayoutManager.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphLayoutManager.java Sun Aug  6 18:52:01 2006
@@ -1,10 +1,21 @@
 /*
- * Created on Jul 13, 2004
+ *  Copyright 2006 The Apache Software Foundation
+ *
+ *  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.cayenne.ropbrowser.layout;
 
 import java.util.List;
-import java.util.Map;
 
 import org.apache.cayenne.ropbrowser.parts.ElementDiagramEditPart;
 import org.eclipse.draw2d.AbstractLayout;
@@ -15,7 +26,11 @@
 
 /**
  * Uses the DirectedGraphLayoutVisitor to automatically lay out figures on diagram
+ * 
+ * Adapted from Phil Zoio's <a href="http://www.eclipse.org/articles/Article-GEF-editor/gef-schema-editor.html">Schema Editor example</a>.
+ * 
  * @author Phil Zoio
+ * @author Marcel Gordon
  */
 public class GraphLayoutManager extends AbstractLayout
 {
@@ -28,6 +43,7 @@
 	}
 
 	
+	@Override
 	protected Dimension calculatePreferredSize(IFigure container, int wHint, int hHint)
 	{		
 		container.validate();
@@ -42,12 +58,7 @@
 	
 	public void layout(IFigure container)
 	{
-		/*
-		GraphAnimation.recordInitialState(container);
-		if (GraphAnimation.playbackState(container))
-			return;
-		*/
 		new DirectedGraphLayoutVisitor().layoutDiagram(diagram);
-		diagram.setTableModelBounds();
+		diagram.setElementModelBounds();
 	}
 }

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphXYLayout.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphXYLayout.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphXYLayout.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/layout/GraphXYLayout.java Sun Aug  6 18:52:01 2006
@@ -1,34 +1,42 @@
 /*
- * Created on Jul 21, 2004
+ *  Copyright 2006 The Apache Software Foundation
+ *
+ *  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.cayenne.ropbrowser.layout;
 
-import org.apache.cayenne.ropbrowser.parts.ElementDiagramEditPart;
 import org.eclipse.draw2d.FreeformLayout;
 import org.eclipse.draw2d.IFigure;
 import org.eclipse.draw2d.geometry.Rectangle;
 
 /**
  * Subclass of XYLayout which can use the child figures actual bounds as a constraint
- * when doing manual layout (XYLayout)
+ * when doing manual layout (XYLayout).
+ * Adapted from Phil Zoio's <a href="http://www.eclipse.org/articles/Article-GEF-editor/gef-schema-editor.html">Schema Editor example</a>.
+ * 
  * @author Phil Zoio
+ * @author Marcel Gordon
  */
 public class GraphXYLayout extends FreeformLayout
 {
 
-	private ElementDiagramEditPart diagram;
-	
-	public GraphXYLayout(ElementDiagramEditPart diagram)
-	{
-		this.diagram = diagram;
-	}	
-
+	@Override
 	public Object getConstraint(IFigure child)
 	{
 		Object constraint = constraints.get(child);
 		if (constraint != null || constraint instanceof Rectangle)
 		{
-			return (Rectangle)constraint;
+			return constraint;
 		}
 		else
 		{

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/AbstractObject.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/AbstractObject.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/AbstractObject.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/AbstractObject.java Sun Aug  6 18:52:01 2006
@@ -22,12 +22,14 @@
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Collections;
+import java.util.Date;
 import java.util.Iterator;
 
 import org.eclipse.ui.views.properties.IPropertyDescriptor;
 import org.eclipse.ui.views.properties.TextPropertyDescriptor;
 import org.objectstyle.cayenne.PersistenceState;
 import org.objectstyle.cayenne.PersistentObject;
+import org.objectstyle.cayenne.map.Attribute;
 import org.objectstyle.cayenne.map.EntityResolver;
 import org.objectstyle.cayenne.map.ObjAttribute;
 import org.objectstyle.cayenne.map.ObjEntity;
@@ -41,12 +43,19 @@
  * 
  * @author Marcel Gordon
  */
-public class AbstractObject extends PersistentObject {
-
-	protected static SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy");
+public class AbstractObject extends PersistentObject {	
+	/**
+	 * Formatter for displaying {@link Date} objects as {@link String}s.
+	 */
+	protected static SimpleDateFormat dateFormatter = new SimpleDateFormat("dd/MM/yyyy ");
+	/** Property indicating that the object has been deleted */
 	public static final String PROP_DELETED = "AbstractObject.Deleted";
+	/** Property indicating that the object has been modified */
 	public static final String PROP_MODIFIED = "AbstractObject.Modified";
 	
+	/**
+	 * The {@link Attribute}s of the object.
+	 */
 	protected Collection attributes;
 	
 	/** Delegate used to implemenent property-change-support. */
@@ -108,13 +117,16 @@
 		return Collections.EMPTY_LIST;
 	}
 	
+	/**
+	 * The name of the object (its simple class name)
+	 */
 	public String getName() {
 		return this.getClass().getSimpleName();
 	}
 	
 	/**
 	 * Generates the property descriptors for this object.
-	 * Should cache the results for efficiency.
+	 * The caller should cache the results for efficiency.
 	 * @return array of IPropertyDescriptors for the objects attributes
 	 */
 	public IPropertyDescriptor[] getPropertyDescriptors() {
@@ -134,38 +146,41 @@
 	}
 
 	/**
-	 * Accesses a property of the object.
+	 * Accesses a property of the object, returning the result as a String
 	 * @param id the name of the property
-	 * @return the value of the property
+	 * @return the value of the property as a String
 	 */
-	public Object getPropertyValue(Object id) {
+	public String getPropertyValue(Object id) {
 		if(objectContext != null) {
+			// prepare the object for access
             objectContext.prepareForAccess(this, id.toString());
 		
 			EntityResolver resolver = objectContext.getEntityResolver();
 			ClassDescriptor descriptor = resolver.getClassDescriptor(getName());
 			ObjAttribute attribute = (ObjAttribute) resolver.getObjEntity(getName()).getAttribute(id.toString());
 			
-			Object value = null;
+			// convert the value of the property to a String for display
+			// in a TextPropertyDescriptor
+			Object value = descriptor.getProperty(id.toString()).readProperty(this);
+			String stringValue = null;
 			if (attribute.getType().equals("java.util.Date")) {
 				try {
-					value = dateFormatter.format(descriptor.getProperty(id.toString()).readProperty(this));
+					stringValue = dateFormatter.format(value);
 				}
 				catch (Exception e) {
-					value = new String("");
+					stringValue = new String("");
 				}
 			}
 			else {
-				value = descriptor.getProperty(id.toString()).readProperty(this);
 				if (value == null) {
-					value = new String("");
+					stringValue = new String("");
 				}
 				else {
-					value = value.toString(); 
+					stringValue = value.toString(); 
 				}
 			} 
 			
-			return value;
+			return stringValue;
 		}
 		return null;
 	}
@@ -180,6 +195,9 @@
 		return Collections.EMPTY_LIST;
 	}
 
+	/**
+	 * @return whether the object has been deleted
+	 */
 	public boolean isDeleted() {
 		return (getPersistenceState() == PersistenceState.DELETED) ||
 				(getPersistenceState() == PersistenceState.TRANSIENT);
@@ -211,6 +229,11 @@
 	public void resetPropertyValue(Object id) {
 	}
 	
+	/**
+	 * Extended to fire property change events when an
+	 * object is deleted.
+	 */
+	@Override
 	public void setPersistenceState(int persistenceState) {
 		int oldState = getPersistenceState();
 		super.setPersistenceState(persistenceState);
@@ -225,7 +248,9 @@
 	}
 
 	/**
-	 * Sets the value of a property of the object
+	 * Sets the value of a property of the object. If conversion
+	 * to the appropriate type fails, the attempt to update the
+	 * object continues to allow failure from the database later.
 	 * @param id the name of the property
 	 * @param value the value to set the property to
 	 */
@@ -236,16 +261,25 @@
 			ClassDescriptor descriptor = resolver.getClassDescriptor(getName());
 			ObjAttribute attribute = (ObjAttribute) resolver.getObjEntity(getName()).getAttribute(id.toString());
 			
+			// convert from a String to the correct object type
 			Object newValue = null;
 			if (attribute.getType().equals("java.util.Date")) {
 				try {
 					newValue = dateFormatter.parse(value.toString());
 				}
 				catch(ParseException e) {
-					// TODO logging etc
-					System.out.println("Invalid date format");
+					newValue = value;
 				}
 			}
+			else if (attribute.getType().equals("java.sql.Date")) {
+				newValue = java.sql.Date.valueOf(value.toString()); 
+			}
+			else if (attribute.getType().equals("java.sql.Time")) {
+				newValue = java.sql.Time.valueOf(value.toString());
+			}
+			else if (attribute.getType().equals("java.sql.Timestamp")) {
+				newValue = java.sql.Timestamp.valueOf(value.toString());
+			}
 			else {
 				// try to use a constructor from a String
 				try {
@@ -253,8 +287,6 @@
 					newValue = newClass.getConstructor(Class.forName("java.lang.String")).newInstance(value.toString());
 				}
 				catch(Exception e) {
-					// TODO log
-					System.out.println("No String constructor available; implement a custom IPropertyDescriptor or type convertor");
 					newValue = value;
 				}
 			}
@@ -271,6 +303,12 @@
 		}
 	}
 
+	/**
+	 * Set the value of a relationship
+	 * @param rel the relationship to set
+	 * @param oldValue the old target of the relationship
+	 * @param newValue the new target of the relationship
+	 */
 	public void setRelationship(Relationship rel, AbstractObject oldValue, AbstractObject newValue) {
 		if (objectContext != null) {
 			
@@ -282,5 +320,23 @@
 			// notify objectContext about simple property change
 	        objectContext.propertyChanged(this, rel.getName(), oldValue, newValue);
 		}
+	}
+
+	/**
+	 * Accesses a property of the object, returning the result in its native form
+	 * @param id the name of the property
+	 * @return the value of the property
+	 */
+	public Object getPropertyValueRaw(Object id) {
+		if(objectContext != null) {
+			// prepare the object for access
+            objectContext.prepareForAccess(this, id.toString());
+		
+			EntityResolver resolver = objectContext.getEntityResolver();
+			ClassDescriptor descriptor = resolver.getClassDescriptor(getName());
+			
+			return descriptor.getProperty(id.toString()).readProperty(this);
+		}
+		return null;
 	}
 }

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/CollectionModelElement.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/CollectionModelElement.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/CollectionModelElement.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/CollectionModelElement.java Sun Aug  6 18:52:01 2006
@@ -16,23 +16,20 @@
  */
 package org.apache.cayenne.ropbrowser.model;
 
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
 
-import org.eclipse.ui.views.properties.IPropertyDescriptor;
-import org.eclipse.ui.views.properties.PropertyDescriptor;
-import org.eclipse.ui.views.properties.TextPropertyDescriptor;
-import org.objectstyle.cayenne.Persistent;
-import org.objectstyle.cayenne.util.PersistentObjectList;
-
 
 /**
  * Class representing a collection of AbstractObjects.
  * Used to display a number of records as one element on the
  * canvas with the ability to scroll through them.
+ * The element will be a property listener for all its objects,
+ * rethrowing events to ensure visual updates (as the visual component
+ * represents the element rather than the object).
  * 
  * @author Marcel Gordon
  *
@@ -40,29 +37,48 @@
 public class CollectionModelElement extends ModelElement {
 	
 	/**
-	 * Property descriptors for total records and current record for use with the Eclipse Properties view.
+	 * Comparator used to sort {@link AbstractObject}s based on a specified attribute
+	 * 
+	 * @author Marcel Gordon
 	 */
-	protected static IPropertyDescriptor [] descriptors;
+	class AbstractObjectComparator implements Comparator<AbstractObject> {
+		
+		private String sortName;
+
+		public AbstractObjectComparator(String sortName) {
+			this.sortName = sortName;
+		}
+				
+		public int compare(AbstractObject arg0, AbstractObject arg1) {
+			
+			Object value0 = arg0.getPropertyValueRaw(sortName);
+			Object value1 = arg1.getPropertyValueRaw(sortName);
+			
+			if (!arg0.getClass().equals(arg1.getClass())) {
+				return value0.toString().compareTo(value1.toString()); 
+			}
+			if (value0 instanceof Comparable) {
+				return ((Comparable) value0).compareTo(value1);
+			}
+			return value0.toString().compareTo(value1.toString());
+		}
+	}
 	
 	/**
 	 * Property for the currently displayed AbstractObject.
 	 */
 	public static String PROP_CURRENT_RECORD = "Collection.RecordNo";
+	
 	/**
 	 * Property for the total number of records stored.
 	 */
 	public static String PROP_TOTAL_RECORDS = "Collection.TotalRecords";
-	static {
-		descriptors = new IPropertyDescriptor[] {
-			new TextPropertyDescriptor(PROP_CURRENT_RECORD, "Current Record"),
-			new PropertyDescriptor(PROP_TOTAL_RECORDS, "Total Records")
-		};
-	}
 	
 	/**
 	 * The AbstractObject currently being displayed.
 	 */
 	protected AbstractObject current;
+	
 	/**
 	 * The index of the AbstractObject currently being displayed.
 	 */
@@ -73,25 +89,26 @@
 	 */
 	protected List<AbstractObject> objects;
 	
-	protected IPropertyDescriptor[] properties = null;
-	
 	/**
-	 * @param createdFrom the ModelElement which initiated this element's creation.
+	 * @param name the name of the element
 	 */
 	public CollectionModelElement(String name) {
 		super(name);
 	}
 	
+	@Override
 	public void addObject(AbstractObject object) {
 		if (!objects.contains(object)) {
 			objects.add(object);
 			object.addPropertyChangeListener(this);
+			getDiagram().createMemberConnections(this, object);
 			firePropertyChange(PROP_TOTAL_RECORDS, null, objects);
 			firePropertyChange(PROP_RECORDS, null, objects);
 			validateCurrent();
 		}
 	}
-	
+
+	@Override
 	public boolean contains(AbstractObject object) {
 		if (objects == null) {
 			return false;
@@ -99,37 +116,25 @@
 		return objects.contains(object);
 	}
 
-	/**
-	 * @return the AbstractObject currently being displayed.
-	 */
+	@Override
 	public AbstractObject getCurrentObject() {
 		return current;
 	}
 
 	/**
-	 * Get the IPropertyDescriptors for use in the Eclipse Properties view.
-	 * Creates the property descriptor array once on demand.
-	 * @return property descriptors for the current AbstractObject and the
-	 * CollectionModelElement, or just the latter if the former is null.
-	 */
-	public IPropertyDescriptor[] getPropertyDescriptors() {
-		if (current == null) {
-			return CollectionModelElement.descriptors;
-		}
-		if (properties == null) {
-			IPropertyDescriptor[] objectProperties = current.getPropertyDescriptors();
-			properties = new IPropertyDescriptor[objectProperties.length + CollectionModelElement.descriptors.length];
-			int i = 0;
-			for (; i < objectProperties.length; i++) {
-				properties[i] = objectProperties[i];
-			}
-			for (int j = 0; j < CollectionModelElement.descriptors.length; i++, j++) {
-				properties[i] = CollectionModelElement.descriptors[j];
-			}
+	 * Returns an iterator over the collection's objects, sorted based on the specified attribute name
+	 * @param sortAttribute name of the attribute on which to sort
+	 * @return an iterator over the objects in order
+	 */
+	public Iterator<AbstractObject> getSortedObjectIterator(String sortAttribute) {
+		if (objects != null) {
+			List<AbstractObject> copyObjects = new ArrayList<AbstractObject>(objects);
+			Collections.sort(copyObjects, new AbstractObjectComparator(sortAttribute));
+			return copyObjects.iterator();
 		}
-		return properties;
+		return null;
 	}
-
+	
 	@Override
 	public Object getPropertyValue(Object id) {
 		if (id.toString().equals(PROP_CURRENT_RECORD)) {
@@ -140,7 +145,7 @@
 		}
 		return super.getPropertyValue(id);
 	}
-
+	
 	@Override
 	public boolean isContextless() {
 		for (AbstractObject object : objects) {
@@ -150,12 +155,13 @@
 		}
 		return !isNull();
 	}
-	
+
 	@Override
 	public boolean isNull() {
 		return (objects == null || objects.isEmpty());
 	}
-	
+
+	@Override
 	public boolean isPropertySet(Object id) {
 		if (id.toString().equals(PROP_CURRENT_RECORD)) {
 			return true;
@@ -165,7 +171,7 @@
 		}
 		return super.isPropertySet(id);
 	}
-
+	
 	/**
 	 * Scrolls through the AbstractObject list, cycling back to the start once the
 	 * end is reached.
@@ -204,6 +210,22 @@
 		}
 	}
 	
+	@Override
+	public void removeDeletedObjects() {
+		if (objects != null) {
+			ArrayList<AbstractObject> deleted = new ArrayList<AbstractObject>();
+			for (AbstractObject object : objects) {
+				if (object.isDeleted()) {
+					deleted.add(object);
+				}
+			}
+			for (AbstractObject object : deleted) {
+				removeObject(object);
+			}
+		}
+	}
+
+	@Override
 	public void removeObject(AbstractObject object) {
 		if (objects != null) {
 			if (objects.remove(object)) {
@@ -231,11 +253,28 @@
 	}
 
 	/**
+	 * Set the current object to the specified object. This does not
+	 * modify the collection of objects, it simply specifies that the
+	 * given object should become the current one (be displayed).
+	 * If the object is not found in the collection, no change is made.
+	 */
+	public void setCurrentObject(AbstractObject object) {
+		if (objects != null && objects.contains(object)) {
+			int oldCurrent = currentRecord;
+			current = object;
+			currentRecord = objects.indexOf(object);
+			firePropertyChange(PROP_CURRENT_RECORD, new Integer(oldCurrent), new Integer(currentRecord));
+		}
+	}
+
+	/**
 	 * Set the records to be displayed. Adds itself as a listener
 	 * to all the AbstractObjects in the list in order to fire its
 	 * own property change events when the underlying data is changed.
+	 * The collection should always hold a list, even if it is empty.
 	 * @param value may be null, an empty list or a list of AbstractObjects.
 	 */
+	@Override
 	public void setObject(Object value) {
 		
 		if (value == this.objects) {
@@ -245,6 +284,7 @@
 		List<AbstractObject> oldObjects = this.objects;
 		this.currentRecord = 0;
 		
+		// remove the element as a listener from the previous objects
 		if (oldObjects != null) {
 			for (AbstractObject oldObject : oldObjects) {
 				oldObject.removePropertyChangeListener(this);
@@ -270,6 +310,7 @@
 			this.current = null;
 		}
 		
+		// add element as a property listener to each object
 		for (AbstractObject object : objects) {
 			object.addPropertyChangeListener(this);
 		}
@@ -280,7 +321,7 @@
 		
 		firePropertyChange(PROP_RECORDS, oldObjects, objects);
 	}
-
+	
 	@Override
 	public void setPropertyValue(Object id, Object value) {
 		if (id.toString().equals(PROP_CURRENT_RECORD)) {
@@ -293,7 +334,11 @@
 			super.setPropertyValue(id, value);
 		}
 	}
-
+	
+	/**
+	 * Check that the current object is still contained in the element
+	 * and that the current record number is correct
+	 */
 	protected void validateCurrent() {
 		if (currentRecord > objects.size() - 1 || !objects.contains(current)) {
 			currentRecord = 0;
@@ -304,34 +349,6 @@
 				current = null;
 			}
 			firePropertyChange(PROP_CURRENT_RECORD, null, objects);
-		}
-	}
-
-	@Override
-	public void removeDeletedObjects() {
-		if (objects != null) {
-			ArrayList<AbstractObject> deleted = new ArrayList<AbstractObject>();
-			for (AbstractObject object : objects) {
-				if (object.isDeleted()) {
-					deleted.add(object);
-				}
-			}
-			for (AbstractObject object : deleted) {
-				removeObject(object);
-			}
-		}
-	}
-
-	public Iterator<AbstractObject> getObjectIterator() {
-		return objects.iterator();
-	}
-
-	public void setCurrentObject(AbstractObject object) {
-		if (objects != null && objects.contains(object)) {
-			int oldCurrent = currentRecord;
-			current = object;
-			currentRecord = objects.indexOf(object);
-			firePropertyChange(PROP_CURRENT_RECORD, new Integer(oldCurrent), new Integer(currentRecord));
 		}
 	}
 }

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/Connection.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/Connection.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/Connection.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/Connection.java Sun Aug  6 18:52:01 2006
@@ -27,7 +27,11 @@
 	protected ModelElement source;
 	/** Connection's target endpoint. */
 	protected ModelElement target;
-	
+	/**
+	 * Whether the connection is currently connected.
+	 * Certain commands will disconnect a connection and may
+	 * later restore it.
+	 */
 	private boolean connected;
 
 	/** 

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ElementDiagram.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ElementDiagram.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ElementDiagram.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ElementDiagram.java Sun Aug  6 18:52:01 2006
@@ -19,26 +19,29 @@
 import java.beans.PropertyChangeListener;
 import java.beans.PropertyChangeSupport;
 import java.util.ArrayList;
-import java.util.Collection;
 import java.util.List;
+
 import org.objectstyle.cayenne.ObjectContext;
-import org.objectstyle.cayenne.query.NamedQuery;
 
 /**
- * The root component in the model - a diagram of ModelElements 
- * representing objects.
+ * The root component in the model - a diagram of {@link ModelElement}s and 
+ * the {@link Connection}s between them.
  * 
  * @author Marcel Gordon
  */
 public class ElementDiagram {
 	
+	/** property indicating that changes have been committed to the database */
 	public static final String PROP_COMMIT = "ObjectDiagram.GraphCommitted";
+	/** property indicating that the layout has changed between automatic and manual */
 	public static final String PROP_LAYOUT = "ObjectDiagram.LayoutChanged";
 	/** property indicating a node (element) has been added */
 	public static final String PROP_NODE_ADDED = "ObjectDiagram.NodeAdded";
 	/** property indicating that a node (element) has been removed */
 	public static final String PROP_NODE_REMOVED = "ObjectDiagram.NodeRemoved";
+	/** property indicating that changes have been rolled back */
 	public static final String PROP_ROLLBACK = "ObjectDiagram.GraphRollback";
+	/** whether automatic layout is being used (rather than manual) */
 	private boolean autoLayout;
 	/** the Cayenne context in which the objects represented by the ModelElements exist */
 	protected ObjectContext context;
@@ -51,8 +54,6 @@
 	
 	/**
 	 * @param context the Cayenne context in which the objects in the diagram are found
-	 * @param query the name of the query contained in the Cayenne data map from which
-	 * this diagram is initialised
 	 */
 	public ElementDiagram(ObjectContext context) {
 		this.context = context;
@@ -60,17 +61,10 @@
 		autoLayout = true;
 	}
 	
-	public void addRootElement(Object matches) {
-		CollectionModelElement rootElement = new CollectionModelElement("ROOT");
-		rootElement.setObject(matches);
-		rootElement.setRoot(true);
-		addElement(rootElement);
-	}
-
 	/**
 	 * Add a ModelElement to the diagram
 	 * @param element the element to add
-	 * @return the element or its equivalent if it already exists
+	 * @return true if the element was added; false if not
 	 */	
 	public boolean addElement(ModelElement element) {
 		if (element != null) {
@@ -86,7 +80,7 @@
 		}
 		return false;
 	}
-	
+
 	/** 
 	 * Attach a non-null PropertyChangeListener to this object.
 	 * @param l a non-null PropertyChangeListener instance
@@ -99,6 +93,22 @@
 		pcsDelegate.addPropertyChangeListener(l);
 	}
 	
+	/**
+	 * Add a root element (an element created directly from a query)
+	 * to the diagram
+	 * @param matches the results of the query
+	 */
+	public void addRootElement(Object matches) {
+		CollectionModelElement rootElement = new CollectionModelElement("ROOT");
+		rootElement.setObject(matches);
+		rootElement.setRoot(true);
+		addElement(rootElement);
+	}
+	
+	/**
+	 * Commit changes made to {@link AbstractObject}s contained in
+	 * {@link ModelElement}s in the diagram back to the database.
+	 */
 	public void commitChanges() {
 		context.commitChanges();
 		firePropertyChange(PROP_COMMIT, false, true);
@@ -107,13 +117,45 @@
 		}
 	}
 	
-	public void createMemberConnections(ModelElement element) {
+	/**
+	 * Create {@link MemberConnection}s between the element passed in
+	 * and other elements in the diagram.
+	 * This function should be used where a single object is added to a {@link CollectionModelElement}
+	 * as it will only add member connections from the new object. In other cases
+	 * use {@link ElementDiagram#createMemberConnections(ModelElement)}.
+	 * This function does not remove existing member connections.
+	 * @param element a {@link CollectionModelElement} for which the connections are to be made
+	 * @param object the {@link AbstractObject} for which has just been added. Member connections will only be made to
+	 * {@link SingleModelElement}s which contain this object rather than any in the collection.
+	 */
+	public void createMemberConnections(CollectionModelElement element, AbstractObject object) {
+		if (element instanceof CollectionModelElement) {
+			for (ModelElement child : elements) {
+				if (child instanceof SingleModelElement) {
+					if (object == child.getCurrentObject()) {
+						MemberConnection connection = new MemberConnection(element, (SingleModelElement) child);
+						connection.connect();
+					}
+				}
+			}
+		}
+	}
+	
+	/**
+	 * Create {@link MemberConnection}s between the element passed in
+	 * and other elements in the diagram.
+	 * Existing member connections are removed first.
+	 */
+	void createMemberConnections(ModelElement element) {
 		if (element instanceof CollectionModelElement) {
+			// disconnect any existing member connections
 			for (Connection conn : element.getSourceConnections()) {
 				if (conn instanceof MemberConnection) {
 					conn.disconnect();
 				}
 			}
+			// make member connections to any single elements with objects
+			// which this collection contains
 			for (ModelElement child : elements) {
 				if (child instanceof SingleModelElement) {
 					if (((CollectionModelElement) element).contains(child.getCurrentObject())) {
@@ -124,11 +166,14 @@
 			}
 		}
 		else if (element instanceof SingleModelElement) {
+			// disconnect any existing member connections
 			for (Connection conn : element.getTargetConnections()) {
 				if (conn instanceof MemberConnection) {
 					conn.disconnect();
 				}
 			}
+			// make member connections to any collections which contain
+			// the object which this element contains
 			for (ModelElement child : elements) {
 				if (child instanceof CollectionModelElement) {
 					if (((CollectionModelElement) child).contains(element.getCurrentObject())) {
@@ -152,6 +197,12 @@
 		}
 	}
 	
+	/**
+	 * Get an element from the diagram.
+	 * @param newElement the element which is sought
+	 * @return the element if found, otherwise null
+	 * @see ModelElement#equals(Object)
+	 */
 	public ModelElement getElement(ModelElement newElement) {
 		for (ModelElement element : elements) {
 			if (element.equals(newElement)) {
@@ -160,25 +211,37 @@
 		}
 		return null;
 	}
-	
-	public ModelElement getSingleElementForObject(AbstractObject newObject) {
-		for (ModelElement element : elements) {
-			if (element.getCurrentObject() == newObject) {
-				return element;
-			}
-		}
-		return null;
-	}
 
 	/** Return a List of Objects in this diagram.  The returned List should not be modified. */
 	public List<ModelElement> getElements() {
 		return elements;
 	}
 
+	/**
+	 * @return the object context which objects in this diagram come from
+	 */
 	public ObjectContext getObjectContext() {
 		return context;
 	}
 	
+	/**
+	 * Get the single element from the diagram which contains the specified object
+	 * @param newObject the object which the element must contain
+	 * @return a {@link SingleModelElement} which contains the specified object, or null
+	 * if the diagram does not contain such an element.
+	 */
+	public SingleModelElement getSingleElementForObject(AbstractObject newObject) {
+		for (ModelElement element : elements) {
+			if (element instanceof SingleModelElement && element.getCurrentObject() == newObject) {
+				return (SingleModelElement) element;
+			}
+		}
+		return null;
+	}
+
+	/**
+	 * @return true if automatic layout is desired, false otherwise
+	 */
 	public boolean isAutoLayoutDesired() {
 		return autoLayout;
 	}
@@ -207,6 +270,9 @@
 		}
 	}
 
+	/**
+	 * Rollback changes made to objects in the diagram.
+	 */
 	public void rollbackChanges() {
 		context.rollbackChanges();
 		firePropertyChange(PROP_ROLLBACK, false, true);
@@ -215,6 +281,9 @@
 		}
 	}
 
+	/**
+	 * Toggle whether automatic layout is on or off
+	 */
 	public void toggleAutoLayout() {
 		autoLayout = !autoLayout;
 		firePropertyChange(PROP_LAYOUT, !autoLayout, autoLayout);

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/MemberConnection.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/MemberConnection.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/MemberConnection.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/MemberConnection.java Sun Aug  6 18:52:01 2006
@@ -16,8 +16,13 @@
  */
 package org.apache.cayenne.ropbrowser.model;
 
+import org.objectstyle.cayenne.map.Relationship;
+
 /**
- * A connection between two {@link ModelElement} objects.
+ * A connection between a {@link CollectionModelElement} and a
+ * {@link SingleModelElement} representing the fact that the
+ * former contains the object contained in the latter; that is, the
+ * latter single element is a member of the former collection.
  * 
  * @author Marcel Gordon
  */
@@ -33,10 +38,12 @@
 		super(source, target);
 	}
 	
+	@Override
 	public CollectionModelElement getSource() {
 		return (CollectionModelElement) source;
 	}
 	
+	@Override
 	public SingleModelElement getTarget() {
 		return (SingleModelElement) target;
 	}

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ModelElement.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ModelElement.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ModelElement.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/ModelElement.java Sun Aug  6 18:52:01 2006
@@ -22,7 +22,6 @@
 import java.util.ArrayList;
 import java.util.List;
 
-import org.eclipse.draw2d.ActionListener;
 import org.eclipse.draw2d.geometry.Rectangle;
 import org.eclipse.ui.views.properties.IPropertyDescriptor;
 import org.eclipse.ui.views.properties.IPropertySource;
@@ -36,9 +35,10 @@
  */
 public abstract class ModelElement implements IPropertySource, PropertyChangeListener {
 	
-	/** Property indicating a transient visual property has changed */
+	/** Property representing a change in the dimensions of the element */
 	public static final String PROP_BOUNDS = "ModelElement.bounds";
 	
+	/** Property representing the name of the element */
 	public static final String PROP_NAME = "ModelElement.Name";
 
 	/**
@@ -52,22 +52,54 @@
 	/** Property indicating that a target connection has been added or removed */
 	public static final String PROP_TARGET_CONN = "ModelElement.targetConnection";
 	
-	private boolean alreadyPolled = false;
+	/**
+	 * Used in checking whether the element is connected to a root
+	 * element to avoid infinite loops.
+	 */
+	private boolean connectedToRootAlreadyChecked = false;
 	
+	/**
+	 * The bounds of the element
+	 */
 	private Rectangle bounds;
 	
+	/**
+	 * The diagram which contains this element
+	 */
 	protected ElementDiagram diagram;
 	
+	/**
+	 * The name of the element, drawn from the name of the objects it contains
+	 */
 	protected String name;
+	
 	/** Delegate used to implemenent property-change-support. */
 	private transient PropertyChangeSupport pcsDelegate = new PropertyChangeSupport(this);
 	
+	/**
+	 * Whether the element is a root element (was the direct result of a query)
+	 */
 	protected boolean root = false;
 	
+	/**
+	 * Connections which begin at this element
+	 */
 	protected List<Connection> sourceConnections = new ArrayList<Connection>();
 
+	/**
+	 * Connections which end at this element
+	 */
 	protected List<Connection> targetConnections = new ArrayList<Connection>();
 	
+	/**
+	 * The property descriptors for the element and its objects; stored to save
+	 * recreating them every time they are requested.
+	 */
+	protected IPropertyDescriptor[] properties = null;
+	
+	/**
+	 * @param name the name of this element
+	 */
 	public ModelElement(String name) {
 		this.name = name;
 	}
@@ -95,6 +127,10 @@
 		}
 	}
 	
+	/**
+	 * Add an object to the element. This should only be used where the element
+	 * has already been added to the diagram. Otherwise, use {@link ModelElement#setObject(Object)}
+	 */
 	public abstract void addObject(AbstractObject object);
 	
 	/** 
@@ -109,8 +145,15 @@
 		pcsDelegate.addPropertyChangeListener(l);
 	}
 
+	/**
+	 * @param object object which is being sought
+	 * @return true if this element contains the object
+	 */
 	public abstract boolean contains(AbstractObject object);
 
+	/**
+	 * Delete the object which is currently being displayed by this element
+	 */
 	public void deleteCurrentObject() {
 		getCurrentObject().getObjectContext().deleteObject(getCurrentObject());
 	}
@@ -128,15 +171,21 @@
 	}
 	
 	/**
-	 * @return Returns the bounds.
+	 * @return the bounds of the element
 	 */
 	public Rectangle getBounds()
 	{
 		return bounds;
 	}
 	
+	/**
+	 * @return the object currently being displayed by this element
+	 */
 	public abstract AbstractObject getCurrentObject();
 
+	/**
+	 * @return the diagram which contains this element
+	 */
 	public ElementDiagram getDiagram() {
 		return diagram;
 	}
@@ -149,16 +198,26 @@
 		return this;
 	}
 	
+	/**
+	 * @return the name of the element, drawn from the name
+	 * of the object which it contains
+	 */
 	public String getName() {
 		return name;
 	}
 	
 	/**
 	 * Property descriptors for editing via the Eclipse Properties view.
-	 * <p>Default implementation returns an array of size 0. Extending classes
-	 * should override to allow properties to be edited.
+	 * Returns the property descriptors for the current object.
 	 */
 	public IPropertyDescriptor[] getPropertyDescriptors() {
+		
+		if (getCurrentObject() != null) {
+			if (properties == null) {
+				properties = getCurrentObject().getPropertyDescriptors();
+			}
+			return properties;
+		}
 		return new IPropertyDescriptor[0];
 	}
 	
@@ -194,31 +253,40 @@
 		firePropertyChange(evt.getPropertyName(), evt.getOldValue(), evt.getNewValue());
 	}
 	
+	/**
+	 * Recursive function to check if this element is connected to a root element
+	 * @return true if this element is connected to a root element
+	 */
 	public boolean isConnectedToRoot() {
 		if (isRoot()) {
 			return true;
 		}
-		if (!alreadyPolled) {
-			alreadyPolled = true;
+		// check if we have already visited this element
+		// to avoid infinite loops
+		if (!connectedToRootAlreadyChecked) {
+			connectedToRootAlreadyChecked = true;
 			for (Connection conn : getTargetConnections()) {
 				if (conn.getSource().isConnectedToRoot()) {
-					alreadyPolled = false;
+					connectedToRootAlreadyChecked = false;
 					return true;
 				}
 			}
 		}
 		
-		alreadyPolled = false;
+		connectedToRootAlreadyChecked = false;
 		return false;
 	}
 
 	/**
-	 * Check if the element has objects, but none with a context.
+	 * @return true if the element has objects, but none with a context.
 	 * If isNull returns true, isContextless should return false (ie an element
 	 * that is null is not contextless).
 	 */
 	public abstract boolean isContextless();
 	
+	/**
+	 * @return true if the element does not contain any objects
+	 */
 	public abstract boolean isNull();
 	
 	/**
@@ -231,10 +299,19 @@
 		return false;
 	}
 	
+	/**
+	 * @return true if this element is a root element (was created directly by a query)
+	 */
 	public boolean isRoot() {
 		return this.root;
 	}
 	
+	/**
+	 * Set the bounds of the element, firing a property change.
+	 * Where the bounds have not been set before or a property event
+	 * is not desired, use {@link ModelElement#setBounds(Rectangle)}
+	 * @param newBounds the new dimensions of the element
+	 */
 	public void modifyBounds(Rectangle newBounds) {
 		Rectangle oldBounds = this.bounds;
 		if (!newBounds.equals(oldBounds))
@@ -281,20 +358,36 @@
 		}
 	}
 
+	/**
+	 * Set the bounds of the element without firing a property change.
+	 * Useful when setting the bounds initially. To fire a property change
+	 * event, use {@link ModelElement#modifyBounds(Rectangle)}
+	 * @param newBounds the new dimensions of the element
+	 */
 	public void setBounds(Rectangle newBounds) {
 		this.bounds = newBounds;
 	}
 	
+	/**
+	 * @param diagram the diagram which contains this element
+	 */
 	public void setDiagram(ElementDiagram diagram) {
 		this.diagram = diagram;
 	}
 	
+	/**
+	 * @param newName the name to set this element's name to
+	 */
 	public void setName(String newName) {
 		String oldName = name;
 		name = newName;
 		firePropertyChange(PROP_NAME, oldName, name);
 	}
 
+	/**
+	 * Set the object (or objects) to be displayed by this element.
+	 * @param object the object(s) to be contained in the element.
+	 */
 	public abstract void setObject(Object object);
 
 	/**
@@ -306,11 +399,21 @@
 		}
 	}
 
+	/**
+	 * @param root whether this is a root element (was directly created from a query). 
+	 */
 	public void setRoot(boolean root) {
 		this.root = root;
 	}
 
+	/**
+	 * Remove an object from this element.
+	 * @param object the object to remove
+	 */
 	public abstract void removeObject(AbstractObject object);
 
+	/**
+	 * Remove any objects which have been deleted from this element
+	 */
 	public abstract void removeDeletedObjects();
 }

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/RelationshipConnection.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/RelationshipConnection.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/RelationshipConnection.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/RelationshipConnection.java Sun Aug  6 18:52:01 2006
@@ -19,7 +19,8 @@
 import org.objectstyle.cayenne.map.Relationship;
 
 /**
- * A connection between two {@link ModelElement} objects.
+ * A connection between a {@link SingleModelElement} and another
+ * {@link ModelElement} representing a {@link Relationship}.
  * 
  * @author Marcel Gordon
  */
@@ -46,6 +47,7 @@
 		return relationship;
 	}
 	
+	@Override
 	public SingleModelElement getSource() {
 		return (SingleModelElement) source;
 	}

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/SingleModelElement.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/SingleModelElement.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/SingleModelElement.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/SingleModelElement.java Sun Aug  6 18:52:01 2006
@@ -16,19 +16,14 @@
  */
 package org.apache.cayenne.ropbrowser.model;
 
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-
 import org.eclipse.ui.views.properties.IPropertyDescriptor;
-import org.objectstyle.cayenne.PersistenceState;
-import org.objectstyle.cayenne.map.Relationship;
 
-// TODO allow drag and drop of single model element as insert existing
 
 /**
- * Class representing a collection of AbstractObjects.
- * Used to display a number of records as one element on the
- * canvas with the ability to scroll through them.
+ * An element which contains a single {@link AbstractObject}.
+ * The element will be a property listener for its object,
+ * rethrowing events to ensure visual updates (as the visual component
+ * represents the element rather than the object).
  * 
  * @author Marcel Gordon
  *
@@ -36,70 +31,40 @@
 public class SingleModelElement extends ModelElement {
 	
 	/**
-	 * List of AbstractObjects displayed by this element.
+	 * The object contained in this element
 	 */
 	protected AbstractObject object;
 	
 	
 	/**
-	 * @param createdFrom the ModelElement which initiated this element's creation.
+	 * @param name the name of this element
 	 */
 	public SingleModelElement(String name) {
 		super(name);
 	}
 	
-	/**
-	 * Set the records to be displayed. Adds itself as a listener
-	 * to all the AbstractObjects in the list in order to fire its
-	 * own property change events when the underlying data is changed.
-	 * @param value may be null, an empty list or a list of AbstractObjects.
-	 */
-	public void setObject(Object value) {
-		
-		if (value == this.object) {
-			return;
-		}
-		
-		AbstractObject oldObject = this.object;
-		
-		if (oldObject != null) {
-			oldObject.removePropertyChangeListener(this);
-		}
-		
-		this.object = (AbstractObject) value;
-		
-		if (object != null) {
-			this.object.addPropertyChangeListener(this);
-			name = this.object.getName();
-		}
-		
-		firePropertyChange(PROP_RECORDS, oldObject, object);
-	}
-	
-	/**
-	 * Get the IPropertyDescriptors for use in the Eclipse Properties view.
-	 * Creates the property descriptor array once on demand.
-	 * @return property descriptors for the current AbstractObject and the
-	 * CollectionModelElement, or just the latter if the former is null.
-	 */
-	public IPropertyDescriptor[] getPropertyDescriptors() {
-		if (object != null) {
-			return object.getPropertyDescriptors();
+	@Override
+	public void addObject(AbstractObject object) {
+		for (Connection conn : getTargetConnections()) {
+			if (conn instanceof RelationshipConnection) {
+				RelationshipConnection relConn = (RelationshipConnection) conn;
+				relConn.getSource().getCurrentObject().setRelationship(relConn.getRelationship(), getCurrentObject(), object);
+			}
 		}
-		return new IPropertyDescriptor[0];
+		setObject(object);
+		getDiagram().createMemberConnections(this);
 	}
 	
-	/**
-	 * @return the AbstractObject objectly being displayed.
-	 */
-	public AbstractObject getCurrentObject() {
-		return object;
+	@Override
+	public boolean contains(AbstractObject object) {
+		return (this.object == object);
 	}
 	
 	/**
-	 * Used to compare two CollectionModelElements to determine if one is
+	 * Used to compare two SingleModelElements to determine if one is
 	 * already in the {@link org.apache.cayenne.ropbrowser.model.ElementDiagram} and hence should not be created.
 	 */
+	@Override
 	public boolean equals(Object o) {
 		if (o instanceof SingleModelElement) {
 			return (this.object == ((SingleModelElement) o).getCurrentObject()) &&
@@ -107,55 +72,76 @@
 		}
 		return false;
 	}
-
+	
 	@Override
-	public void addObject(AbstractObject object) {
-		for (Connection conn : getTargetConnections()) {
-			if (conn instanceof RelationshipConnection) {
-				RelationshipConnection relConn = (RelationshipConnection) conn;
-				relConn.getSource().getCurrentObject().setRelationship(relConn.getRelationship(), getCurrentObject(), object);
-			}
-		}
-		setObject(object);
+	public AbstractObject getCurrentObject() {
+		return object;
 	}
 
 	@Override
-	public boolean isNull() {
-		return (object == null);
+	public boolean isContextless() {
+		return (getCurrentObject() != null && getCurrentObject().getObjectContext() == null);
 	}
 
 	@Override
-	public boolean isContextless() {
-		return (getCurrentObject() != null && getCurrentObject().getObjectContext() == null);
+	public boolean isNull() {
+		return (object == null);
 	}
 
 	@Override
-	public boolean contains(AbstractObject object) {
-		return (this.object == object);
+	public void removeDeletedObjects() {
+		if (getCurrentObject() != null) {
+			if (getCurrentObject().isDeleted()) {
+				removeObject(getCurrentObject());
+			}
+		}
 	}
 
 	@Override
-	public void removeObject(AbstractObject object) {
+	public void removeObject(AbstractObject object) {		
 		if (this.object == object && object != null) {
 			for (Connection conn : getTargetConnections()) {
+				// set incoming relationships to null
 				if (conn instanceof RelationshipConnection) {
 					RelationshipConnection relConn = (RelationshipConnection) conn;
 					relConn.getSource().getCurrentObject().setRelationship(relConn.getRelationship(), getCurrentObject(), null);
 				}
+				// remove all member connections
 				if (conn instanceof MemberConnection) {
 					conn.disconnect();
 				}
 			}
+			
 			setObject(null);
 		}
 	}
 
+	/**
+	 * Set the object to be displayed. Adds itself as a listener
+	 * to the {@link AbstractObject} in order to fire its
+	 * own property change events when the underlying data is changed.
+	 * @param value may be null or an AbstractObject.
+	 */
 	@Override
-	public void removeDeletedObjects() {
-		if (getCurrentObject() != null) {
-			if (getCurrentObject().isDeleted()) {
-				removeObject(getCurrentObject());
-			}
+	public void setObject(Object value) {
+		
+		if (value == this.object) {
+			return;
 		}
+		
+		AbstractObject oldObject = this.object;
+		
+		if (oldObject != null) {
+			oldObject.removePropertyChangeListener(this);
+		}
+		
+		this.object = (AbstractObject) value;
+		
+		if (object != null) {
+			this.object.addPropertyChangeListener(this);
+			name = this.object.getName();
+		}
+		
+		firePropertyChange(PROP_RECORDS, oldObject, object);
 	}
 }

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Artist.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Artist.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Artist.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Artist.java Sun Aug  6 18:52:01 2006
@@ -4,7 +4,7 @@
 import java.util.List;
 
 import org.apache.cayenne.ropbrowser.model.AbstractObject;
-import org.apache.cayenne.ropbrowser.model.Painting;
+import org.apache.cayenne.ropbrowser.model.Painting;
 
 /**
  * A generated persistent class mapped as "Artist" Cayenne entity. It is a good idea to

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Gallery.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Gallery.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Gallery.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Gallery.java Sun Aug  6 18:52:01 2006
@@ -3,7 +3,7 @@
 import java.util.List;
 
 import org.apache.cayenne.ropbrowser.model.AbstractObject;
-import org.apache.cayenne.ropbrowser.model.Painting;
+import org.apache.cayenne.ropbrowser.model.Painting;
 
 /**
  * A generated persistent class mapped as "Gallery" Cayenne entity. It is a good idea to

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Painting.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Painting.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Painting.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/model/auto/_Painting.java Sun Aug  6 18:52:01 2006
@@ -3,7 +3,7 @@
 import org.apache.cayenne.ropbrowser.model.AbstractObject;
 import org.apache.cayenne.ropbrowser.model.Artist;
 import org.apache.cayenne.ropbrowser.model.Gallery;
-import org.objectstyle.cayenne.ValueHolder;
+import org.objectstyle.cayenne.ValueHolder;
 
 /**
  * A generated persistent class mapped as "Painting" Cayenne entity. It is a good idea to

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/CollectionEditPart.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/CollectionEditPart.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/CollectionEditPart.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/CollectionEditPart.java Sun Aug  6 18:52:01 2006
@@ -16,39 +16,24 @@
  */
 package org.apache.cayenne.ropbrowser.parts;
 
-import java.beans.PropertyChangeEvent;
-import java.util.Iterator;
-
-import org.apache.cayenne.ropbrowser.actions.HideAction;
-import org.apache.cayenne.ropbrowser.actions.InsertAction;
-import org.apache.cayenne.ropbrowser.actions.SetNameAction;
-import org.apache.cayenne.ropbrowser.commands.ExistingObjectCommand;
-import org.apache.cayenne.ropbrowser.commands.ExistingObjectRequest;
-import org.apache.cayenne.ropbrowser.commands.HideElementCommand;
-import org.apache.cayenne.ropbrowser.commands.ObjectInsertCommand;
 import org.apache.cayenne.ropbrowser.commands.SetNameElementCommand;
+import org.apache.cayenne.ropbrowser.commands.SetNameElementRequest;
 import org.apache.cayenne.ropbrowser.figures.CollectionFigure;
-import org.apache.cayenne.ropbrowser.figures.CompartmentFigure;
-import org.apache.cayenne.ropbrowser.figures.ElementFigure;
 import org.apache.cayenne.ropbrowser.model.AbstractObject;
 import org.apache.cayenne.ropbrowser.model.CollectionModelElement;
-import org.apache.cayenne.ropbrowser.model.ModelElement;
 import org.apache.cayenne.ropbrowser.policies.CollectionDirectEditPolicy;
 import org.apache.cayenne.ropbrowser.policies.CollectionSelectionPolicy;
 import org.eclipse.draw2d.ActionEvent;
 import org.eclipse.draw2d.ActionListener;
 import org.eclipse.draw2d.Button;
-import org.eclipse.draw2d.Figure;
 import org.eclipse.draw2d.IFigure;
-import org.eclipse.draw2d.Label;
-import org.eclipse.draw2d.geometry.Point;
 import org.eclipse.gef.EditPolicy;
 import org.eclipse.gef.Request;
 import org.eclipse.gef.commands.Command;
 
 /**
  * EditPart for the {@link CollectionModelElement} class. Allows
- * scrolling through records and expansion of relationships.
+ * scrolling through records and popout of member elements.
  * 
  * @author Marcel Gordon
  */
@@ -56,10 +41,11 @@
 	
 	/**
 	 * Extends super to allow scrolling through records on double-click and
-	 * expansion of relationships on single-click.
+	 * pop out of elements on single click.
 	 * 
 	 * @see ElementEditPart#createEditPolicies()
 	 */
+	@Override
 	protected void createEditPolicies() {
 		super.createEditPolicies();
 		
@@ -70,6 +56,7 @@
 	/**
 	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
 	 */
+	@Override
 	protected IFigure createFigure() {		
 		CollectionFigure figure = new CollectionFigure(this);
 				
@@ -80,14 +67,19 @@
 		return (CollectionModelElement) getModel();
 	}
 	
+	@Override
 	public Command getCommand(Request request) {
-		if (request.getType().equals(SetNameAction.SET_NAME_REQUEST)) {
-			return new SetNameElementCommand(this.getModelCast());
+		if (request.getType().equals(SetNameElementRequest.SET_NAME_REQUEST)) {
+			return new SetNameElementCommand(this.getModelCast(), ((SetNameElementRequest) request).getName());
 		}
 		// handle requests not in policies; pass the rest along
 		return super.getCommand(request); 
 	}
 
+	/**
+	 * Handle action events from dropdown buttons in the figure,
+	 * changing the object which is currently displayed
+	 */
 	public void actionPerformed(ActionEvent event) {
 		getModelCast().setCurrentObject((AbstractObject) ((Button) event.getSource()).getModel().getUserData());
 	}

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ConnectionEditPart.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ConnectionEditPart.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ConnectionEditPart.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ConnectionEditPart.java Sun Aug  6 18:52:01 2006
@@ -17,20 +17,19 @@
 package org.apache.cayenne.ropbrowser.parts;
 
 import org.apache.cayenne.ropbrowser.model.MemberConnection;
+import org.apache.cayenne.ropbrowser.model.ModelElement;
 import org.apache.cayenne.ropbrowser.model.RelationshipConnection;
-import org.apache.cayenne.ropbrowser.policies.SingleSelectionPolicy;
 import org.eclipse.draw2d.Graphics;
 import org.eclipse.draw2d.IFigure;
 import org.eclipse.draw2d.Label;
 import org.eclipse.draw2d.PolygonDecoration;
 import org.eclipse.draw2d.PolylineConnection;
-import org.eclipse.gef.EditPolicy;
+import org.eclipse.gef.EditPart;
 import org.eclipse.gef.editparts.AbstractConnectionEditPart;
-import org.eclipse.gef.editpolicies.ConnectionEndpointEditPolicy;
 
 /**
- * An EditPart for the {@link org.apache.cayenne.ropbrowser.model.Connection} class,
- * representing a relationship between two ModelElements.
+ * An {@link EditPart} for the {@link org.apache.cayenne.ropbrowser.model.Connection} class,
+ * representing a relationship between two {@link ModelElement}s.
  * 
  * @author Marcel Gordon
  */
@@ -39,17 +38,17 @@
 	@Override
 	protected void createEditPolicies() {
 	}
-	
-	/**
-	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
-	 */
+
+	@Override
 	protected IFigure createFigure() {
 		PolylineConnection connection = new PolylineConnection();
 		connection.setLineWidth(2);
 		connection.setTargetDecoration(new PolygonDecoration());
+		// dashed line represents a member connection
 		if (getModel() instanceof MemberConnection) {
 			connection.setLineStyle(Graphics.LINE_DASH);
 		}
+		// label relationship connections with name of relationship as a tooltip
 		else if (getModel() instanceof RelationshipConnection) {
 			connection.setToolTip(new Label(((RelationshipConnection) getModel()).getRelationship().getName()));
 		}

Modified: incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ElementDiagramEditPart.java
URL: http://svn.apache.org/viewvc/incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ElementDiagramEditPart.java?rev=429228&r1=429227&r2=429228&view=diff
==============================================================================
--- incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ElementDiagramEditPart.java (original)
+++ incubator/cayenne/soc/trunk/cayenne-rop/rop-browser/src/org/apache/cayenne/ropbrowser/parts/ElementDiagramEditPart.java Sun Aug  6 18:52:01 2006
@@ -19,7 +19,6 @@
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
 import java.util.ArrayList;
-import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
@@ -28,16 +27,13 @@
 import org.apache.cayenne.ropbrowser.layout.DelegatingLayoutManager;
 import org.apache.cayenne.ropbrowser.model.ElementDiagram;
 import org.apache.cayenne.ropbrowser.model.ModelElement;
-import org.apache.cayenne.ropbrowser.model.SingleModelElement;
 import org.eclipse.draw2d.ConnectionLayer;
 import org.eclipse.draw2d.Figure;
 import org.eclipse.draw2d.FreeformLayer;
 import org.eclipse.draw2d.IFigure;
 import org.eclipse.draw2d.MarginBorder;
-import org.eclipse.draw2d.PolylineConnection;
 import org.eclipse.draw2d.ShortestPathConnectionRouter;
 import org.eclipse.draw2d.geometry.Rectangle;
-import org.eclipse.gef.EditPart;
 import org.eclipse.gef.EditPolicy;
 import org.eclipse.gef.LayerConstants;
 import org.eclipse.gef.editparts.AbstractGraphicalEditPart;
@@ -53,11 +49,16 @@
 public class ElementDiagramEditPart extends AbstractGraphicalEditPart 
 	implements PropertyChangeListener  {
 	
+	/**
+	 * A layout manager used to delegate the layout to either an 
+	 * automatic or manual layout manager.
+	 */
 	private DelegatingLayoutManager delegatingLayoutManager;
 
 	/**
 	 * Upon activation, attach to the model element as a property change listener.
 	 */
+	@Override
 	public void activate() {
 		if (!isActive()) {
 			super.activate();
@@ -68,18 +69,18 @@
 	/**
 	 * @see org.eclipse.gef.editparts.AbstractEditPart#createEditPolicies()
 	 */
+	@Override
 	protected void createEditPolicies() {
 		// disallows the removal of this edit part from its parent
 		installEditPolicy(EditPolicy.COMPONENT_ROLE, new RootComponentEditPolicy());
-		// handles constraint changes (e.g. moving and/or resizing) of model elements
-		// and creation of new model elements
+		// removes any default layout policy
 		installEditPolicy(EditPolicy.LAYOUT_ROLE, null);
-		//installEditPolicy(EditPolicy.LAYOUT_ROLE,  new ElementXYLayoutEditPolicy());
 	}
 	
 	/**
 	 * @see org.eclipse.gef.editparts.AbstractGraphicalEditPart#createFigure()
 	 */
+	@Override
 	protected IFigure createFigure() {
 		Figure f = new FreeformLayer();
 		f.setBorder(new MarginBorder(3));
@@ -99,6 +100,7 @@
 	/**
 	 * Upon deactivation, detach from the model element as a property change listener.
 	 */
+	@Override
 	public void deactivate() {
 		if (isActive()) {
 			super.deactivate();
@@ -109,11 +111,15 @@
 	/**
 	 * @see org.eclipse.gef.editparts.AbstractEditPart#getModelChildren()
 	 */
+	@Override
 	protected List getModelChildren() {
 		ElementDiagram diagram = (ElementDiagram) this.getModel();
 		return new ArrayList<ModelElement>(diagram.getElements()); // return a list of objects
 	}
 	
+	/**
+	 * Remove any elements which are null from the diagram.
+	 */
 	public void hideNullObjects() {
 		for (Object o : getModelChildren()) {
 			ModelElement element = (ModelElement) o;
@@ -148,85 +154,69 @@
 		}
 	}
 
+	/**
+	 * @return true if automatic layout is desired
+	 */
 	public boolean isAutoLayoutDesired() {
 		return getModelCast().isAutoLayoutDesired();
 	}
 	
-	public ElementDiagram getModelCast() {
+	private ElementDiagram getModelCast() {
 		return (ElementDiagram) getModel();
 	}
 
 	/**
-	 * Updates the table bounds in the model so that the same bounds can be
-	 * restored after saving
+	 * Updates the element bounds in the model so that the same bounds
+	 * are maintained after the layout is changed to and from automatic. 
 	 * 
-	 * @return whether the procedure execute successfully without any omissions.
-	 *         The latter occurs if any TableFigure has no bounds set for any of
-	 *         the Table model objects
+	 * Adapted from Phil Zoio's SchemaEditor example.
+	 * 
+	 * @return whether the procedure executed successfully without any omissions.
 	 */
-	public boolean setTableModelBounds()
-	{
-
-		List tableParts = getChildren();
-
-		for (Iterator iter = tableParts.iterator(); iter.hasNext();)
-		{
-			ElementEditPart tablePart = (ElementEditPart) iter.next();
-			Figure tableFigure = (Figure) tablePart.getFigure();
-
-			//if we don't find a node for one of the children then we should
-			// continue
-			if (tableFigure == null)
-				continue;
-
-			Rectangle bounds = tableFigure.getBounds().getCopy();
-			ModelElement table = (ModelElement) tablePart.getModel();
-			table.setBounds(bounds);
+	public boolean setElementModelBounds() {
+		for (Object o : getChildren()) {
+			ElementEditPart elementEditPart = (ElementEditPart) o;
+			Figure elementFigure = (Figure) elementEditPart.getFigure();
+
+			if (elementFigure != null) {
+				Rectangle bounds = elementFigure.getBounds().getCopy();
+				ModelElement element = (ModelElement) elementEditPart.getModel();
+				element.setBounds(bounds);
+			}
 		}
 
 		return true;
-
 	}
 
 	/**
-	 * Updates the bounds of the table figure (without invoking any event
+	 * Updates the bounds of the element figure (without invoking any event
 	 * handling), and sets layout constraint data
 	 * 
+	 * Adapted from Phil Zoio's SchemaEditor example.
+	 * 
 	 * @return whether the procedure execute successfully without any omissions.
-	 *         The latter occurs if any Table objects have no bounds set or if
-	 *         no figure is available for the TablePart
 	 */
-	public boolean setTableFigureBounds(boolean updateConstraint)
-	{
+	public boolean setElementFigureBounds(boolean updateConstraint) {
 
-		List tableParts = getChildren();
+		for (Object o : getChildren()) {
+			ElementEditPart elementEditPart = (ElementEditPart) o;
+			ModelElement element = (ModelElement) elementEditPart.getModel();
 
-		for (Iterator iter = tableParts.iterator(); iter.hasNext();)
-		{
-			ElementEditPart tablePart = (ElementEditPart) iter.next();
-			ModelElement table = (ModelElement) tablePart.getModel();
-
-			//now check whether we can find an entry in the tableToNodesMap
-			Rectangle bounds = table.getBounds();
-			if (bounds == null)
-			{
+			Rectangle bounds = element.getBounds();
+			if (bounds == null) {
 				//TODO handle this better
 				return false;
 			}
-			else
-			{
-				Figure tableFigure = (Figure) tablePart.getFigure();
-				if (tableFigure == null)
-				{
+			else {
+				Figure elementFigure = (Figure) elementEditPart.getFigure();
+				if (elementFigure == null) {
 					return false;
 				}
-				else
-				{
-					if (updateConstraint)
-					{
+				else {
+					if (updateConstraint) {
 						//pass the constraint information to the xy layout
 						//setting the width and height so that the preferred size will be applied
-						delegatingLayoutManager.setXYLayoutConstraint(tableFigure, new Rectangle(bounds.x, bounds.y,
+						delegatingLayoutManager.setXYLayoutConstraint(elementFigure, new Rectangle(bounds.x, bounds.y,
 								-1, -1));
 					}
 				}