D3ConceptRelationshipTree, ConceptRelationshipComposite, ConceptRelationshipPresenter...
authorCherian Mathew <c.mathew@bgbm.org>
Wed, 22 Apr 2015 12:24:40 +0000 (14:24 +0200)
committerCherian Mathew <c.mathew@bgbm.org>
Wed, 22 Apr 2015 12:24:40 +0000 (14:24 +0200)
d3.conceptrelationshiptree_connector.js : updated to handle bi-directional display
D3CTree, ConceptRelationshipPresenterTest, d3ctree_connector.js : testing bi-directional display

src/main/java/eu/etaxonomy/cdm/vaadin/component/ConceptRelationshipComposite.java
src/main/java/eu/etaxonomy/cdm/vaadin/jscomponent/D3ConceptRelationshipTree.java
src/main/java/eu/etaxonomy/cdm/vaadin/presenter/ConceptRelationshipPresenter.java
src/main/java/eu/etaxonomy/cdm/vaadin/view/ConceptRelationshipView.java
src/main/java/eu/etaxonomy/cdm/vaadin/view/IConceptRelationshipComponentListener.java
src/main/resources/eu/etaxonomy/cdm/vaadin/jscomponent/lib/d3.conceptrelationshiptree_connector.js
src/test/java/eu/etaxonomy/cdm/vaadin/jscomponent/D3CTree.java
src/test/java/eu/etaxonomy/cdm/vaadin/presenter/ConceptRelationshipPresenterTest.java
src/test/java/eu/etaxonomy/cdm/vaadin/ui/D3CTreeUI.java
src/test/resources/eu/etaxonomy/cdm/vaadin/jscomponent/lib/d3ctree_connector.js

index eb5db692b75d60d98983d57d9dc5091f06f90523..a608164c5c07e4f9478f4db641532344b087be6a 100644 (file)
@@ -26,6 +26,7 @@ import com.vaadin.ui.VerticalLayout;
 
 import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
 import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
 import eu.etaxonomy.cdm.vaadin.presenter.ConceptRelationshipPresenter;
 import eu.etaxonomy.cdm.vaadin.session.BasicEvent;
 import eu.etaxonomy.cdm.vaadin.session.CdmChangeEvent;
@@ -160,10 +161,10 @@ public class ConceptRelationshipComposite extends CustomComponent implements ISe
     }
 
 
-    private void refreshRelationshipView() {
+    private void refreshRelationshipView(Direction direction) {
         if(fromTaxonIun != null) {
             try {
-                listener.refreshRelationshipView(fromTaxonIun);
+                listener.refreshRelationshipView(fromTaxonIun, direction);
             } catch (JSONException e) {
                 Notification.show("Error generating concept relation JSON",  e.getMessage(), Type.WARNING_MESSAGE);
             }
@@ -188,8 +189,8 @@ public class ConceptRelationshipComposite extends CustomComponent implements ISe
     public void onSelect(SelectionEvent event) {
         if(event.getSourceType().equals(StatusComposite.class)) {
             fromTaxonIun = (IdUuidName)event.getSelectedObjects().get(0);
-            view.setPrimaryStatusComposite((UUID)event.getSelectedObjects().get(1));
-            refreshRelationshipView();
+            view.setPrimaryStatusCompositeUuid((UUID)event.getSelectedObjects().get(1));
+            refreshRelationshipView(view.getDirection());
         }
     }
 
@@ -202,7 +203,7 @@ public class ConceptRelationshipComposite extends CustomComponent implements ISe
     public void onCreate(CdmChangeEvent event) {
         if(event.getSourceType().equals(EditConceptRelationshipComposite.class)) {
             setSelectedTaxonRelUuid(null);
-            refreshRelationshipView();
+            refreshRelationshipView(view.getDirection());
 
         }
 
@@ -216,7 +217,7 @@ public class ConceptRelationshipComposite extends CustomComponent implements ISe
     public void onUpdate(CdmChangeEvent event) {
         if(event.getSourceType().equals(EditConceptRelationshipComposite.class)) {
             setSelectedTaxonRelUuid(null);
-            refreshRelationshipView();
+            refreshRelationshipView(view.getDirection());
         }
 
     }
@@ -229,7 +230,7 @@ public class ConceptRelationshipComposite extends CustomComponent implements ISe
     public void onDelete(CdmChangeEvent event) {
         if(event.getSourceType().equals(EditConceptRelationshipComposite.class)) {
             setSelectedTaxonRelUuid(null);
-            refreshRelationshipView();
+            refreshRelationshipView(view.getDirection());
         }
 
     }
index 29a7012aa5affeb5d68721b282aac5c15ea83464..c2b413698b2d59d7102dd9c698e9b541472376b6 100644 (file)
@@ -49,15 +49,37 @@ public class D3ConceptRelationshipTree extends AbstractJavaScriptComponent {
 
     private Mode mode;
 
+    public enum Direction {
+        LEFT_RIGHT("left-right"),
+        RIGHT_LEFT("right-left");
+
+        private final String name;
+
+        private Direction(String s) {
+            name = s;
+        }
+
+        @Override
+        public String toString(){
+           return name;
+        }
+    }
+
+    private Direction direction;
+
     private ConceptRelationshipComposite conceptRelComposite;
 
     public D3ConceptRelationshipTree() {
-        this(Mode.OneToOne);
+        this(Mode.OneToOne, Direction.LEFT_RIGHT);
     }
 
-    public D3ConceptRelationshipTree(Mode mode) {
-        this.mode = mode;
+    public D3ConceptRelationshipTree(Direction direction) {
+        this(Mode.OneToOne, direction);
+    }
 
+    public D3ConceptRelationshipTree(Mode mode, Direction direction) {
+        this.mode = mode;
+        this.direction = direction;
         addFunction("select", new JavaScriptFunction() {
 
             @Override
@@ -78,7 +100,8 @@ public class D3ConceptRelationshipTree extends AbstractJavaScriptComponent {
     }
 
 
-    public void update(Taxon fromTaxon) throws JSONException {
+    public void update(Taxon fromTaxon, Direction direction) throws JSONException {
+        this.direction = direction;
         switch(mode) {
         case OneToOne:
             updateForOneToOne(fromTaxon);
@@ -101,6 +124,7 @@ public class D3ConceptRelationshipTree extends AbstractJavaScriptComponent {
         fromTaxonJO.put("name", fromTaxon.getName().getTitleCache());
         fromTaxonJO.put("uuid", fromTaxon.getUuid().toString());
         fromTaxonJO.put("type", "taxon");
+        fromTaxonJO.put("direction", direction.toString());
 
         JSONArray ftChildren = new JSONArray();
         fromTaxonJO.put("children", ftChildren);
index 876946af0b25a3b69b24720e3625099625e5c7e9..313290cabe4265b8bbc59244b7c5c70d5826869e 100644 (file)
@@ -18,6 +18,7 @@ import eu.etaxonomy.cdm.model.common.CdmBase;
 import eu.etaxonomy.cdm.model.taxon.Taxon;
 import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
 import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
 import eu.etaxonomy.cdm.vaadin.util.CdmSpringContextHelper;
 import eu.etaxonomy.cdm.vaadin.view.IConceptRelationshipComponentListener;
 
@@ -43,10 +44,10 @@ public class ConceptRelationshipPresenter implements IConceptRelationshipCompone
     }
 
     @Override
-    public void refreshRelationshipView(IdUuidName taxonIun) throws JSONException {
+    public void refreshRelationshipView(IdUuidName taxonIun, Direction direction) throws JSONException {
         TransactionStatus tx = app.startTransaction();
         Taxon taxon = CdmBase.deproxy(taxonService.load(taxonIun.getUuid()), Taxon.class);
-        crTree.update(taxon);
+        crTree.update(taxon, direction);
         app.commitTransaction(tx);
     }
 
index a5233363b4a8421805e78ce94cad358e909286c5..7b677b1c2512aa35bbfc6a3d15ca0009ba48befd 100644 (file)
@@ -20,6 +20,7 @@ import com.vaadin.ui.HorizontalLayout;
 
 import eu.etaxonomy.cdm.vaadin.component.ConceptRelationshipComposite;
 import eu.etaxonomy.cdm.vaadin.component.StatusComposite;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
 import eu.etaxonomy.cdm.vaadin.session.BasicEvent;
 import eu.etaxonomy.cdm.vaadin.session.IBasicEventListener;
 import eu.etaxonomy.cdm.vaadin.util.CdmVaadinSessionUtilities;
@@ -43,6 +44,8 @@ public class ConceptRelationshipView extends CustomComponent implements View, IB
     private StatusComposite statusCompositeLeft;
 
     private StatusComposite primaryStatusComposite, secondaryStatusComposite;
+
+    private Direction direction;
     /**
      * The constructor should first build the main layout, set the
      * composition root and then do any custom initialization.
@@ -58,8 +61,8 @@ public class ConceptRelationshipView extends CustomComponent implements View, IB
         conceptRelationshipComposite.setView(this);
         conceptRelationshipComposite.setSizeFull();
 
-        setPrimaryStatusComposite(statusCompositeLeft.getSelectedClassificationUuid());
-
+        setPrimaryStatusCompositeUuid(statusCompositeLeft.getSelectedClassificationUuid());
+        direction = Direction.LEFT_RIGHT;
         CdmVaadinSessionUtilities.getCurrentBasicEventService().register(this);
     }
 
@@ -72,14 +75,21 @@ public class ConceptRelationshipView extends CustomComponent implements View, IB
 
     }
 
-    public void setPrimaryStatusComposite(UUID scUuid) {
+    public Direction getDirection() {
+        return direction;
+    }
+
+    public void setPrimaryStatusCompositeUuid(UUID scUuid) {
         if(scUuid != null) {
-            if(statusCompositeLeft.getSelectedClassificationUuid().equals(scUuid)) {
+            if(scUuid.equals(statusCompositeLeft.getSelectedClassificationUuid())) {
                 primaryStatusComposite = statusCompositeLeft;
                 secondaryStatusComposite = statusCompositeRight;
-            } else {
+                direction = Direction.LEFT_RIGHT;
+            }
+            if(scUuid.equals(statusCompositeRight.getSelectedClassificationUuid())) {
                 secondaryStatusComposite = statusCompositeLeft;
                 primaryStatusComposite = statusCompositeRight;
+                direction = Direction.RIGHT_LEFT;
             }
             secondaryStatusComposite.clearTaxaTableSelections();
         }
index 508bfc57303871c4f909daf5be510efdf3bcf518..e8e0975ecb43e8706fcab49b09b7b9defd35a3f8 100644 (file)
@@ -12,6 +12,7 @@ package eu.etaxonomy.cdm.vaadin.view;
 import org.json.JSONException;
 
 import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
 
 /**
  * @author cmathew
@@ -21,10 +22,11 @@ import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
 public interface IConceptRelationshipComponentListener {
 
     /**
-     * @param taxonUuid
+     * @param taxonIun
+     * @param direction
      * @throws JSONException
      */
-    public void refreshRelationshipView(IdUuidName taxonUuid) throws JSONException;
+    public void refreshRelationshipView(IdUuidName taxonIun, Direction direction) throws JSONException;
 
 
 
index cffe15676b528eb1570ee2157658199e0c45f88e..a5ccb057dd4f03306887e318e742ab775fa3ae31 100644 (file)
@@ -1,5 +1,9 @@
 
-
+/**
+ * D3 Layout Tree (inspired by http://bl.ocks.org/mbostock/4339083)
+ * which displays a list concept relationships between a 'from' taxon 
+ * and a number of 'to' taxon
+ */
 window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function() {
     var connector = this;
     var diagramElement = connector.getElement();
@@ -11,11 +15,8 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function(
     duration = 750,
     root;
 
-    var tree = d3.layout.tree()
-    .size([height, width]);
-
-    var diagonal = d3.svg.diagonal()
-    .projection(function(d) { return [d.y, d.x]; });
+    var tree;
+    var diagonal;
 
     var svg = d3.select(diagramElement).append("svg")
     .attr("width", width + margin.right + margin.left)
@@ -24,31 +25,61 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function(
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
     var selectedNode;
+    
+    var orientations = {
+            "topbottom": {
+                size: [width, height],
+                x: function(d) { return d.x; },
+                y: function(d) { return d.y; }
+            },
+            "rightleft": {
+                size: [height, width],
+                x: function(d) { return width - d.y; },
+                y: function(d) { return d.x; }
+            },
+            "bottomtop": {
+                size: [width, height],
+                x: function(d) { return d.x; },
+                y: function(d) { return height - d.y; }
+            },
+            "leftright": {
+                size: [height, width],
+                x: function(d) { return d.y; },
+                y: function(d) { return d.x; }
+            }
+    };
+    // default setting is left-right
+    var orientation = orientations.rightleft;    
+    var tAnchorWithChildren = "end";
+    var tAnchorWithoutChildren = "start";
+    var dirMult = 1;
     this.onStateChange = function() {
         crTree = this.getState().conceptRelationshipTree;
 
         if(crTree) {
             root = JSON.parse(connector.getState().conceptRelationshipTree);
-
-            root.x0 = height / 2;
-            root.y0 = 0;
-
-            function collapse(d) {
-                if (d.children) {
-                    d._children = d.children;
-                    d._children.forEach(collapse);
-                    d.children = null;
-                }
+                        
+            if(root.direction === "left-right") {               
+                orientation = orientations.leftright;       
+                tAnchorWithChildren = "end";
+                tAnchorWithoutChildren = "start";
+                dirMult = 1;
             }
-
-            //root.children.forEach(collapse);
+            if(root.direction === "right-left") {                
+                orientation = orientations.rightleft;      
+                tAnchorWithChildren = "start";
+                tAnchorWithoutChildren = "end";
+                dirMult = -1;
+            }
+                        
+            diagonal = d3.svg.diagonal().projection(function(d) { return [orientation.x(d), orientation.y(d)]; });                
+            tree = d3.layout.tree().size(orientation.size);
             update(root);
-
-
             d3.select(self.frameElement).style("height", "800px");
-        }               
+        }           
     }
 
+    
     function update(source) {
 
         // Compute the new tree layout.
@@ -66,31 +97,31 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function(
         // Enter any new nodes at the parent's previous position.
         var nodeEnter = node.enter().append("g")
         .attr("class", "node")
-        .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
+        .attr("transform", function(d) { return "translate(" + orientation.x(source) + "," + orientation.y(source) + ")"; })
         .on("click", click);
 
         nodeEnter.append("circle")
         .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
         .style("fill", function(d) { return d === source && d.type === "conceptr" ? "#DF7401" : "#fff"; });
-
+        
         nodeEnter.append("text")
         .attr("x", function(d) { 
             if(d.type === "conceptr") { 
-                return 50;
+                return dirMult*50;
             } else {
-                return d.children || d._children ? -10 : 10; 
+                return d.children || d._children ? -1*dirMult*10 : dirMult*10; 
             }
         })
         .attr("y", function(d) { return d.type === "conceptr" ? -20 : 0; })
         .attr("dy", ".35em")
-        .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
+        .attr("text-anchor", function(d) { return d.children || d._children ? tAnchorWithChildren : tAnchorWithoutChildren; })
         .text(function(d) { return d.name; })
         .style("fill-opacity", 1e-6);
 
         // Transition nodes to their new position.
         var nodeUpdate = node.transition()
         .duration(duration)
-        .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
+        .attr("transform", function(d) { return "translate(" + orientation.x(d) + "," + orientation.y(d) + ")"; });
 
         nodeUpdate.select("circle")
         .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
@@ -101,25 +132,34 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function(
 
         // Transition exiting nodes to the parent's new position.
         var nodeExit = node.exit().transition()
-        .duration(duration)
-        .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
-        .remove();
+            .duration(duration)
+            .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
+            .remove();
 
         nodeExit.select("circle")
-        .attr("r", 1e-6);
+            .attr("r", 1e-6);
 
         nodeExit.select("text")
-        .style("fill-opacity", 1e-6);
-
+            .style("fill-opacity", 1e-6);
+        
         // Update the links…
         var link = svg.selectAll("path.link")
         .data(links, function(d) { return d.target.id; });
 
+        // Transition exiting nodes to the parent's new position.
+        link.exit().transition()
+            .duration(duration)
+            .attr("d", function(d) {
+              var o = {x: source.x, y: source.y};
+              return diagonal({source: o, target: o});
+            })
+            .remove();
+        
         // Enter any new links at the parent's previous position.
         link.enter().insert("path", "g")
         .attr("class", "link")
         .attr("d", function(d) {
-            var o = {x: source.x0, y: source.y0};
+            var o = {x: source.x, y: source.y};
             return diagonal({source: o, target: o});
         });
 
@@ -128,20 +168,6 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3ConceptRelationshipTree = function(
         .duration(duration)
         .attr("d", diagonal);
 
-        // Transition exiting nodes to the parent's new position.
-        link.exit().transition()
-        .duration(duration)
-        .attr("d", function(d) {
-            var o = {x: source.x, y: source.y};
-            return diagonal({source: o, target: o});
-        })
-        .remove();
-
-        // Stash the old positions for transition.
-        nodes.forEach(function(d) {
-            d.x0 = d.x;
-            d.y0 = d.y;
-        });
 
     }
 
index ed06a1b94b1ed5aac0ec828a5bb984388f62e658..ef0263a414b728564a2def79369367ee32e75afb 100644 (file)
@@ -32,7 +32,7 @@ public class D3CTree extends AbstractJavaScriptComponent {
     private static final Logger logger = Logger.getLogger(D3CTree.class);
 
     public D3CTree() {
-        addFunction("test", new JavaScriptFunction() {
+        addFunction("select", new JavaScriptFunction() {
 
             @Override
             public void call(JSONArray arguments) throws JSONException {
@@ -68,8 +68,8 @@ public class D3CTree extends AbstractJavaScriptComponent {
 
             cr1Children.put(0, taxonTo);
             cr2Children.put(0, taxonTo);
-            String conceptRelationshipTree = taxonFrom.toString();
-
+            //String conceptRelationshipTree = taxonFrom.toString();
+            String conceptRelationshipTree = "{\"direction\":\"right-left\",\"name\":\"Taxon d\",\"children\":[{\"name\":\"Congruent to\",\"children\":[{\"name\":\"Taxon e\",\"uuid\":\"84e99e24-f50a-4726-92d0-6088430c492a\",\"type\":\"taxon\"}],\"uuid\":\"511f504b-ae3b-4f04-b7b9-35c222f06e10\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon a\",\"uuid\":\"eaac797e-cac7-4649-97cf-c7b580076895\",\"type\":\"taxon\"}],\"uuid\":\"0e8b7922-974d-4389-b71e-af6fc9f98c56\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon b\",\"uuid\":\"5004a8e7-b907-4744-b67e-44ccb057ab3b\",\"type\":\"taxon\"}],\"uuid\":\"6fd9947e-21c3-4190-8748-57d9661e8659\",\"type\":\"conceptr\"},{\"name\":\"Excludes\",\"children\":[{\"name\":\"Taxon c\",\"uuid\":\"3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9\",\"type\":\"taxon\"}],\"uuid\":\"cc761030-38d2-4b5d-954d-32329c0ea106\",\"type\":\"conceptr\"}],\"uuid\":\"5f713f69-e03e-4a11-8a55-700fbbf44805\",\"type\":\"taxon\"}";
             logger.warn("conceptRelationshipTree : " + conceptRelationshipTree);
 
             setConceptRelationshipTree(conceptRelationshipTree);
index 30c483471459a8d092b49b69d39b6fc7f4b5dd8d..f5ad12a5c21d15fa90779337e5848ce13d3858e5 100644 (file)
@@ -21,6 +21,7 @@ import org.unitils.dbunit.annotation.DataSet;
 import eu.etaxonomy.cdm.vaadin.CdmVaadinBaseTest;
 import eu.etaxonomy.cdm.vaadin.container.IdUuidName;
 import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree;
+import eu.etaxonomy.cdm.vaadin.jscomponent.D3ConceptRelationshipTree.Direction;
 
 /**
  * @author cmathew
@@ -45,13 +46,15 @@ public class ConceptRelationshipPresenterTest extends CdmVaadinBaseTest {
     @Test
     public void testRefreshRelationshipView() throws JSONException {
         UUID taxonUuid = UUID.fromString("5f713f69-e03e-4a11-8a55-700fbbf44805");
-        crp.refreshRelationshipView(new IdUuidName(30, taxonUuid, null));
+        crp.refreshRelationshipView(new IdUuidName(30, taxonUuid, null), Direction.LEFT_RIGHT);
         String expected = "{\"name\":\"Taxon d\",\"children\":[{\"name\":\"Congruent to\",\"children\":[{\"name\":\"Taxon e\",\"uuid\":\"84e99e24-f50a-4726-92d0-6088430c492a\",\"type\":\"taxon\"}],\"uuid\":\"511f504b-ae3b-4f04-b7b9-35c222f06e10\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon a\",\"uuid\":\"eaac797e-cac7-4649-97cf-c7b580076895\",\"type\":\"taxon\"}],\"uuid\":\"0e8b7922-974d-4389-b71e-af6fc9f98c56\",\"type\":\"conceptr\"},{\"name\":\"Includes\",\"children\":[{\"name\":\"Taxon b\",\"uuid\":\"5004a8e7-b907-4744-b67e-44ccb057ab3b\",\"type\":\"taxon\"}],\"uuid\":\"6fd9947e-21c3-4190-8748-57d9661e8659\",\"type\":\"conceptr\"},{\"name\":\"Excludes\",\"children\":[{\"name\":\"Taxon c\",\"uuid\":\"3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9\",\"type\":\"taxon\"}],\"uuid\":\"cc761030-38d2-4b5d-954d-32329c0ea106\",\"type\":\"conceptr\"}],\"uuid\":\"5f713f69-e03e-4a11-8a55-700fbbf44805\",\"type\":\"taxon\"}";
+        logger.warn(crTree.getState().getConceptRelationshipTree());
         Assert.assertEquals(expected, crTree.getState().getConceptRelationshipTree());
 
         taxonUuid = UUID.fromString("3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9");
-        crp.refreshRelationshipView(new IdUuidName(20, taxonUuid, null));
+        crp.refreshRelationshipView(new IdUuidName(20, taxonUuid, null), Direction.LEFT_RIGHT);
         expected = "{\"name\":\"Taxon c\",\"children\":[],\"uuid\":\"3d71c8b8-3bec-4f5f-ba23-6f9d55ef84e9\",\"type\":\"taxon\"}";
+        logger.warn(crTree.getState().getConceptRelationshipTree());
         Assert.assertEquals(expected, crTree.getState().getConceptRelationshipTree());
 
     }
index e55ee1d68b7caeeb07236be89c20ae3124c7ad55..f841de67d62f73868678239fa60755ad7e727c23 100644 (file)
@@ -27,7 +27,7 @@ import eu.etaxonomy.cdm.vaadin.jscomponent.D3CTree;
  * @date 8 Apr 2015
  *
  */
-@Theme("mytheme")
+@Theme("edit")
 public class D3CTreeUI extends UI {
 
     private final static Logger logger =
index 4cbff2fd07d8eec66e47c319b076506a6dfefc02..1f6f3508f0531f4bfa217910ae45a365d2817f8d 100644 (file)
@@ -11,11 +11,8 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3CTree = function() {
     duration = 750,
     root;
 
-    var tree = d3.layout.tree()
-    .size([height, width]);
-
-    var diagonal = d3.svg.diagonal()
-    .projection(function(d) { return [d.y, d.x]; });
+    var tree;
+    var diagonal;
 
     var svg = d3.select(diagramElement).append("svg")
     .attr("width", width + margin.right + margin.left)
@@ -23,26 +20,64 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3CTree = function() {
     .append("g")
     .attr("transform", "translate(" + margin.left + "," + margin.top + ")");
 
-    //alert(this.getState().conceptRelationshipTree);
-    root = JSON.parse(this.getState().conceptRelationshipTree);
-
-    root.x0 = height / 2;
-    root.y0 = 0;
-
-    function collapse(d) {
-        if (d.children) {
-            d._children = d.children;
-            d._children.forEach(collapse);
-            d.children = null;
-        }
+    var selectedNode;
+    
+    var orientations = {
+            "topbottom": {
+                size: [width, height],
+                x: function(d) { return d.x; },
+                y: function(d) { return d.y; }
+            },
+            "rightleft": {
+                size: [height, width],
+                x: function(d) { return width - d.y; },
+                y: function(d) { return d.x; }
+            },
+            "bottomtop": {
+                size: [width, height],
+                x: function(d) { return d.x; },
+                y: function(d) { return height - d.y; }
+            },
+            "leftright": {
+                size: [height, width],
+                x: function(d) { return d.y; },
+                y: function(d) { return d.x; }
+            }
+    };
+    // default setting is left-right
+    var orientation = orientations.rightleft;    
+    var tAnchorWithChildren = "end";
+    var tAnchorWithoutChildren = "start";
+    var dirMult = 1;
+    this.onStateChange = function() {
+        crTree = this.getState().conceptRelationshipTree;
+
+        if(crTree) {
+            root = JSON.parse(connector.getState().conceptRelationshipTree);
+                        
+            if(root.direction === "left-right") {               
+                orientation = orientations.leftright;       
+                tAnchorWithChildren = "end";
+                tAnchorWithoutChildren = "start";
+                dirMult = 1;
+            }
+            if(root.direction === "right-left") {                
+                orientation = orientations.rightleft;      
+                tAnchorWithChildren = "start";
+                tAnchorWithoutChildren = "end";
+                dirMult = -1;
+            }
+                        
+            diagonal = d3.svg.diagonal().projection(function(d) { return [orientation.x(d), orientation.y(d)]; });            
+            tree = d3.layout.tree().size(orientation.size);
+
+
+            update(root);
+            d3.select(self.frameElement).style("height", "800px");
+        }           
     }
 
-    root.children.forEach(collapse);
-    update(root);
-
-
-    d3.select(self.frameElement).style("height", "800px");
-
+    
     function update(source) {
 
         // Compute the new tree layout.
@@ -60,45 +95,39 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3CTree = function() {
         // Enter any new nodes at the parent's previous position.
         var nodeEnter = node.enter().append("g")
         .attr("class", "node")
-        .attr("transform", function(d) { return "translate(" + source.y0 + "," + source.x0 + ")"; })
+        .attr("transform", function(d) { return "translate(" + orientation.x(source) + "," + orientation.y(source) + ")"; })
         .on("click", click);
 
         nodeEnter.append("circle")
-        .attr("r", 10)
-        .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
-
+        .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
+        .style("fill", function(d) { return d === source && d.type === "conceptr" ? "#DF7401" : "#fff"; });
+        
         nodeEnter.append("text")
-        .attr("x", function(d) { return d.children || d._children ? -10 : 10; })
-        .attr("y", "-10")
+        .attr("x", function(d) { 
+            if(d.type === "conceptr") { 
+                return dirMult*50;
+            } else {
+                return d.children || d._children ? -1*dirMult*10 : dirMult*10; 
+            }
+        })
+        .attr("y", function(d) { return d.type === "conceptr" ? -20 : 0; })
         .attr("dy", ".35em")
-        .attr("text-anchor", function(d) { return d.children || d._children ? "end" : "start"; })
+        .attr("text-anchor", function(d) { return d.children || d._children ? tAnchorWithChildren : tAnchorWithoutChildren; })
         .text(function(d) { return d.name; })
         .style("fill-opacity", 1e-6);
 
         // Transition nodes to their new position.
         var nodeUpdate = node.transition()
         .duration(duration)
-        .attr("transform", function(d) { return "translate(" + d.y + "," + d.x + ")"; });
+        .attr("transform", function(d) { return "translate(" + orientation.x(d) + "," + orientation.y(d) + ")"; });
 
         nodeUpdate.select("circle")
-        .attr("r", 10)
-        .style("fill", function(d) { return d._children ? "lightsteelblue" : "#fff"; });
+        .attr("r", function(d) { return d.type === "taxon" ? 5 : 10; })
+        .style("fill", function(d) { return d === selectedNode && d.type === "conceptr" ? "#DF7401" : "#fff"; });
 
         nodeUpdate.select("text")
         .style("fill-opacity", 1);
 
-        // Transition exiting nodes to the parent's new position.
-        var nodeExit = node.exit().transition()
-        .duration(duration)
-        .attr("transform", function(d) { return "translate(" + source.y + "," + source.x + ")"; })
-        .remove();
-
-        nodeExit.select("circle")
-        .attr("r", 1e-6);
-
-        nodeExit.select("text")
-        .style("fill-opacity", 1e-6);
-
         // Update the links…
         var link = svg.selectAll("path.link")
         .data(links, function(d) { return d.target.id; });
@@ -107,7 +136,7 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3CTree = function() {
         link.enter().insert("path", "g")
         .attr("class", "link")
         .attr("d", function(d) {
-            var o = {x: source.x0, y: source.y0};
+            var o = {x: source.x, y: source.y};
             return diagonal({source: o, target: o});
         });
 
@@ -116,34 +145,18 @@ window.eu_etaxonomy_cdm_vaadin_jscomponent_D3CTree = function() {
         .duration(duration)
         .attr("d", diagonal);
 
-        // Transition exiting nodes to the parent's new position.
-        link.exit().transition()
-        .duration(duration)
-        .attr("d", function(d) {
-            var o = {x: source.x, y: source.y};
-            return diagonal({source: o, target: o});
-        })
-        .remove();
-
-        // Stash the old positions for transition.
-        nodes.forEach(function(d) {
-            d.x0 = d.x;
-            d.y0 = d.y;
-        });
 
     }
 
 //  Toggle children on click.
     function click(d) {
-        root.children.forEach(collapse);
-        connector.test(d.name);
-        if (d.children) {
-            d._children = d.children;
-            d.children = null;
-        } else {
-            d.children = d._children;
-            d._children = null;
+        //root.children.forEach(collapse);
+
+        if(d.type === "conceptr") {
+            connector.select(d.uuid);
         }
+
+        selectedNode = d;
         update(d);
     }
 }
\ No newline at end of file