From 92c53a0fbc08a49ac6e0d143fd34d62fd2a4784b Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 19 Nov 2018 15:14:12 +0100 Subject: [PATCH 01/17] moved IndexedNode to ui-core --- .../java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java | 2 +- .../ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java | 2 +- .../ch/hsr/adv/ui/core}/presentation/widgets/IndexedNode.java | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) rename {module-tree/src/main/java/ch/hsr/adv/ui/tree => ui-core/src/main/java/ch/hsr/adv/ui/core}/presentation/widgets/IndexedNode.java (95%) diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java index 3e6a606..0498f10 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java @@ -14,7 +14,7 @@ import ch.hsr.adv.ui.core.presentation.widgets.LabeledEdge; import ch.hsr.adv.ui.tree.domain.WalkerNode; import ch.hsr.adv.ui.tree.logic.WalkerTreeAlgorithm; -import ch.hsr.adv.ui.tree.presentation.widgets.IndexedNode; +import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import java.util.ArrayList; import java.util.List; diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java index aecbb0e..7d6ca5e 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java @@ -5,7 +5,7 @@ import ch.hsr.adv.ui.core.presentation.widgets.LabeledEdge; import ch.hsr.adv.ui.tree.domain.WalkerNode; import ch.hsr.adv.ui.tree.logic.TreeParser; -import ch.hsr.adv.ui.tree.presentation.widgets.IndexedNode; +import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import com.google.gson.Gson; import com.google.gson.JsonElement; import javafx.scene.Group; diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/widgets/IndexedNode.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java similarity index 95% rename from module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/widgets/IndexedNode.java rename to ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java index 66d9fde..01b4558 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/widgets/IndexedNode.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java @@ -1,7 +1,6 @@ -package ch.hsr.adv.ui.tree.presentation.widgets; +package ch.hsr.adv.ui.core.presentation.widgets; import ch.hsr.adv.commons.core.logic.domain.styles.ADVStyle; -import ch.hsr.adv.ui.core.presentation.widgets.LabeledNode; import javafx.geometry.HPos; import javafx.geometry.VPos; import javafx.scene.control.Label; From ed308da890913fd952069ca24bc9abc21884e27b Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 19 Nov 2018 16:41:27 +0100 Subject: [PATCH 02/17] updated to version 1.1.1 --- bintray.json | 6 +++--- build.gradle | 2 +- ui-core/build.gradle | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bintray.json b/bintray.json index 2fb3da4..6a6f9d1 100644 --- a/bintray.json +++ b/bintray.json @@ -9,14 +9,14 @@ ] }, "version": { - "name": "1.1", - "released": "2018-11-15", + "name": "1.1.1", + "released": "2018-11-19", "gpgSign": false }, "files": [ { "includePattern": "build/libs/(.*)", - "uploadPattern": "/ch/hsr/adv/adv-ui/1.1/$1", + "uploadPattern": "/ch/hsr/adv/adv-ui/1.1.1/$1", "matrixParams": { "override": 1 } diff --git a/build.gradle b/build.gradle index 01c18d6..175f4a0 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'ch.hsr.adv' -version = '1.1' +version = '1.1.1' /**************************************** * instructions for all projects diff --git a/ui-core/build.gradle b/ui-core/build.gradle index e45b2ee..34a24ce 100644 --- a/ui-core/build.gradle +++ b/ui-core/build.gradle @@ -30,7 +30,7 @@ dependencies { // common dependencies - compile('ch.hsr.adv:adv-commons:1.1') + compile('ch.hsr.adv:adv-commons:1.1.1') } mainClassName = 'ADVApplication' \ No newline at end of file From 3645aaf7c36fc5ed18e67e6a6cb160cbd18b1b91 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 19 Nov 2018 17:10:56 +0100 Subject: [PATCH 03/17] added IndexPosition to IndexedNode --- .../tree/presentation/TreeLayouterBase.java | 6 +- .../presentation/widgets/IndexPosition.java | 8 ++ .../presentation/widgets/IndexedNode.java | 89 +++++++++++-------- 3 files changed, 62 insertions(+), 41 deletions(-) create mode 100644 ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexPosition.java diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java index 0498f10..ad94efc 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java @@ -11,10 +11,11 @@ import ch.hsr.adv.ui.core.logic.Layouter; import ch.hsr.adv.ui.core.presentation.widgets.AutoScalePane; import ch.hsr.adv.ui.core.presentation.widgets.ConnectorType; +import ch.hsr.adv.ui.core.presentation.widgets.IndexPosition; +import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import ch.hsr.adv.ui.core.presentation.widgets.LabeledEdge; import ch.hsr.adv.ui.tree.domain.WalkerNode; import ch.hsr.adv.ui.tree.logic.WalkerTreeAlgorithm; -import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import java.util.ArrayList; import java.util.List; @@ -152,7 +153,8 @@ private Map createIndexedNodes(boolean showIndex) { style = new ADVDefaultElementStyle(); } IndexedNode indexedNode = new IndexedNode(index, element - .getContent(), style, ROUNDED_CORNER_STYLE, showIndex); + .getContent(), style, ROUNDED_CORNER_STYLE, showIndex, + IndexPosition.RIGHT); indexedNodes.put(index, indexedNode); } return indexedNodes; diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexPosition.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexPosition.java new file mode 100644 index 0000000..8137dd7 --- /dev/null +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexPosition.java @@ -0,0 +1,8 @@ +package ch.hsr.adv.ui.core.presentation.widgets; + +/** + * Available index positions for a IndexedNode + */ +public enum IndexPosition { + TOP, RIGHT +} diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java index 01b4558..b6dcf54 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java @@ -1,38 +1,37 @@ package ch.hsr.adv.ui.core.presentation.widgets; import ch.hsr.adv.commons.core.logic.domain.styles.ADVStyle; -import javafx.geometry.HPos; -import javafx.geometry.VPos; +import javafx.geometry.Insets; +import javafx.geometry.Pos; import javafx.scene.control.Label; -import javafx.scene.layout.Region; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Pane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; /** * Widget component for a indexed labeled node with optional rounded corners */ -public class IndexedNode extends Region { +public class IndexedNode extends Pane { private static final double INDEX_LABEL_DISTANCE = 5; private final LabeledNode labeledNode; - - private int centerX; - private int centerY; - private Label indexLabel; - private boolean showIndex; + private final Label indexLabel; public IndexedNode(long index, String labelText, ADVStyle style, - boolean isRoundedDown, boolean showIndex) { - this.showIndex = showIndex; - + boolean isRoundedDown, boolean showIndex, + IndexPosition indexPosition) { labeledNode = new LabeledNode(labelText, style, isRoundedDown); labeledNode.setX(0); labeledNode.setY(0); - getChildren().add(labeledNode); indexLabel = new Label(); indexLabel.setText(String.valueOf(index)); indexLabel.setVisible(showIndex); - getChildren().add(indexLabel); + indexLabel.setPadding(calculateInsets(indexPosition)); + + getChildren().add(createRootPane(indexPosition, showIndex)); } /** @@ -41,8 +40,7 @@ public IndexedNode(long index, String labelText, ADVStyle style, * @param x x coordinate */ public void setCenterX(int x) { - centerX = x; - layoutXProperty().set(centerX - labeledNode.getWidth() / 2); + layoutXProperty().set(x - labeledNode.getWidth() / 2); } /** @@ -51,37 +49,50 @@ public void setCenterX(int x) { * @param y y coordinate */ public void setCenterY(int y) { - centerY = y; - layoutYProperty().set(centerY - labeledNode.getHeight() / 2); + layoutYProperty().set(y - labeledNode.getHeight() / 2); } public LabeledNode getLabeledNode() { return labeledNode; } - /** - * Centers the label and the index on the node - */ - @Override - protected void layoutChildren() { + private Pane createRootPane(IndexPosition position, boolean showIndex) { if (showIndex) { - final double nodeHeight = getHeight(); - final double insetTop = getInsets().getTop(); - final double insetLeft = getInsets().getLeft(); - final double insetBottom = getInsets().getBottom(); - - final double contentHeight = (nodeHeight - insetTop - insetBottom); - double leftPos = insetLeft - + labeledNode.getWidth() + INDEX_LABEL_DISTANCE; - - layoutInArea(indexLabel, leftPos, insetTop, - indexLabel.getWidth(), contentHeight, - getBaselineOffset(), HPos.LEFT, VPos.CENTER); + switch (position) { + case TOP: + VBox vBox = new VBox(); + vBox.setAlignment(Pos.TOP_CENTER); + vBox.getChildren().add(indexLabel); + vBox.getChildren().add(labeledNode); + return vBox; + case RIGHT: + HBox hBox = new HBox(); + hBox.setAlignment(Pos.CENTER_LEFT); + hBox.getChildren().add(labeledNode); + hBox.getChildren().add(indexLabel); + return hBox; + default: + throw new IllegalArgumentException( + "unknown IndexPosition " + position.toString()); + } + } else { + StackPane pane = new StackPane(); + pane.setAlignment(Pos.CENTER); + pane.getChildren().add(labeledNode); + pane.getChildren().add(indexLabel); + return pane; } + } - setCenterX(centerX); - setCenterY(centerY); - - super.layoutChildren(); + private Insets calculateInsets(IndexPosition position) { + switch (position) { + case TOP: + return new Insets(0, 0, INDEX_LABEL_DISTANCE, 0); + case RIGHT: + return new Insets(0, 0, 0, INDEX_LABEL_DISTANCE); + default: + throw new IllegalArgumentException( + "unknown IndexPosition " + position.toString()); + } } } \ No newline at end of file From 0b96aaa8632348c45d8cf7fdbd806c5d816a7fed Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 19 Nov 2018 17:24:22 +0100 Subject: [PATCH 04/17] added IndexedNodes to module-array --- .../presentation/ArrayDefaultLayouter.java | 25 ++++++----- .../ui/array/presentation/ArrayLayouter.java | 11 +++-- .../ArrayObjectReferenceLayouter.java | 42 +++++++++++-------- .../ArrayDefaultLayouterTest.java | 2 +- .../array/presentation/ArrayLayouterTest.java | 26 +++++++++++- .../ArrayObjectReferenceLayouterTest.java | 2 +- 6 files changed, 72 insertions(+), 36 deletions(-) diff --git a/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouter.java b/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouter.java index e101e95..ce9ae48 100644 --- a/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouter.java +++ b/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouter.java @@ -3,10 +3,10 @@ import ch.hsr.adv.commons.array.logic.domain.ArrayElement; import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; import ch.hsr.adv.commons.core.logic.domain.styles.ADVStyle; -import ch.hsr.adv.commons.core.logic.domain.styles.presets - .ADVDefaultElementStyle; +import ch.hsr.adv.commons.core.logic.domain.styles.presets.ADVDefaultElementStyle; import ch.hsr.adv.ui.core.presentation.widgets.AutoScalePane; -import ch.hsr.adv.ui.core.presentation.widgets.LabeledNode; +import ch.hsr.adv.ui.core.presentation.widgets.IndexPosition; +import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import com.google.inject.Singleton; import javafx.geometry.Pos; import javafx.scene.layout.HBox; @@ -25,11 +25,12 @@ public class ArrayDefaultLayouter { * Layouts an array to look like a primitive array. * * @param moduleGroup moduleGroup to layout + * @param showIndices flag to show indices above array * @return layouted pane */ - public Pane layout(ModuleGroup moduleGroup) { + public Pane layout(ModuleGroup moduleGroup, boolean showIndices) { initializeContainer(); - drawElements(moduleGroup); + drawElements(moduleGroup, showIndices); scalePane.addChildren(valueContainer); @@ -42,19 +43,21 @@ private void initializeContainer() { valueContainer.setAlignment(Pos.CENTER); } - private void drawElements(ModuleGroup moduleGroup) { + private void drawElements(ModuleGroup moduleGroup, boolean showIndices) { + for (int i = 0; i < moduleGroup.getElements().size(); i++) { + ArrayElement element = + (ArrayElement) moduleGroup.getElements().get(i); - moduleGroup.getElements().forEach(e -> { - ArrayElement element = (ArrayElement) e; ADVStyle style = element.getStyle(); if (style == null) { style = new ADVDefaultElementStyle(); } - LabeledNode valueNode = new LabeledNode(element - .getContent(), style); + IndexedNode valueNode = new IndexedNode(i, element.getContent(), + style, false, showIndices, + IndexPosition.TOP); valueContainer.getChildren().add(valueNode); - }); + } } } diff --git a/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayLayouter.java b/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayLayouter.java index c5292e2..c21593f 100644 --- a/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayLayouter.java +++ b/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayLayouter.java @@ -38,24 +38,29 @@ public ArrayLayouter(ArrayObjectReferenceLayouter objectLayouter, * Delegates the layout of an array to the correct array layouter. * * @param moduleGroup to be layouted - * @param flags to switch between primitive array and object references + * @param flags to switch between primitive array and object + * references * @return layouted snapshot */ @Override public Pane layout(ModuleGroup moduleGroup, List flags) { boolean showObjectRelations = false; + boolean showIndices = false; if (flags != null) { showObjectRelations = flags.stream() .anyMatch(f -> f.equals(SHOW_OBJECT_RELATIONS)); + showIndices = flags.stream() + .anyMatch(f -> f.equals(ConstantsArray.SHOW_ARRAY_INDICES)); } if (showObjectRelations) { logger.info("Use Object Reference Array Layouter"); - return arrayObjectReferenceLayouter.layout(moduleGroup); + return arrayObjectReferenceLayouter.layout( + moduleGroup, showIndices); } else { logger.info("Use Default Array Layouter"); - return arrayDefaultLayouter.layout(moduleGroup); + return arrayDefaultLayouter.layout(moduleGroup, showIndices); } } } diff --git a/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouter.java b/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouter.java index ad2539b..cbffbb3 100644 --- a/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouter.java +++ b/module-array/src/main/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouter.java @@ -3,14 +3,9 @@ import ch.hsr.adv.commons.array.logic.domain.ArrayElement; import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; import ch.hsr.adv.commons.core.logic.domain.styles.ADVStyle; -import ch.hsr.adv.commons.core.logic.domain.styles.presets - .ADVDefaultElementStyle; -import ch.hsr.adv.commons.core.logic.domain.styles.presets - .ADVDefaultRelationStyle; -import ch.hsr.adv.ui.core.presentation.widgets.AutoScalePane; -import ch.hsr.adv.ui.core.presentation.widgets.ConnectorType; -import ch.hsr.adv.ui.core.presentation.widgets.LabeledEdge; -import ch.hsr.adv.ui.core.presentation.widgets.LabeledNode; +import ch.hsr.adv.commons.core.logic.domain.styles.presets.ADVDefaultElementStyle; +import ch.hsr.adv.commons.core.logic.domain.styles.presets.ADVDefaultRelationStyle; +import ch.hsr.adv.ui.core.presentation.widgets.*; import com.google.inject.Singleton; import javafx.geometry.Pos; import javafx.scene.layout.HBox; @@ -33,11 +28,12 @@ public class ArrayObjectReferenceLayouter { * Layouts an array with object references * * @param moduleGroup moduleGroup to layout + * @param showIndices flag to show indices above array * @return layouted pane */ - public Pane layout(ModuleGroup moduleGroup) { + public Pane layout(ModuleGroup moduleGroup, boolean showIndices) { initializeContainer(); - drawElements(moduleGroup); + drawElements(moduleGroup, showIndices); boxContainer.getChildren() .addAll(referenceContainer, valueContainer); @@ -57,28 +53,32 @@ private void initializeContainer() { boxContainer.setSpacing(SPACING); } - private void drawElements(ModuleGroup moduleGroup) { - moduleGroup.getElements().forEach(e -> { - ArrayElement element = (ArrayElement) e; + private void drawElements(ModuleGroup moduleGroup, boolean showIndices) { + for (int i = 0; i < moduleGroup.getElements().size(); i++) { + ArrayElement element = + (ArrayElement) moduleGroup.getElements().get(i); + ADVStyle style = element.getStyle(); if (style == null) { style = new ADVDefaultElementStyle(); } - LabeledNode referenceNode; + IndexedNode referenceNode; if (element.getContent() != null) { LabeledNode valueNode = new LabeledNode( element.getContent(), style); - referenceNode = new LabeledNode("*", style); - drawRelations(referenceNode, valueNode); + referenceNode = createIndexedNode("*", showIndices, i, + style); + drawRelations(referenceNode.getLabeledNode(), valueNode); valueContainer.getChildren().add(valueNode); } else { - referenceNode = new LabeledNode("null", style); + referenceNode = createIndexedNode("null", showIndices, i, + style); } referenceContainer.getChildren().addAll(referenceNode); - }); + } } private void drawRelations(LabeledNode referenceNode, @@ -92,4 +92,10 @@ private void drawRelations(LabeledNode referenceNode, scalePane.addChildren(relation); } + + private IndexedNode createIndexedNode(String label, boolean showIndices, + long index, ADVStyle style) { + return new IndexedNode(index, label, style, false, + showIndices, IndexPosition.TOP); + } } diff --git a/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouterTest.java b/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouterTest.java index 04c1343..750f4f7 100644 --- a/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouterTest.java +++ b/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayDefaultLayouterTest.java @@ -48,7 +48,7 @@ public void setUp() throws IOException, TimeoutException { @Test public void layoutTest() { // WHEN - Pane actual = sut.layout(moduleGroup); + Pane actual = sut.layout(moduleGroup, false); // THEN ObservableList children = actual.getChildren(); diff --git a/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayLayouterTest.java b/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayLayouterTest.java index 9e231fc..1509962 100644 --- a/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayLayouterTest.java +++ b/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayLayouterTest.java @@ -1,5 +1,6 @@ package ch.hsr.adv.ui.array.presentation; +import ch.hsr.adv.commons.array.logic.ConstantsArray; import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; import ch.hsr.adv.ui.array.logic.ArrayParser; import ch.hsr.adv.ui.core.access.FileDatastoreAccess; @@ -47,7 +48,7 @@ public void layoutDefaultTest(ArrayDefaultLayouter mockDefaultLayouter) { sut.layout(moduleGroup, null); // THEN - verify(mockDefaultLayouter).layout(moduleGroup); + verify(mockDefaultLayouter).layout(moduleGroup, false); } @Test @@ -59,7 +60,28 @@ public void layoutObjectReferenceTest(ArrayObjectReferenceLayouter sut.layout(moduleGroup, flags); // THEN - verify(mockObjectReferenceLayouter).layout(moduleGroup); + verify(mockObjectReferenceLayouter).layout(moduleGroup, false); + } + + @Test + public void layoutShowArrayIndicesTest( + ArrayDefaultLayouter mockDefaultLayouter) { + List flags = new ArrayList<>(); + flags.add(ConstantsArray.SHOW_ARRAY_INDICES); + sut.layout(moduleGroup, flags); + + verify(mockDefaultLayouter).layout(moduleGroup, true); + } + + @Test + public void layoutObjectReferenceAndShowArrayIndicesTest( + ArrayObjectReferenceLayouter mockObjectReferenceLayouter) { + List flags = new ArrayList<>(); + flags.add(ConstantsArray.SHOW_ARRAY_INDICES); + flags.add(SHOW_OBJECT_RELATIONS); + sut.layout(moduleGroup, flags); + + verify(mockObjectReferenceLayouter).layout(moduleGroup, true); } public static class Module extends JukitoModule { diff --git a/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouterTest.java b/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouterTest.java index 1836d19..c1b9225 100644 --- a/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouterTest.java +++ b/module-array/src/test/java/ch/hsr/adv/ui/array/presentation/ArrayObjectReferenceLayouterTest.java @@ -47,7 +47,7 @@ public void setUp() throws IOException, TimeoutException { @Test public void layoutTest() { // WHEN - Pane actual = sut.layout(moduleGroup); + Pane actual = sut.layout(moduleGroup, false); // THEN ObservableList children = actual.getChildren(); From f77a0478039d6120a07c1a2769f77f20a3b1c7bc Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Fri, 23 Nov 2018 14:25:47 +0100 Subject: [PATCH 05/17] fixed bug in IndexedNode that caused wrong position of nodes --- .../presentation/widgets/IndexedNode.java | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java index b6dcf54..2d2be7d 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java @@ -19,6 +19,9 @@ public class IndexedNode extends Pane { private final LabeledNode labeledNode; private final Label indexLabel; + private int preferredX; + private int preferredY; + public IndexedNode(long index, String labelText, ADVStyle style, boolean isRoundedDown, boolean showIndex, IndexPosition indexPosition) { @@ -40,7 +43,8 @@ public IndexedNode(long index, String labelText, ADVStyle style, * @param x x coordinate */ public void setCenterX(int x) { - layoutXProperty().set(x - labeledNode.getWidth() / 2); + preferredX = x; + layoutXProperty().set(preferredX - labeledNode.getWidth() / 2); } /** @@ -49,7 +53,8 @@ public void setCenterX(int x) { * @param y y coordinate */ public void setCenterY(int y) { - layoutYProperty().set(y - labeledNode.getHeight() / 2); + preferredY = y; + layoutYProperty().set(preferredY - labeledNode.getHeight() / 2); } public LabeledNode getLabeledNode() { @@ -95,4 +100,15 @@ private Insets calculateInsets(IndexPosition position) { "unknown IndexPosition " + position.toString()); } } + + /** + * Updates position of IndexedNode so that the center of the Labeled Node + * is at preferredX / preferredY + */ + @Override + protected void layoutChildren() { + setCenterX(preferredX); + setCenterY(preferredY); + super.layoutChildren(); + } } \ No newline at end of file From a870a920c7a31a237760babf3cc8b78b771452fb Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Fri, 23 Nov 2018 14:51:15 +0100 Subject: [PATCH 06/17] added Tests for TreeBinaryTreeParser for MetaData --- .../ch/hsr/adv/ui/tree/logic/TreeParserTestBase.java | 12 ++++++++++++ .../logic/binarytree/TreeBinaryTreeParserTest.java | 12 ++++++++++++ .../src/test/resources/binary-tree-module-group.json | 9 ++++++++- 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/TreeParserTestBase.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/TreeParserTestBase.java index 2fbd4c4..a1ac208 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/TreeParserTestBase.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/TreeParserTestBase.java @@ -104,4 +104,16 @@ public void assertStyleOfRelationEquals(int relationIndex, int fillColor, assertEquals(strokeThickness, parsedStyle .getStrokeThickness(), DOUBLE_ACCURACY); } + + public void assertFlagIsSet(String flag) { + ModuleGroup actual = sut.parse(jsonElement); + + assertTrue(actual.getFlags().contains(flag)); + } + + public void assertMetaDataEquals(String metaDataKey, String expectedValue) { + ModuleGroup actual = sut.parse(jsonElement); + + assertEquals(expectedValue, actual.getMetaData().get(metaDataKey)); + } } diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/binarytree/TreeBinaryTreeParserTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/binarytree/TreeBinaryTreeParserTest.java index b050cb5..aea9497 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/binarytree/TreeBinaryTreeParserTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/logic/binarytree/TreeBinaryTreeParserTest.java @@ -1,5 +1,6 @@ package ch.hsr.adv.ui.tree.logic.binarytree; +import ch.hsr.adv.commons.tree.logic.ConstantsTree; import ch.hsr.adv.ui.core.access.FileDatastoreAccess; import ch.hsr.adv.ui.tree.logic.TreeParserTestBase; import com.google.inject.Inject; @@ -58,4 +59,15 @@ public void parseElementStyleTest() { public void parseRelationStyleTest() { base.assertStyleOfRelationEquals(0, 14006715, 12148586, "dashed", 7); } + + @Test + public void parseFlagTest() { + base.assertFlagIsSet(ConstantsTree.SHOW_ARRAY_INDICES); + } + + @Test + public void parseMetaDataTest() { + base.assertMetaDataEquals("max-right-tree-height", "2"); + base.assertMetaDataEquals("max-left-tree-height", "3"); + } } diff --git a/module-tree/src/test/resources/binary-tree-module-group.json b/module-tree/src/test/resources/binary-tree-module-group.json index fc70657..ad4b865 100644 --- a/module-tree/src/test/resources/binary-tree-module-group.json +++ b/module-tree/src/test/resources/binary-tree-module-group.json @@ -59,5 +59,12 @@ "sourceElementId": 3, "targetElementId": 6 } - ] + ], + "flags": [ + "show-array-indices" + ], + "metaData": { + "max-right-tree-height": "2", + "max-left-tree-height": "3" + } } \ No newline at end of file From 7717cd5a5c28f6b186ee047a83ea36545d2afd1c Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Fri, 23 Nov 2018 15:29:05 +0100 Subject: [PATCH 07/17] added logic to set nodes at fixed positions --- .../presentation/TreeBinaryTreeLayouter.java | 128 +++++++++++++++++- .../tree/presentation/TreeLayouterBase.java | 28 +++- .../TreeBinaryTreeLayouterTest.java | 43 +++++- .../presentation/TreeLayouterTestBase.java | 12 +- 4 files changed, 193 insertions(+), 18 deletions(-) diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java index 0116406..9a0c7d6 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java @@ -4,8 +4,10 @@ import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; import ch.hsr.adv.commons.tree.logic.ConstantsTree; import ch.hsr.adv.ui.core.logic.Layouter; +import ch.hsr.adv.ui.core.presentation.widgets.AutoScalePane; import ch.hsr.adv.ui.tree.domain.BinaryWalkerNode; import com.google.inject.Singleton; +import javafx.scene.layout.Background; import javafx.scene.layout.Pane; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -33,23 +35,139 @@ public Pane layout(ModuleGroup moduleGroup, List flags) { && flags.contains(ConstantsTree.SHOW_ARRAY_INDICES); initializeLayouting(moduleGroup); - insertDummyNodes(); + + addDummyNodesToSingleChildParents(); + fillTreeWithDummyNodes(moduleGroup.getMetaData()); + positionNodes(); + + Pane invisiblePane = createInvisiblePane(showIndex); + removeDummyNodes(); - return generatePane(showIndex); + + AutoScalePane visualizationPane = generatePane(showIndex); + visualizationPane.addChildren(invisiblePane); + + return visualizationPane; + } + + /** + * fills max tree with dummy nodes so that fixed node-position is + * possible + * + * @param metaData metaData that contains tree-layout-information + */ + private void fillTreeWithDummyNodes(Map metaData) { + fillLeftSideWithDummyNodes(metaData); + fillRightSideWithDummyNodes(metaData); } - private void insertDummyNodes() { + private void fillLeftSideWithDummyNodes(Map metaData) { + String leftMaxHeightValue = + metaData.get(ConstantsTree.MAX_TREE_HEIGHT_LEFT); + if (leftMaxHeightValue != null) { + int leftMaxHeight = Integer.parseInt(leftMaxHeightValue); + BinaryWalkerNode root = getDefaultRoot(); + fillWithDummyNodes(root.getLeftChild(), leftMaxHeight - 1); + } + } + + private void fillRightSideWithDummyNodes(Map metaData) { + String rightMaxHeightValue = + metaData.get(ConstantsTree.MAX_TREE_HEIGHT_RIGHT); + if (rightMaxHeightValue != null) { + int rightMaxHeight = Integer.parseInt(rightMaxHeightValue); + BinaryWalkerNode root = getDefaultRoot(); + fillWithDummyNodes(root.getRightChild(), rightMaxHeight - 1); + } + } + + private void fillWithDummyNodes(BinaryWalkerNode node, int height) { + if (height > 0) { + if (node.getLeftChild() == null) { + addLeftDummyNodeToParent(node); + } + if (node.getRightChild() == null) { + addRightDummyNodeToParent(node); + } + fillWithDummyNodes(node.getLeftChild(), height - 1); + fillWithDummyNodes(node.getRightChild(), height - 1); + } + } + + /** + * inserts dummy-children to nodes with one child + * this positions left children to the left side of the parent + * and right children to the right side of the parent + */ + private void addDummyNodesToSingleChildParents() { for (BinaryWalkerNode node : getNodes().values()) { if (node.getLeftChild() == null && node.getRightChild() != null) { - node.setLeftChild(new BinaryWalkerNode(true)); + addLeftDummyNodeToParent(node); } if (node.getLeftChild() != null && node.getRightChild() == null) { - node.setRightChild(new BinaryWalkerNode(true)); + addRightDummyNodeToParent(node); } } } + private void addLeftDummyNodeToParent(BinaryWalkerNode parent) { + BinaryWalkerNode dummyChild = new BinaryWalkerNode(true); + parent.setLeftChild(dummyChild); + dummyChild.setParent(parent); + } + + private void addRightDummyNodeToParent(BinaryWalkerNode parent) { + BinaryWalkerNode dummyChild = new BinaryWalkerNode(true); + parent.setRightChild(dummyChild); + dummyChild.setParent(parent); + } + + private double[] getRightmostPosition(BinaryWalkerNode node) { + if (node.getRightChild() != null) { + return getRightmostPosition(node.getRightChild()); + } + return new double[] {node.getCenterX(), node.getCenterY()}; + } + + private double[] getLeftmostPosition(BinaryWalkerNode node) { + if (node.getLeftChild() != null) { + return getLeftmostPosition(node.getLeftChild()); + } + return new double[] {node.getCenterX(), node.getCenterY()}; + } + + /** + * creates invisible Pane to prevent AutoScalePane from that fits the + * boundaries of the tree + * + * @param showIndex true if node indices are visible + * @return invisible Pane + */ + private Pane createInvisiblePane(boolean showIndex) { + double[] leftPosition = getLeftmostPosition(getDefaultRoot()); + double[] rightPosition = getRightmostPosition(getDefaultRoot()); + double horizontalDistance = getHorizontalVertexDistance(showIndex); + double verticalDistance = getVerticalVertexDistance(); + double left = (leftPosition[0] - 0.5) * horizontalDistance; + double right = (rightPosition[0] + 0.5) * horizontalDistance; + double top = -0.5 * verticalDistance; + double bottom = (Math.max(leftPosition[1], rightPosition[1]) + 0.5) + * verticalDistance; + double width = right - left; + double height = bottom - top; + + Pane invisiblePane = new Pane(); + invisiblePane.setPrefWidth(width); + invisiblePane.setPrefHeight(height); + invisiblePane.setLayoutX(left); + invisiblePane.setLayoutY(top); + invisiblePane.setVisible(true); + invisiblePane.setBackground(Background.EMPTY); + + return invisiblePane; + } + private void removeDummyNodes() { for (BinaryWalkerNode node : getNodes().values()) { if (node.getLeftChild() != null diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java index ad94efc..aa4d28d 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java @@ -9,11 +9,7 @@ import ch.hsr.adv.commons.tree.logic.domain.TreeNodeElement; import ch.hsr.adv.commons.tree.logic.domain.TreeNodeRelation; import ch.hsr.adv.ui.core.logic.Layouter; -import ch.hsr.adv.ui.core.presentation.widgets.AutoScalePane; -import ch.hsr.adv.ui.core.presentation.widgets.ConnectorType; -import ch.hsr.adv.ui.core.presentation.widgets.IndexPosition; -import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; -import ch.hsr.adv.ui.core.presentation.widgets.LabeledEdge; +import ch.hsr.adv.ui.core.presentation.widgets.*; import ch.hsr.adv.ui.tree.domain.WalkerNode; import ch.hsr.adv.ui.tree.logic.WalkerTreeAlgorithm; @@ -70,7 +66,7 @@ void initializeLayouting(ModuleGroup moduleGroup) { */ void positionNodes() { WalkerTreeAlgorithm algorithm = new WalkerTreeAlgorithm( - nodes.get(DEFAULT_ROOT_ID)); + getDefaultRoot()); algorithm.positionNodes(); } @@ -89,6 +85,26 @@ void positionNodes(List roots) { positionTrees(trees); } + T getDefaultRoot() { + return nodes.get(DEFAULT_ROOT_ID); + } + + /** + * @param showIndex true if node indices are visible + * @return distance between two vertices in a tree + */ + static double getHorizontalVertexDistance(boolean showIndex) { + double distance = VERTEX_DISTANCE_HORIZONTAL; + if (showIndex) { + distance += INDEX_WIDTH; + } + return distance; + } + + static double getVerticalVertexDistance() { + return VERTEX_DISTANCE_VERTICAL; + } + private void positionTrees(List trees) { if (trees.size() <= 0) { return; diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java index 91bad4f..3055c9e 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java @@ -1,9 +1,11 @@ package ch.hsr.adv.ui.tree.presentation; import ch.hsr.adv.ui.core.access.FileDatastoreAccess; +import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import ch.hsr.adv.ui.tree.domain.BinaryWalkerNode; import ch.hsr.adv.ui.tree.logic.binarytree.TreeBinaryTreeParser; import com.google.inject.Inject; +import javafx.scene.layout.Pane; import org.jukito.JukitoRunner; import org.junit.Before; import org.junit.Test; @@ -12,12 +14,14 @@ import java.io.IOException; import java.util.concurrent.TimeoutException; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.Assert.*; @RunWith(JukitoRunner.class) public class TreeBinaryTreeLayouterTest { + private static final double DOUBLE_ACCURACY + = TreeLayouterTestBase.DOUBLE_ACCURACY; + private TreeLayouterTestBase base; @Inject @@ -67,10 +71,43 @@ public void layoutTreePaneContainsAllRelationsTest() { } @Test - public void layoutTreePositionsVerticesCorrectTest() { + public void layoutTreeWithoutFixationPositionsVerticesCorrectTest() { + base.getModuleGroup().getMetaData().clear(); + final long nodeIndex = 6L; final double expectedX = 0.5; final double expectedY = 2.0; base.assertNodePositionedCorrect(nodeIndex, expectedX, expectedY); } + + @Test + public void layoutTreeWithFixationPositionsVerticesCorrectTest() { + final long nodeIndex = 5L; + final double expectedX = -0.25; + final double expectedY = 2.0; + + base.assertNodePositionedCorrect(nodeIndex, expectedX, expectedY); + } + + @Test + public void layoutTreePositionsInvisiblePaneCorrectTest() { + Pane pane = base.getChildren(base.layoutTree(), + e -> (e instanceof Pane && !(e instanceof IndexedNode))) + .stream().map(n -> (Pane) n).findFirst().orElse(null); + + final double verticalDistance = TreeLayouterBase + .getVerticalVertexDistance(); + final double horizontalDistance = TreeLayouterBase + .getHorizontalVertexDistance(true); + final double expectedX = -3.25 * horizontalDistance; + final double expectedY = -0.5 * verticalDistance; + final double expectedWidth = 5.5 * horizontalDistance; + final double expectedHeight = 4 * verticalDistance; + + assertNotNull(pane); + assertEquals(expectedX, pane.getLayoutX(), DOUBLE_ACCURACY); + assertEquals(expectedY, pane.getLayoutY(), DOUBLE_ACCURACY); + assertEquals(expectedWidth, pane.getPrefWidth(), DOUBLE_ACCURACY); + assertEquals(expectedHeight, pane.getPrefHeight(), DOUBLE_ACCURACY); + } } diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java index 7d6ca5e..f691195 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java @@ -2,10 +2,10 @@ import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; import ch.hsr.adv.ui.core.access.FileDatastoreAccess; +import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import ch.hsr.adv.ui.core.presentation.widgets.LabeledEdge; import ch.hsr.adv.ui.tree.domain.WalkerNode; import ch.hsr.adv.ui.tree.logic.TreeParser; -import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import com.google.gson.Gson; import com.google.gson.JsonElement; import javafx.scene.Group; @@ -28,7 +28,7 @@ class TreeLayouterTestBase { - private static final double DOUBLE_ACCURACY = 0.00001; + static final double DOUBLE_ACCURACY = 0.00001; private ModuleGroup moduleGroup; private TreeLayouterBase sut; @@ -53,19 +53,23 @@ class TreeLayouterTestBase { } Pane layoutTree() { - return sut.layout(moduleGroup, null); + return sut.layout(moduleGroup, moduleGroup.getFlags()); } Map getNodes() { return sut.getNodes(); } - private List getChildren(Pane pane, Predicate filter) { + List getChildren(Pane pane, Predicate filter) { Group group = (Group) pane.getChildren().get(0); return group.getChildren().stream().filter(filter) .collect(Collectors.toList()); } + ModuleGroup getModuleGroup() { + return moduleGroup; + } + void assertTreeContainsNode(Long nodeId) { layoutTree(); Map actual = getNodes(); From 165a98360ed81678c877ecd8a30d60cbe3a668a9 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Fri, 23 Nov 2018 16:00:08 +0100 Subject: [PATCH 08/17] added style-class for index-label in IndexedNode --- .../ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java | 1 + ui-core/src/main/resources/css/session-view.css | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java index 2d2be7d..222d071 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java @@ -33,6 +33,7 @@ public IndexedNode(long index, String labelText, ADVStyle style, indexLabel.setText(String.valueOf(index)); indexLabel.setVisible(showIndex); indexLabel.setPadding(calculateInsets(indexPosition)); + indexLabel.getStyleClass().add("node-index"); getChildren().add(createRootPane(indexPosition, showIndex)); } diff --git a/ui-core/src/main/resources/css/session-view.css b/ui-core/src/main/resources/css/session-view.css index 7cd8cda..4e2ebd9 100644 --- a/ui-core/src/main/resources/css/session-view.css +++ b/ui-core/src/main/resources/css/session-view.css @@ -9,4 +9,9 @@ .text-area { -fx-focus-color: -accent; +} + +.node-index { + -fx-font-size: 0.8em; + -fx-font-weight: bold; } \ No newline at end of file From 91eb3760bd8763e15e8a9826a173c4302b131e89 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Sat, 24 Nov 2018 14:55:51 +0100 Subject: [PATCH 09/17] updated tree-module to allow trees without root --- .../presentation/TreeBinaryTreeLayouter.java | 10 ++++++++-- .../ui/tree/presentation/TreeLayouterBase.java | 16 +++++++--------- .../presentation/TreeBinaryTreeLayouterTest.java | 5 +++++ .../TreeCollectionTreeLayouterTest.java | 5 +++++ .../TreeGeneralTreeLayouterTest.java | 5 +++++ .../tree/presentation/TreeLayouterTestBase.java | 10 ++++++++++ 6 files changed, 40 insertions(+), 11 deletions(-) diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java index 9a0c7d6..b5a0876 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java @@ -145,8 +145,14 @@ private double[] getLeftmostPosition(BinaryWalkerNode node) { * @return invisible Pane */ private Pane createInvisiblePane(boolean showIndex) { - double[] leftPosition = getLeftmostPosition(getDefaultRoot()); - double[] rightPosition = getRightmostPosition(getDefaultRoot()); + double[] leftPosition = new double[2]; + double[] rightPosition = new double[2]; + + if (getDefaultRoot() != null) { + leftPosition = getLeftmostPosition(getDefaultRoot()); + rightPosition = getRightmostPosition(getDefaultRoot()); + } + double horizontalDistance = getHorizontalVertexDistance(showIndex); double verticalDistance = getVerticalVertexDistance(); double left = (leftPosition[0] - 0.5) * horizontalDistance; diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java index aa4d28d..fb397a5 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterBase.java @@ -65,9 +65,12 @@ void initializeLayouting(ModuleGroup moduleGroup) { * Positions the tree-vertices using the WalkerTreeAlgorithm */ void positionNodes() { - WalkerTreeAlgorithm algorithm = new WalkerTreeAlgorithm( - getDefaultRoot()); - algorithm.positionNodes(); + T root = getDefaultRoot(); + if (root != null) { + WalkerTreeAlgorithm algorithm = + new WalkerTreeAlgorithm(getDefaultRoot()); + algorithm.positionNodes(); + } } /** @@ -183,12 +186,7 @@ private void addVerticesToPane(AutoScalePane pane, IndexedNode indexedNode = indexedNodes.get(entry.getKey()); WalkerNode node = entry.getValue(); - double horizontalDistance = VERTEX_DISTANCE_HORIZONTAL; - - if (showIndex) { - horizontalDistance += INDEX_WIDTH; - } - + double horizontalDistance = getHorizontalVertexDistance(showIndex); int x = (int) (node.getCenterX() * horizontalDistance); int y = (int) (node.getCenterY() * VERTEX_DISTANCE_VERTICAL); diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java index 3055c9e..a15b9e9 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java @@ -110,4 +110,9 @@ public void layoutTreePositionsInvisiblePaneCorrectTest() { assertEquals(expectedWidth, pane.getPrefWidth(), DOUBLE_ACCURACY); assertEquals(expectedHeight, pane.getPrefHeight(), DOUBLE_ACCURACY); } + + @Test + public void layoutTreeWithoutRootHasNoElementsTest() { + base.assertTreeWithoutRootHasNoElements(); + } } diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java index 2c4ace2..9cfa569 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java @@ -76,4 +76,9 @@ public void layoutTreePositionsVerticesCorrectTest() { final double expectedY = 1.0; base.assertNodePositionedCorrect(nodeIndex, expectedX, expectedY); } + + @Test + public void layoutTreeWithoutRootHasNoElementsTest() { + base.assertTreeWithoutRootHasNoElements(); + } } diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeGeneralTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeGeneralTreeLayouterTest.java index 5932e60..9b3891b 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeGeneralTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeGeneralTreeLayouterTest.java @@ -70,4 +70,9 @@ public void layoutTreePositionsVerticesCorrectTest() { final double expectedY = 2.0; base.assertNodePositionedCorrect(nodeIndex, expectedX, expectedY); } + + @Test + public void layoutTreeWithoutRootHasNoElementsTest() { + base.assertTreeWithoutRootHasNoElements(); + } } diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java index f691195..c1c0c36 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeLayouterTestBase.java @@ -102,4 +102,14 @@ void assertNodePositionedCorrect(long nodeIndex, double expectedX, assertEquals(expectedX, actual.getCenterX(), DOUBLE_ACCURACY); assertEquals(expectedY, actual.getCenterY(), DOUBLE_ACCURACY); } + + void assertTreeWithoutRootHasNoElements() { + ModuleGroup emptyModule = new ModuleGroup("TestModule"); + Pane pane = sut.layout(emptyModule, emptyModule.getFlags()); + + final int expectedNodes = 0; + final int nodes = + getChildren(pane, e -> e instanceof IndexedNode).size(); + assertEquals(expectedNodes, nodes); + } } From e0367046328926eeac072520d4a724807f80de94 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 26 Nov 2018 15:55:34 +0100 Subject: [PATCH 10/17] refactored fillTree-methods in TreeBinaryTreeLayouter --- .../presentation/TreeBinaryTreeLayouter.java | 65 +++++++++---------- .../TreeBinaryTreeLayouterTest.java | 16 +++++ 2 files changed, 46 insertions(+), 35 deletions(-) diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java index b5a0876..e53a7c6 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java @@ -58,31 +58,26 @@ public Pane layout(ModuleGroup moduleGroup, List flags) { * @param metaData metaData that contains tree-layout-information */ private void fillTreeWithDummyNodes(Map metaData) { - fillLeftSideWithDummyNodes(metaData); - fillRightSideWithDummyNodes(metaData); - } - - private void fillLeftSideWithDummyNodes(Map metaData) { - String leftMaxHeightValue = - metaData.get(ConstantsTree.MAX_TREE_HEIGHT_LEFT); - if (leftMaxHeightValue != null) { - int leftMaxHeight = Integer.parseInt(leftMaxHeightValue); - BinaryWalkerNode root = getDefaultRoot(); - fillWithDummyNodes(root.getLeftChild(), leftMaxHeight - 1); + BinaryWalkerNode root = getDefaultRoot(); + if (root != null) { + fillBranchWithDummyNodes( + metaData.get(ConstantsTree.MAX_TREE_HEIGHT_LEFT), + root.getLeftChild()); + fillBranchWithDummyNodes( + metaData.get(ConstantsTree.MAX_TREE_HEIGHT_RIGHT), + root.getRightChild()); } } - private void fillRightSideWithDummyNodes(Map metaData) { - String rightMaxHeightValue = - metaData.get(ConstantsTree.MAX_TREE_HEIGHT_RIGHT); - if (rightMaxHeightValue != null) { - int rightMaxHeight = Integer.parseInt(rightMaxHeightValue); - BinaryWalkerNode root = getDefaultRoot(); - fillWithDummyNodes(root.getRightChild(), rightMaxHeight - 1); + private void fillBranchWithDummyNodes(String maxHeightValue, + BinaryWalkerNode branchRoot) { + if (maxHeightValue != null) { + final int maxHeight = Integer.parseInt(maxHeightValue); + fillBranchWithDummyNodes(branchRoot, maxHeight - 1); } } - private void fillWithDummyNodes(BinaryWalkerNode node, int height) { + private void fillBranchWithDummyNodes(BinaryWalkerNode node, int height) { if (height > 0) { if (node.getLeftChild() == null) { addLeftDummyNodeToParent(node); @@ -90,8 +85,8 @@ private void fillWithDummyNodes(BinaryWalkerNode node, int height) { if (node.getRightChild() == null) { addRightDummyNodeToParent(node); } - fillWithDummyNodes(node.getLeftChild(), height - 1); - fillWithDummyNodes(node.getRightChild(), height - 1); + fillBranchWithDummyNodes(node.getLeftChild(), height - 1); + fillBranchWithDummyNodes(node.getRightChild(), height - 1); } } @@ -123,20 +118,6 @@ private void addRightDummyNodeToParent(BinaryWalkerNode parent) { dummyChild.setParent(parent); } - private double[] getRightmostPosition(BinaryWalkerNode node) { - if (node.getRightChild() != null) { - return getRightmostPosition(node.getRightChild()); - } - return new double[] {node.getCenterX(), node.getCenterY()}; - } - - private double[] getLeftmostPosition(BinaryWalkerNode node) { - if (node.getLeftChild() != null) { - return getLeftmostPosition(node.getLeftChild()); - } - return new double[] {node.getCenterX(), node.getCenterY()}; - } - /** * creates invisible Pane to prevent AutoScalePane from that fits the * boundaries of the tree @@ -174,6 +155,20 @@ private Pane createInvisiblePane(boolean showIndex) { return invisiblePane; } + private double[] getRightmostPosition(BinaryWalkerNode node) { + if (node.getRightChild() != null) { + return getRightmostPosition(node.getRightChild()); + } + return new double[] {node.getCenterX(), node.getCenterY()}; + } + + private double[] getLeftmostPosition(BinaryWalkerNode node) { + if (node.getLeftChild() != null) { + return getLeftmostPosition(node.getLeftChild()); + } + return new double[] {node.getCenterX(), node.getCenterY()}; + } + private void removeDummyNodes() { for (BinaryWalkerNode node : getNodes().values()) { if (node.getLeftChild() != null diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java index a15b9e9..deb8fb3 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java @@ -1,5 +1,7 @@ package ch.hsr.adv.ui.tree.presentation; +import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; +import ch.hsr.adv.commons.tree.logic.ConstantsTree; import ch.hsr.adv.ui.core.access.FileDatastoreAccess; import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; import ch.hsr.adv.ui.tree.domain.BinaryWalkerNode; @@ -115,4 +117,18 @@ public void layoutTreePositionsInvisiblePaneCorrectTest() { public void layoutTreeWithoutRootHasNoElementsTest() { base.assertTreeWithoutRootHasNoElements(); } + + @Test + public void layoutTreeWithoutRootAndWithFixationHasNoElementsTest() { + ModuleGroup emptyModule = new ModuleGroup("TestModule"); + emptyModule.getMetaData().put(ConstantsTree.MAX_TREE_HEIGHT_LEFT, "1"); + emptyModule.getMetaData().put(ConstantsTree.MAX_TREE_HEIGHT_RIGHT, "2"); + + Pane pane = sut.layout(emptyModule, emptyModule.getFlags()); + + final int expectedNodes = 0; + final int nodes = + base.getChildren(pane, e -> e instanceof IndexedNode).size(); + assertEquals(expectedNodes, nodes); + } } From 7a603596a2413168c6c19657513a4339b55805b0 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 26 Nov 2018 16:07:01 +0100 Subject: [PATCH 11/17] refactored setters for position in IndexedNode --- .../core/presentation/widgets/IndexedNode.java | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java index 222d071..1a83dbc 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java @@ -38,24 +38,12 @@ public IndexedNode(long index, String labelText, ADVStyle style, getChildren().add(createRootPane(indexPosition, showIndex)); } - /** - * Sets the X property of the center of the labeled node - * - * @param x x coordinate - */ public void setCenterX(int x) { preferredX = x; - layoutXProperty().set(preferredX - labeledNode.getWidth() / 2); } - /** - * Sets the y property of the center of the labeled node - * - * @param y y coordinate - */ public void setCenterY(int y) { preferredY = y; - layoutYProperty().set(preferredY - labeledNode.getHeight() / 2); } public LabeledNode getLabeledNode() { @@ -108,8 +96,8 @@ private Insets calculateInsets(IndexPosition position) { */ @Override protected void layoutChildren() { - setCenterX(preferredX); - setCenterY(preferredY); + layoutXProperty().set(preferredX - labeledNode.getWidth() / 2); + layoutYProperty().set(preferredY - labeledNode.getHeight() / 2); super.layoutChildren(); } } \ No newline at end of file From 1544b810ca62a08a0f802c6ff75e47ed3db7aea8 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Fri, 30 Nov 2018 15:51:19 +0100 Subject: [PATCH 12/17] fixed bug that caused NullPointerException in tree with fixed positions and only root --- .../presentation/TreeBinaryTreeLayouter.java | 23 +++++++++++++++---- .../TreeBinaryTreeLayouterTest.java | 18 +++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java index e53a7c6..60f062d 100644 --- a/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java +++ b/module-tree/src/main/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouter.java @@ -15,6 +15,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.function.Supplier; /** * Creates JavaFX Nodes for the tree elements and adds them to a pane @@ -62,18 +63,30 @@ private void fillTreeWithDummyNodes(Map metaData) { if (root != null) { fillBranchWithDummyNodes( metaData.get(ConstantsTree.MAX_TREE_HEIGHT_LEFT), - root.getLeftChild()); + root.getLeftChild(), () -> { + addLeftDummyNodeToParent(root); + return root.getLeftChild(); + }); fillBranchWithDummyNodes( metaData.get(ConstantsTree.MAX_TREE_HEIGHT_RIGHT), - root.getRightChild()); + root.getRightChild(), () -> { + addRightDummyNodeToParent(root); + return root.getRightChild(); + }); } } - private void fillBranchWithDummyNodes(String maxHeightValue, - BinaryWalkerNode branchRoot) { + private void fillBranchWithDummyNodes( + String maxHeightValue, BinaryWalkerNode branchRoot, + Supplier createDummyBranchRoot) { if (maxHeightValue != null) { final int maxHeight = Integer.parseInt(maxHeightValue); - fillBranchWithDummyNodes(branchRoot, maxHeight - 1); + if (maxHeight > 0) { + if (branchRoot == null) { + branchRoot = createDummyBranchRoot.get(); + } + fillBranchWithDummyNodes(branchRoot, maxHeight - 1); + } } } diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java index deb8fb3..6c933b7 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeBinaryTreeLayouterTest.java @@ -2,8 +2,10 @@ import ch.hsr.adv.commons.core.logic.domain.ModuleGroup; import ch.hsr.adv.commons.tree.logic.ConstantsTree; +import ch.hsr.adv.commons.tree.logic.domain.TreeNodeElement; import ch.hsr.adv.ui.core.access.FileDatastoreAccess; import ch.hsr.adv.ui.core.presentation.widgets.IndexedNode; +import ch.hsr.adv.ui.tree.domain.BinaryTreeTestNode; import ch.hsr.adv.ui.tree.domain.BinaryWalkerNode; import ch.hsr.adv.ui.tree.logic.binarytree.TreeBinaryTreeParser; import com.google.inject.Inject; @@ -131,4 +133,20 @@ public void layoutTreeWithoutRootAndWithFixationHasNoElementsTest() { base.getChildren(pane, e -> e instanceof IndexedNode).size(); assertEquals(expectedNodes, nodes); } + + @Test + public void layoutTreeWithOnlyRootAndFixationPositionsRootCorrectTest() { + BinaryTreeTestNode root = new BinaryTreeTestNode<>("Hi"); + ModuleGroup emptyModule = new ModuleGroup("TestModule"); + emptyModule.addElement(new TreeNodeElement(root, 1)); + emptyModule.getMetaData().put(ConstantsTree.MAX_TREE_HEIGHT_LEFT, "0"); + emptyModule.getMetaData().put(ConstantsTree.MAX_TREE_HEIGHT_RIGHT, "1"); + + Pane pane = sut.layout(emptyModule, emptyModule.getFlags()); + + final int expectedNodes = 1; + final int nodes = + base.getChildren(pane, e -> e instanceof IndexedNode).size(); + assertEquals(expectedNodes, nodes); + } } From b660b07809d4cb9ba26665178718032319743200 Mon Sep 17 00:00:00 2001 From: Jan Winter Date: Mon, 3 Dec 2018 09:35:11 +0100 Subject: [PATCH 13/17] added brackets to visualisation --- .../ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java index 1a83dbc..511f862 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/presentation/widgets/IndexedNode.java @@ -30,7 +30,7 @@ public IndexedNode(long index, String labelText, ADVStyle style, labeledNode.setY(0); indexLabel = new Label(); - indexLabel.setText(String.valueOf(index)); + indexLabel.setText("[" + index + "]"); indexLabel.setVisible(showIndex); indexLabel.setPadding(calculateInsets(indexPosition)); indexLabel.getStyleClass().add("node-index"); From 4155407f102bb5fff856045d39926acac81e91ab Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 3 Dec 2018 11:34:10 +0100 Subject: [PATCH 14/17] added logic for positioning modules with set ModulePosition --- .../hsr/adv/ui/core/logic/CoreLayouter.java | 123 +++++++++++++++--- .../ch/hsr/adv/ui/core/logic/FlowControl.java | 7 +- .../adv/ui/core/logic/CoreLayouterTest.java | 116 +++++++++++++++-- 3 files changed, 217 insertions(+), 29 deletions(-) diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java index b75443b..9e39015 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java @@ -1,5 +1,6 @@ package ch.hsr.adv.ui.core.logic; +import ch.hsr.adv.commons.core.logic.domain.ModulePosition; import com.google.inject.Singleton; import javafx.geometry.Orientation; import javafx.scene.control.SplitPane; @@ -10,6 +11,7 @@ import java.util.LinkedList; import java.util.List; +import java.util.Map; import java.util.Queue; /** @@ -29,44 +31,129 @@ public class CoreLayouter { * snapshots in a session are bound together so that the user can * rearrange them for a session. * - * @param dividers empty list to store split pane dividers - * @param panes child panes of the module-specific layouter + * @param panes child panes of the module-specific layouter + * @param positions desired positions of the panes + * @param dividers empty list to store split pane dividers * @return split pane */ public Region layout(List panes, + Map positions, List dividers) { logger.info("Creating grid layout for all active modules..."); + + checkParameters(panes, positions, dividers); + + Queue positionedPanes = new LinkedList<>(); + Queue defaultPanes = new LinkedList<>(); + + Pane mainPane = panes.get(0); + defaultPanes.add(mainPane); + + for (int i = 1; i < panes.size(); i++) { + Pane currentPane = panes.get(i); + if (positions.get(currentPane) == ModulePosition.DEFAULT) { + defaultPanes.add(currentPane); + } else { + positionedPanes.add(currentPane); + } + } + + return positionPanes(positions, dividers, positionedPanes, + defaultPanes); + } + + private void checkParameters(List panes, + Map positions, + List dividers) { + if (panes.size() <= 0) { + String message = "panes must contain at least one element"; + logger.error(message); + throw new IllegalArgumentException(message); + } else if (panes.size() != positions.size()) { + String message = "panes and positions must have equal size"; + logger.error(message); + throw new IllegalArgumentException(message); + } + if (!dividers.isEmpty()) { logger.info("Expecting an empty list of dividers. Correcting..."); dividers.clear(); } - Queue remainingPanes = new LinkedList<>(panes); - SplitPane parentPane = new SplitPane(); - parentPane.setOrientation(Orientation.VERTICAL); + } - // calculate dimensions of the grid - int columns = 1; - int rows = 1; - while (columns * rows < remainingPanes.size()) { - columns++; - if (columns * rows < remainingPanes.size()) { - rows++; - } + private Region positionPanes(Map positions, + List dividers, + Queue positionedPanes, + Queue defaultPanes) { + Region centerPane; + + if (defaultPanes.size() > 1) { + centerPane = generateCenterPane(defaultPanes, dividers); + } else { + centerPane = defaultPanes.poll(); + } + + while (!positionedPanes.isEmpty()) { + Pane nextPane = positionedPanes.poll(); + ModulePosition position = positions.get(nextPane); + centerPane = positionPane(dividers, centerPane, nextPane, position); + } + return centerPane; + } + + private Region positionPane(List dividers, + Region centerPane, Pane nextPane, + ModulePosition position) { + SplitPane newPane = new SplitPane(); + switch (position) { + case LEFT: + newPane.setOrientation(Orientation.HORIZONTAL); + newPane.getItems().addAll(nextPane, centerPane); + break; + case TOP: + newPane.setOrientation(Orientation.VERTICAL); + newPane.getItems().addAll(nextPane, centerPane); + break; + case RIGHT: + newPane.setOrientation(Orientation.HORIZONTAL); + newPane.getItems().addAll(centerPane, nextPane); + break; + case BOTTOM: + newPane.setOrientation(Orientation.VERTICAL); + newPane.getItems().addAll(centerPane, nextPane); + break; + default: + String message = "Unknown state \"" + position + "\""; + logger.error(message); + throw new IllegalArgumentException(message); } + dividers.addAll(newPane.getDividers()); + return newPane; + } + + private SplitPane generateCenterPane(Queue defaultPanes, + List dividers) { + SplitPane centerPane = new SplitPane(); + centerPane.setOrientation(Orientation.VERTICAL); + + // calculate dimensions of the grid + int columns = (int) Math.ceil(Math.sqrt(defaultPanes.size())); + int rows = (int) Math.ceil(defaultPanes.size() / (double) columns); // fill the grid SplitPane rowPane; for (int rowCount = 0; rowCount < rows; rowCount++) { - rowPane = addNewRow(parentPane); + rowPane = addNewRow(centerPane); for (int colCount = 0; colCount < columns; colCount++) { - if (!remainingPanes.isEmpty()) { - rowPane.getItems().add(remainingPanes.poll()); + if (!defaultPanes.isEmpty()) { + rowPane.getItems().add(defaultPanes.poll()); } } dividers.addAll(rowPane.getDividers()); } - dividers.addAll(parentPane.getDividers()); - return parentPane; + dividers.addAll(centerPane.getDividers()); + + return centerPane; } private SplitPane addNewRow(SplitPane parentPane) { diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/FlowControl.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/FlowControl.java index 6a6f9a7..f274dbd 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/FlowControl.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/FlowControl.java @@ -1,5 +1,6 @@ package ch.hsr.adv.ui.core.logic; +import ch.hsr.adv.commons.core.logic.domain.ModulePosition; import ch.hsr.adv.commons.core.logic.domain.Session; import ch.hsr.adv.commons.core.logic.domain.Snapshot; import ch.hsr.adv.ui.core.access.DatastoreAccess; @@ -21,7 +22,9 @@ import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.stream.Collectors; /** @@ -120,16 +123,18 @@ private boolean layoutSession(Session session) { // layout List panes = new ArrayList<>(); + Map positions = new HashMap<>(); snapshot.getModuleGroups().forEach(group -> { String moduleName = group.getModuleName(); Layouter layouter = serviceProvider.getLayouter(moduleName); Pane pane = layouter.layout(group, group.getFlags()); panes.add(pane); + positions.put(pane, group.getPosition()); }); // wrap in split pane List dividers = new ArrayList<>(); - Region parent = coreLayouter.layout(panes, dividers); + Region parent = coreLayouter.layout(panes, positions, dividers); LayoutedSnapshot layoutedSnapshot = new LayoutedSnapshot( snapshot.getSnapshotId(), parent, dividers); layoutedSnapshot diff --git a/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java b/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java index d0275a9..4da9424 100644 --- a/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java +++ b/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java @@ -1,5 +1,6 @@ package ch.hsr.adv.ui.core.logic; +import ch.hsr.adv.commons.core.logic.domain.ModulePosition; import com.google.inject.Inject; import javafx.scene.control.SplitPane; import javafx.scene.layout.Pane; @@ -11,16 +12,21 @@ import org.testfx.api.FxToolkit; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; -import static org.junit.Assert.*; @RunWith(JukitoRunner.class) public class CoreLayouterTest { -@Inject -private CoreLayouter sut; + @Inject + private CoreLayouter sut; -private List panes = new ArrayList<>(); -private List dividers =new ArrayList<>(); + private List panes = new ArrayList<>(); + private Map positions = new HashMap<>(); + private List dividers = new ArrayList<>(); @Before public void setUp() throws Exception { @@ -28,26 +34,116 @@ public void setUp() throws Exception { panes.add(new Pane()); panes.add(new Pane()); panes.add(new Pane()); + panes.add(new Pane()); + panes.add(new Pane()); + positions.put(panes.get(0), ModulePosition.DEFAULT); + positions.put(panes.get(1), ModulePosition.LEFT); + positions.put(panes.get(2), ModulePosition.BOTTOM); + positions.put(panes.get(3), ModulePosition.RIGHT); + positions.put(panes.get(4), ModulePosition.TOP); } @Test public void layoutTest() { // WHEN - Region actual = sut.layout(panes, dividers); + Region actual = sut.layout(panes, positions, dividers); // THEN - assertEquals(2, dividers.size()); + assertEquals(4, dividers.size()); assertTrue(actual instanceof SplitPane); } @Test - public void layoutNonEmptyListTest() { + public void layoutNonEmptyDividerListTest() { // WHEN dividers.add(new SplitPane.Divider()); - Region actual = sut.layout(panes, dividers); + Region actual = sut.layout(panes, positions, dividers); // THEN - assertEquals(2, dividers.size()); + assertEquals(4, dividers.size()); assertTrue(actual instanceof SplitPane); } + + @Test + public void layoutCreatesCorrectPanesTest() { + Region actual = sut.layout(panes, positions, dividers); + + SplitPane outerPane = (SplitPane) actual; + SplitPane innerPane1 = (SplitPane) outerPane.getItems().get(1); + SplitPane innerPane2 = (SplitPane) innerPane1.getItems().get(0); + SplitPane innerPane3 = (SplitPane) innerPane2.getItems().get(0); + + assertEquals(panes.get(4), outerPane.getItems().get(0)); + assertEquals(panes.get(3), innerPane1.getItems().get(1)); + assertEquals(panes.get(2), innerPane2.getItems().get(1)); + assertEquals(panes.get(1), innerPane3.getItems().get(0)); + assertEquals(panes.get(0), innerPane3.getItems().get(1)); + } + + @Test + public void layoutWithMultipleDefaultPanesCreatesCorrectPanesTest() { + positions.put(panes.get(1), ModulePosition.DEFAULT); + Region actual = sut.layout(panes, positions, dividers); + + SplitPane outerPane = (SplitPane) actual; + SplitPane innerPane1 = (SplitPane) outerPane.getItems().get(1); + SplitPane innerPane2 = (SplitPane) innerPane1.getItems().get(0); + SplitPane centerPane = (SplitPane) innerPane2.getItems().get(0); + SplitPane rowPane = (SplitPane) centerPane.getItems().get(0); + + assertEquals(panes.get(0), rowPane.getItems().get(0)); + assertEquals(panes.get(1), rowPane.getItems().get(1)); + } + + @Test + public void layoutWithoutDefaultPanesCreatesCorrectPanesTest() { + positions.put(panes.get(0), ModulePosition.TOP); + Region actual = sut.layout(panes, positions, dividers); + + SplitPane outerPane = (SplitPane) actual; + SplitPane innerPane1 = (SplitPane) outerPane.getItems().get(1); + SplitPane innerPane2 = (SplitPane) innerPane1.getItems().get(0); + SplitPane innerPane3 = (SplitPane) innerPane2.getItems().get(0); + + assertEquals(panes.get(4), outerPane.getItems().get(0)); + assertEquals(panes.get(3), innerPane1.getItems().get(1)); + assertEquals(panes.get(2), innerPane2.getItems().get(1)); + assertEquals(panes.get(1), innerPane3.getItems().get(0)); + assertEquals(panes.get(0), innerPane3.getItems().get(1)); + } + + @Test + public void layoutWithAllDefaultPanesCreatesCorrectPanesTest() { + positions.put(panes.get(1), ModulePosition.DEFAULT); + positions.put(panes.get(2), ModulePosition.DEFAULT); + positions.put(panes.get(3), ModulePosition.DEFAULT); + positions.put(panes.get(4), ModulePosition.DEFAULT); + Region actual = sut.layout(panes, positions, dividers); + + SplitPane centerPane = (SplitPane) actual; + SplitPane rowPane1 = (SplitPane) centerPane.getItems().get(0); + SplitPane rowPane2 = (SplitPane) centerPane.getItems().get(1); + + assertEquals(2, centerPane.getItems().size()); + assertEquals(3, rowPane1.getItems().size()); + assertEquals(2, rowPane2.getItems().size()); + assertEquals(panes.get(0), rowPane1.getItems().get(0)); + assertEquals(panes.get(1), rowPane1.getItems().get(1)); + assertEquals(panes.get(2), rowPane1.getItems().get(2)); + assertEquals(panes.get(3), rowPane2.getItems().get(0)); + assertEquals(panes.get(4), rowPane2.getItems().get(1)); + } + + @Test(expected = IllegalArgumentException.class) + public void layoutEmptyPanesTest() { + panes.clear(); + positions.clear(); + sut.layout(panes, positions, dividers); + } + + @Test(expected = IllegalArgumentException.class) + public void layoutNotEqualPositionSizeTest() { + positions.clear(); + sut.layout(panes, positions, dividers); + } } \ No newline at end of file From 221f0f90ba0cb2a07f080447e9b588577adffdf3 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 3 Dec 2018 13:54:05 +0100 Subject: [PATCH 15/17] removed check for equal size of positions and panes in CoreLayouter --- .../main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java | 4 ---- .../java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java | 6 ------ 2 files changed, 10 deletions(-) diff --git a/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java b/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java index 9e39015..b7ba291 100644 --- a/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java +++ b/ui-core/src/main/java/ch/hsr/adv/ui/core/logic/CoreLayouter.java @@ -69,10 +69,6 @@ private void checkParameters(List panes, String message = "panes must contain at least one element"; logger.error(message); throw new IllegalArgumentException(message); - } else if (panes.size() != positions.size()) { - String message = "panes and positions must have equal size"; - logger.error(message); - throw new IllegalArgumentException(message); } if (!dividers.isEmpty()) { diff --git a/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java b/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java index 4da9424..1153d87 100644 --- a/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java +++ b/ui-core/src/test/java/ch/hsr/adv/ui/core/logic/CoreLayouterTest.java @@ -140,10 +140,4 @@ public void layoutEmptyPanesTest() { positions.clear(); sut.layout(panes, positions, dividers); } - - @Test(expected = IllegalArgumentException.class) - public void layoutNotEqualPositionSizeTest() { - positions.clear(); - sut.layout(panes, positions, dividers); - } } \ No newline at end of file From 2e4c5c698ea6ee01e2e4474aa8c4dc612daac332 Mon Sep 17 00:00:00 2001 From: Fabian Meier Date: Mon, 3 Dec 2018 13:55:55 +0100 Subject: [PATCH 16/17] renamed test in TreeCollectionTreeLayouterTest --- .../ui/tree/presentation/TreeCollectionTreeLayouterTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java index 9cfa569..ea54954 100644 --- a/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java +++ b/module-tree/src/test/java/ch/hsr/adv/ui/tree/presentation/TreeCollectionTreeLayouterTest.java @@ -43,7 +43,7 @@ public void layoutTreeContainsAllRootsTest() { } @Test - public void layoutTreeRootAHasNoChildren() { + public void layoutTreeRootAHasNoChildrenTest() { final long rootAIndex = 1L; base.layoutTree(); From 0da168a04b043c0255470572c1d8eaf51cbfc00e Mon Sep 17 00:00:00 2001 From: Jan Winter Date: Fri, 7 Dec 2018 08:54:07 +0100 Subject: [PATCH 17/17] added release version 1.2 --- bintray.json | 6 +++--- build.gradle | 2 +- ui-core/build.gradle | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/bintray.json b/bintray.json index 6a6f9d1..aa2e687 100644 --- a/bintray.json +++ b/bintray.json @@ -9,14 +9,14 @@ ] }, "version": { - "name": "1.1.1", - "released": "2018-11-19", + "name": "1.2", + "released": "2018-12-07", "gpgSign": false }, "files": [ { "includePattern": "build/libs/(.*)", - "uploadPattern": "/ch/hsr/adv/adv-ui/1.1.1/$1", + "uploadPattern": "/ch/hsr/adv/adv-ui/1.2/$1", "matrixParams": { "override": 1 } diff --git a/build.gradle b/build.gradle index 175f4a0..ee45908 100644 --- a/build.gradle +++ b/build.gradle @@ -4,7 +4,7 @@ plugins { } group = 'ch.hsr.adv' -version = '1.1.1' +version = '1.2' /**************************************** * instructions for all projects diff --git a/ui-core/build.gradle b/ui-core/build.gradle index 34a24ce..969926a 100644 --- a/ui-core/build.gradle +++ b/ui-core/build.gradle @@ -30,7 +30,7 @@ dependencies { // common dependencies - compile('ch.hsr.adv:adv-commons:1.1.1') + compile('ch.hsr.adv:adv-commons:1.2') } mainClassName = 'ADVApplication' \ No newline at end of file