From 8eefe554c9e1374f16dc2368be4033e3b7efa808 Mon Sep 17 00:00:00 2001 From: ClaasN Date: Fri, 18 Aug 2023 12:37:51 +0200 Subject: [PATCH 01/45] spaeter commit --- .../org.eclipse.elk.targetplatform.target | 16 +- .../feature.xml | 7 + .../org.eclipse.elk.alg.yconstree/.classpath | 8 + .../org.eclipse.elk.alg.yconstree/.project | 46 + .../.settings/org.eclipse.jdt.core.prefs | 297 + .../.settings/org.eclipse.jdt.ui.prefs | 5 + .../META-INF/MANIFEST.MF | 13 + .../org.eclipse.elk.alg.yconstree/about.html | 36 + .../build.properties | 18 + .../images/Force.svg | 10131 ++++++++++++++++ .../images/Stress.svg | 1860 +++ .../images/exampleForce.elkt | 44 + .../images/force_layout.png | Bin 0 -> 24084 bytes .../images/stress_layout.png | Bin 0 -> 25835 bytes plugins/org.eclipse.elk.alg.yconstree/pom.xml | 49 + ...ipse.elk.core.data.ILayoutMetaDataProvider | 1 + .../elk/alg/yconstree/InternalProperties.java | 38 + .../eclipse/elk/alg/yconstree/Yconstree.melk | 65 + .../alg/yconstree/YconstreeLayoutPhases.java | 25 + .../yconstree/YconstreeLayoutProvider.java | 62 + .../yconstree/p1treechecking/TreeChecker.java | 42 + .../p1treechecking/TreeCheckerStrategy.java | 37 + .../yconstree/p2yplacement/NodeYPlacer.java | 80 + .../p2yplacement/NodeYPlacerStrategy.java | 37 + .../yconstree/p3relative/NodeComparator.java | 28 + .../alg/yconstree/p3relative/OutlineNode.java | 91 + .../yconstree/p3relative/RelativeXPlacer.java | 330 + .../p3relative/RelativeXPlacerStrategy.java | 37 + .../yconstree/p4absolute/AbsoluteXPlacer.java | 91 + .../p4absolute/AbsoluteXPlacerStrategy.java | 38 + .../grandom/ide/AbstractGRandomIdeModule.java | 13 +- .../meta/ide/AbstractMetaDataIdeModule.java | 13 +- .../build.properties | 2 +- plugins/pom.xml | 1 + 34 files changed, 13541 insertions(+), 20 deletions(-) create mode 100644 plugins/org.eclipse.elk.alg.yconstree/.classpath create mode 100644 plugins/org.eclipse.elk.alg.yconstree/.project create mode 100644 plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.core.prefs create mode 100644 plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.ui.prefs create mode 100644 plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF create mode 100644 plugins/org.eclipse.elk.alg.yconstree/about.html create mode 100644 plugins/org.eclipse.elk.alg.yconstree/build.properties create mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/Force.svg create mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg create mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt create mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/force_layout.png create mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/stress_layout.png create mode 100644 plugins/org.eclipse.elk.alg.yconstree/pom.xml create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacerStrategy.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/NodeComparator.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacerStrategy.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacerStrategy.java diff --git a/build/org.eclipse.elk.targetplatform/org.eclipse.elk.targetplatform.target b/build/org.eclipse.elk.targetplatform/org.eclipse.elk.targetplatform.target index 1fdbcaa94e..b7a2a2084e 100644 --- a/build/org.eclipse.elk.targetplatform/org.eclipse.elk.targetplatform.target +++ b/build/org.eclipse.elk.targetplatform/org.eclipse.elk.targetplatform.target @@ -1,19 +1,21 @@ - + + + + + + - - - - - + - + + diff --git a/features/org.eclipse.elk.algorithms.feature/feature.xml b/features/org.eclipse.elk.algorithms.feature/feature.xml index 016c5fc402..30747129c6 100644 --- a/features/org.eclipse.elk.algorithms.feature/feature.xml +++ b/features/org.eclipse.elk.algorithms.feature/feature.xml @@ -101,5 +101,12 @@ SPDX-License-Identifier: EPL-2.0 install-size="0" version="0.0.0" unpack="false"/> + + diff --git a/plugins/org.eclipse.elk.alg.yconstree/.classpath b/plugins/org.eclipse.elk.alg.yconstree/.classpath new file mode 100644 index 0000000000..f0c5549859 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/plugins/org.eclipse.elk.alg.yconstree/.project b/plugins/org.eclipse.elk.alg.yconstree/.project new file mode 100644 index 0000000000..50488b91db --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/.project @@ -0,0 +1,46 @@ + + + org.eclipse.elk.alg.yconstree + + + + + + org.eclipse.xtext.ui.shared.xtextBuilder + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + net.sf.eclipsecs.core.CheckstyleBuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + net.sf.eclipsecs.core.CheckstyleNature + org.eclipse.xtext.ui.shared.xtextNature + + diff --git a/plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.core.prefs b/plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..5ed2aebf75 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,297 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.8 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.8 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_annotation=0 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=16 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_method_declaration=0 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_resources_in_try=80 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_union_type_in_multicatch=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=0 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_lambda_body=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false +org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false +org.eclipse.jdt.core.formatter.comment.format_block_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true +org.eclipse.jdt.core.formatter.comment.format_line_comments=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=120 +org.eclipse.jdt.core.formatter.comment.new_lines_at_block_boundaries=true +org.eclipse.jdt.core.formatter.comment.new_lines_at_javadoc_boundaries=true +org.eclipse.jdt.core.formatter.comment.preserve_white_space_between_code_and_line_comments=false +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.disabling_tag=@formatter\:off +org.eclipse.jdt.core.formatter.enabling_tag=@formatter\:on +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.format_line_comment_starting_on_first_column=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_field=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_method=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_package=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_type=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_label=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_after_type_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_try_resources=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_try=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_lambda_arrow=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_try=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_try_resources=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.join_lines_in_comments=true +org.eclipse.jdt.core.formatter.join_wrapped_lines=true +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=120 +org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false +org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=space +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_on_off_tags=true +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=true +org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true +org.eclipse.jdt.core.formatter.wrap_before_or_operator_multicatch=true +org.eclipse.jdt.core.formatter.wrap_outer_expressions_when_nested=true +org.eclipse.jdt.core.javaFormatter=org.eclipse.jdt.core.defaultJavaFormatter diff --git a/plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.ui.prefs b/plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..d529be02be --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +formatter_profile=_Elk +formatter_settings_version=12 +org.eclipse.jdt.ui.javadoc=true +org.eclipse.jdt.ui.text.custom_code_templates= diff --git a/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF b/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..d0728f8a27 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF @@ -0,0 +1,13 @@ +Manifest-Version: 1.0 +Automatic-Module-Name: org.eclipse.elk.alg.force +Bundle-ManifestVersion: 2 +Bundle-Name: ELK Force Layout Algorithm +Bundle-SymbolicName: org.eclipse.elk.alg.force;singleton:=true +Bundle-Version: 0.9.0.qualifier +Bundle-Vendor: Eclipse Modeling Project +Bundle-RequiredExecutionEnvironment: JavaSE-1.8 +Require-Bundle: com.google.guava, + org.eclipse.elk.alg.common, + org.eclipse.elk.core, + org.eclipse.elk.graph +Export-Package: org.eclipse.elk.alg.yconstree diff --git a/plugins/org.eclipse.elk.alg.yconstree/about.html b/plugins/org.eclipse.elk.alg.yconstree/about.html new file mode 100644 index 0000000000..164f781a8f --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/about.html @@ -0,0 +1,36 @@ + + + + +About + + +

About This Content

+ +

November 30, 2017

+

License

+ +

+ The Eclipse Foundation makes available all content in this plug-in + ("Content"). Unless otherwise indicated below, the Content + is provided to you under the terms and conditions of the Eclipse + Public License Version 2.0 ("EPL"). A copy of the EPL is + available at http://www.eclipse.org/legal/epl-2.0. + For purposes of the EPL, "Program" will mean the Content. +

+ +

+ If you did not receive this Content directly from the Eclipse + Foundation, the Content is being redistributed by another party + ("Redistributor") and different terms and conditions may + apply to your use of any object code in the Content. Check the + Redistributor's license that was provided with the Content. If no such + license exists, contact the Redistributor. Unless otherwise indicated + below, the terms and conditions of the EPL still apply to any source + code in the Content and such source code may be obtained at http://www.eclipse.org. +

+ + + \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/build.properties b/plugins/org.eclipse.elk.alg.yconstree/build.properties new file mode 100644 index 0000000000..90b6bbaa24 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/build.properties @@ -0,0 +1,18 @@ +############################################################################### +# Copyright (c) 2011, 2015 Kiel University and others. +# +# This program and the accompanying materials are made available under the +# terms of the Eclipse Public License 2.0 which is available at +# http://www.eclipse.org/legal/epl-2.0. +# +# SPDX-License-Identifier: EPL-2.0 +############################################################################### +source.. = src/,\ + src-gen/ +output.. = bin/ +bin.includes = META-INF/,\ + .,\ + images/,\ + about.html +src.includes = about.html +additional.bundles = org.eclipse.xtext.xbase.lib diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/Force.svg b/plugins/org.eclipse.elk.alg.yconstree/images/Force.svg new file mode 100644 index 0000000000..3d54a1fbdf --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/images/Force.svg @@ -0,0 +1,10131 @@ + +image/svg+xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Wednesday, May 17, 2017 10:16:58 PM CEST + + \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg b/plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg new file mode 100644 index 0000000000..fcaa29f601 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg @@ -0,0 +1,1860 @@ + +image/svg+xml + + + + + + + + + + +Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Thursday, September 7, 2017 2:16:27 PM CEST + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt b/plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt new file mode 100644 index 0000000000..284b2d2f69 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt @@ -0,0 +1,44 @@ +/******************************************************************************* + * Copyright (c) 2019 Kiel University and others. + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +algorithm: force +spacing.nodeNode:100 +model:FRUCHTERMAN_REINGOLD + +edge node1 -> node2 +edge node2 -> node4 +edge node2 -> node7 +edge node4 -> node6 +edge node6 -> node10 +edge node6 -> node12 +edge node7-> node10 +edge node7-> node11 +edge node10-> node12 + + +edge node3 -> node4 +edge node3 -> node5 +edge node3 -> node6 +edge node5 -> node8 +edge node5 -> node9 +edge node9 -> node11 +edge node9 -> node12 + +node node1 +node node2 +node node3 +node node4 +node node5 + +node node6 +node node7 +node node8 +node node9 +node node10 +node node11 +node node12 diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/force_layout.png b/plugins/org.eclipse.elk.alg.yconstree/images/force_layout.png new file mode 100644 index 0000000000000000000000000000000000000000..f99a6e8a1d1884b8e79976641911313aa9c01ba0 GIT binary patch literal 24084 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%0Atj~K5kU-^*U&XR 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 literal 0 HcmV?d00001 diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/stress_layout.png b/plugins/org.eclipse.elk.alg.yconstree/images/stress_layout.png new file mode 100644 index 0000000000000000000000000000000000000000..6848d9864b18f18363e686e012dcfee809437280 GIT binary patch literal 25835 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

-8$*3bfGGskOC+Gh-BLy`j;|n6BRiP76SM(sO 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 b-E*a{w3?aU8kfKalR)&ej1g6L(NF&eQ@~b= literal 0 HcmV?d00001 diff --git a/plugins/org.eclipse.elk.alg.yconstree/pom.xml b/plugins/org.eclipse.elk.alg.yconstree/pom.xml new file mode 100644 index 0000000000..b8c1772e09 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/pom.xml @@ -0,0 +1,49 @@ + + + + 4.0.0 + + org.eclipse.elk + parent + 0.9.0-SNAPSHOT + ../../build/pom.xml + + + org.eclipse.elk + org.eclipse.elk.alg.yconstree + ELK Force Layout Algorithm + 0.9.0-SNAPSHOT + Tree drawing algorithm with y-level constrains. + eclipse-plugin + + + + org.eclipse.elk + org.eclipse.elk.core + ${project.version} + + + org.eclipse.elk + org.eclipse.elk.alg.common + ${project.version} + + + + + + + + org.eclipse.xtext + xtext-maven-plugin + + + + diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider b/plugins/org.eclipse.elk.alg.yconstree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider new file mode 100644 index 0000000000..bef67bdefd --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/META-INF/services/org.eclipse.elk.core.data.ILayoutMetaDataProvider @@ -0,0 +1 @@ +org.eclipse.elk.alg.yconstree.options.YconstreeMetaDataProvider \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java new file mode 100644 index 0000000000..090f69a76c --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree; + +import org.eclipse.elk.alg.yconstree.p3relative.OutlineNode; +import org.eclipse.elk.core.options.CoreOptions; +import org.eclipse.elk.core.options.PortConstraints; +import org.eclipse.elk.graph.properties.IProperty; +import org.eclipse.elk.graph.properties.Property; + +/** + * @author claas + * + */ +public class InternalProperties { + /** + * Defines the left outline of this subtree. + */ + public static final IProperty LEFT_OUTLINE = new Property("LEFT_OUTLINE"); + + /** + * Defines the right outline of this subtree. + */ + public static final IProperty RIGHT_OUTLINE = new Property("RIGHT_OUTLINE"); + + /** + * Defines the maximum depth (as a coordinate) + */ + public static final IProperty MAX_DEPTH = new Property("MAX_DEPTH"); + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk new file mode 100644 index 0000000000..358ca31d42 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk @@ -0,0 +1,65 @@ +/******************************************************************************* + * Copyright (c) 2015, 2020 Kiel University and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutProvider +import org.eclipse.elk.core.math.ElkPadding +import org.eclipse.elk.core.util.ExclusiveBounds +import org.eclipse.elk.core.options.TopdownNodeTypes + +/** + * Declarations for the ELK Force layout algorithm. + */ +bundle { + metadataClass options.YconstreeMetaDataProvider + idPrefix org.eclipse.elk.yconstree +} + +algorithm yconstree(YconstreeLayoutProvider) { + label "ELK Yconstree" + description + "Force-based algorithm provided by the Eclipse Layout Kernel. Implements methods that + follow physical analogies by simulating forces that move the nodes into a balanced + distribution. Currently the original Eades model and the Fruchterman - Reingold model are + supported." + metadataClass options.YconstreeOptions + category org.eclipse.elk.tree + features multi_edges, edge_labels + preview images/force_layout.png + supports org.eclipse.elk.priority = 1 + documentation "Priorities set on nodes determine the order in which connected components are placed: + components with a higher sum of node priorities will end up + before components with a lower sum. + Priorities set on edges usually directly influence the attractive force of a connection, + with higher priorities corresponding to greater attractive forces." + supports org.eclipse.elk.spacing.nodeNode = 80 + supports org.eclipse.elk.spacing.edgeLabel = 5 + supports org.eclipse.elk.aspectRatio = 1.6f + supports org.eclipse.elk.randomSeed = 1 + supports org.eclipse.elk.separateConnectedComponents = true + supports org.eclipse.elk.padding = new ElkPadding(50) + supports org.eclipse.elk.interactive + supports org.eclipse.elk.portConstraints + supports org.eclipse.elk.edgeLabels.inline = false + // Common node micro layout + supports org.eclipse.elk.omitNodeMicroLayout + supports org.eclipse.elk.nodeSize.fixedGraphSize + supports org.eclipse.elk.nodeSize.options + supports org.eclipse.elk.nodeSize.constraints + supports org.eclipse.elk.nodeLabels.placement + supports org.eclipse.elk.portLabels.placement + supports verticalConstraint +} + + +option verticalConstraint: double { + label "Fixed vertical position" + targets nodes +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java new file mode 100644 index 0000000000..634e44d184 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java @@ -0,0 +1,25 @@ +/******************************************************************************* + * Copyright (c) 2011, 2020 Kiel University and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree; +/** + * This algorithm's layout phases. each phase has its own strategy factory. + */ +public enum YconstreeLayoutPhases { + + /** Phase 1. */ + //P1_TREECHECKING, + /** Phase 2. */ + P2_NODE_Y_PLACEMENT, + /** Phase 2. */ + P3_NODE_RELATIV_PLACEMENT, + /** Phase 2. */ + P4_NODE_ABSOLUTE_PLACEMENT; + +} \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java new file mode 100644 index 0000000000..99e1d2a483 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java @@ -0,0 +1,62 @@ +/******************************************************************************* + * Copyright (c) 2011, 2020 Kiel University and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree; + +import java.util.List; + +import org.eclipse.elk.alg.yconstree.p1treechecking.TreeCheckerStrategy; +import org.eclipse.elk.alg.yconstree.p2yplacement.NodeYPlacerStrategy; +import org.eclipse.elk.alg.yconstree.p3relative.RelativeXPlacerStrategy; +import org.eclipse.elk.alg.yconstree.p4absolute.AbsoluteXPlacerStrategy; +import org.eclipse.elk.core.AbstractLayoutProvider; +import org.eclipse.elk.core.alg.AlgorithmAssembler; +import org.eclipse.elk.core.alg.ILayoutProcessor; +import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkNode; + +/** + * Layout provider for the force layout algorithms. + */ +public final class YconstreeLayoutProvider extends AbstractLayoutProvider { + + + private final AlgorithmAssembler algorithmAssembler = + AlgorithmAssembler.create(YconstreeLayoutPhases.class); + + @Override + public void layout(ElkNode graph, IElkProgressMonitor progressMonitor) { + List> algorithm = assembleAlgorithm(graph); + + progressMonitor.begin("Tree layout", algorithm.size()); + + for (ILayoutProcessor processor : algorithm) { + processor.process(graph, progressMonitor.subTask(1)); + } + + progressMonitor.done(); + } + + public List> assembleAlgorithm(ElkNode graph) { + algorithmAssembler.reset(); + + // Configure phases + algorithmAssembler.setPhase(YconstreeLayoutPhases.P2_NODE_Y_PLACEMENT, + NodeYPlacerStrategy.SIMPLE_YPLACING); + algorithmAssembler.setPhase(YconstreeLayoutPhases.P3_NODE_RELATIV_PLACEMENT, + RelativeXPlacerStrategy.SIMPLE_XPLACING); + algorithmAssembler.setPhase(YconstreeLayoutPhases.P4_NODE_ABSOLUTE_PLACEMENT, + AbsoluteXPlacerStrategy.ABSOLUTE_XPLACING); + + // Assemble the algorithm + return algorithmAssembler.build(graph); + } + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java new file mode 100644 index 0000000000..54fb32800f --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java @@ -0,0 +1,42 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p1treechecking; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public class TreeChecker implements ILayoutPhase { + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) + */ + @Override + public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { + // TODO Auto-generated method stub + + } + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) + */ + @Override + public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java new file mode 100644 index 0000000000..a7e183d7e8 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p1treechecking; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.ILayoutPhaseFactory; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public enum TreeCheckerStrategy implements ILayoutPhaseFactory { + + SIMPLE_TREECHECKING; + + @Override + public ILayoutPhase create() { + switch (this) { + case SIMPLE_TREECHECKING: + return new TreeChecker(); + + default: + throw new IllegalArgumentException( + "No implementation is available for the node orderer " + this.toString()); + } + } + +} \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java new file mode 100644 index 0000000000..63cb6541d1 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java @@ -0,0 +1,80 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p2yplacement; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.alg.yconstree.options.YconstreeOptions; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public class NodeYPlacer implements ILayoutPhase { + + private final double STANDARD_DISTANCE = 50.0; + private IElkProgressMonitor pm; + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) + */ + @Override + public void process(final ElkNode graph, IElkProgressMonitor progressMonitor) { + // TODO Auto-generated method stub + //elkGraph.setX(0.0); + pm = progressMonitor; + pm.begin("YPlacer", 1); + + try { + if (!graph.getChildren().isEmpty()){ + ElkNode parent = graph.getChildren().get(0); + setYLevels(parent,0.0); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + pm.done(); + } + + /** + * A Method to set the absolute Y coordinates of the notes. + * Uses a default distance between the notes. + * @param node and it's children are getting updated Y-coords. + * @param minHeight: Node gets minimum this height. + */ + private void setYLevels(ElkNode node, double minHeight) { + // TODO: Y-Level_Constraints, remove different heightlevels. + if (node.hasProperty(YconstreeOptions.VERTICAL_CONSTRAINT)) { + pm.log("hier hab ich einen Constraint"); + minHeight = node.getProperty(YconstreeOptions.VERTICAL_CONSTRAINT); + //System.out.println("Hab was"); + } + node.setY(minHeight); + double newMinHeight = minHeight + STANDARD_DISTANCE + node.getHeight(); + for (int i = 0; i < node.getOutgoingEdges().size(); i++) { + ElkNode child = (ElkNode) node.getOutgoingEdges().get(i).getTargets().get(0); + setYLevels(child, newMinHeight); + } + } + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) + */ + @Override + public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacerStrategy.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacerStrategy.java new file mode 100644 index 0000000000..918edddb46 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacerStrategy.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p2yplacement; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.ILayoutPhaseFactory; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public enum NodeYPlacerStrategy implements ILayoutPhaseFactory { + + SIMPLE_YPLACING; + + @Override + public ILayoutPhase create() { + switch (this) { + case SIMPLE_YPLACING: + return new NodeYPlacer(); + + default: + throw new IllegalArgumentException( + "No implementation is available for the node orderer " + this.toString()); + } + } + +} \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/NodeComparator.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/NodeComparator.java new file mode 100644 index 0000000000..bebe524fb0 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/NodeComparator.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p3relative; + +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +class NodeComparator implements java.util.Comparator { + + /* (non-Javadoc) + * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object) + */ + @Override + public int compare(final ElkNode a, final ElkNode b) { + // TODO Auto-generated method stub + return (int) (a.getY() - b.getY()); // might be problematic when very small numbers are compared + } +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java new file mode 100644 index 0000000000..32fbd35421 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p3relative; + +/** + * @author claas + * + */ +public class OutlineNode { + + private double relativeX; + private double relativeY; + private OutlineNode next; + + OutlineNode(double relativeX, double relativeY, OutlineNode next){ + this.setRelativeX(relativeX); + this.setRelativeY(relativeY); + this.setNext(next); + } + + /** + * @return the relativeY + */ + public double getRelativeY() { + return relativeY; + } + + /** + * @param relativeY the relativeY to set + */ + public void setRelativeY(double relativeY) { + this.relativeY = relativeY; + } + + /** + * @return the relativeX + */ + public double getRelativeX() { + return relativeX; + } + + /** + * @param relativeX the relativeX to set + */ + public void setRelativeX(double relativeX) { + this.relativeX = relativeX; + } + + /** + * @return the next + */ + public OutlineNode getNext() { + return next; + } + + /** + * @param next the next to set + */ + public void setNext(OutlineNode next) { + this.next = next; + } + + /** + * @return a string representation of this objects relative coordinates + */ + public String toString() { + return "X:" + relativeX + ", Y:" + relativeY; + } + + /** + * + * @return if this OutlineNode has no "next" + */ + public boolean isLast() { + return next == null; + } + + public void printFullOutline() { + System.out.println(this.toString()); + if(!this.isLast()) { + this.getNext().printFullOutline(); + } + } +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java new file mode 100644 index 0000000000..c6023da7bc --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java @@ -0,0 +1,330 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p3relative; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.eclipse.elk.alg.yconstree.InternalProperties; +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; +import org.eclipse.elk.core.math.ElkMargin; +import org.eclipse.elk.core.options.CoreOptions; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkNode; +import org.eclipse.elk.graph.properties.IProperty; + +/** + * @author claas + * + */ +public class RelativeXPlacer implements ILayoutPhase { + + + private IElkProgressMonitor pm; + private double spacingNodeNode = 0.0; + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) + */ + @Override + public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { + // TODO Auto-generated method stub + pm = progressMonitor; + pm.begin("XPlacer", 1); + + spacingNodeNode = graph.getProperty(CoreOptions.SPACING_NODE_NODE); + + try { + if (!graph.getChildren().isEmpty()){ + ElkNode parent = graph.getChildren().get(0); + + yConsTreeStep(parent); + // for debugging: print outlines + parent.getProperty(InternalProperties.RIGHT_OUTLINE).printFullOutline(); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + pm.done(); + } + + private void testfunction() { + OutlineNode outline1 = new OutlineNode(20.0, 0.0, new OutlineNode(0.0, 30.0, new OutlineNode(30.0, 30.0, new OutlineNode(0.0, 40.0, new OutlineNode(-20.0, 0.0, new OutlineNode(0.0, 20.0, null)))))); + OutlineNode outline3 = new OutlineNode(0.0, 0.0, new OutlineNode(0.0, 40.0, null)); + + System.out.println("Hello There"); + double dist = outlineDistance(outline1, 0.0, outline3, 0.0, true); + System.out.println(dist); + } + + private double outlineDistance(OutlineNode outline1, double start1, OutlineNode outline2, double start2, boolean UseMaxDisp) { + OutlineNode o1 = outline1; + OutlineNode o2 = outline2; + double y1 = o1.getRelativeY() + start1; + double y2 = o2.getRelativeY() + start2; + double x1 = o1.getRelativeX(); + double x2 = o2.getRelativeX(); + double maxO1 = o1.getRelativeX(); + double minO2 = o2.getRelativeX(); + double dist = o1.getRelativeX() - o2.getRelativeX(); + while(!o1.isLast() && !o2.isLast()) { + if (y1 <= y2 && y1 + o1.getNext().getRelativeY() > y2) { + dist = max(dist, (x1 + (y2 - y1) * o1.getNext().getRelativeX() / o1.getNext().getRelativeY()) - x2); + } + if (y2 <= y1 && y2 + o2.getNext().getRelativeY() > y1) { + dist = max(dist, x1 - (x2 + (y1 - y2) * o2.getNext().getRelativeX() / o2.getNext().getRelativeY())); + } + if (y2 + o2.getNext().getRelativeY() < y1 + o1.getNext().getRelativeY()) { + y2 += o2.getNext().getRelativeY(); + x2 += o2.getNext().getRelativeX(); + o2 = o2.getNext(); + minO2 = min(minO2, x2); + } else { + y1 += o1.getNext().getRelativeY(); + x1 += o1.getNext().getRelativeX(); + o1 = o1.getNext(); + maxO1 = max(maxO1, x1); + } + } + if (!o1.isLast()){ + if (y1 <= y2 && y1 + o1.getNext().getRelativeY() > y2) { + dist = max(dist, (x1 + (y2 - y1) * o1.getNext().getRelativeX() / o1.getNext().getRelativeY()) - x2); + } else { + if (UseMaxDisp){ + dist = max(dist,-minO2 + o1.getRelativeX()); + } + } + } + if (!o2.isLast()) { + if (y2 <= y1) { + dist = max(dist, x1 - (x2 + (y1 - y2) * o2.getNext().getRelativeX() / o2.getNext().getRelativeY())); + } else { + if (UseMaxDisp){ + dist = max(dist,maxO1); + } + } + } + return dist; + } + + + /** + * Just a rudimentary function to + * @param d + * @param e + * @return + */ + private double min(double d, double e) { + // TODO Auto-generated method stub + return d < e ? d : e; + } + + /** + * @param d + * @param e + * @return + */ + private double max(double d, double e) { + // TODO Auto-generated method stub + return d > e ? d : e; + } + + /** + * This is the recursive function that calculates the layout for one node and it's children. + * @param graph + */ + private void yConsTreeStep(ElkNode graph) { + + ElkMargin margins = graph.getProperty(CoreOptions.MARGINS); + + // set the properties for left and right outlines + graph.setProperty(InternalProperties.LEFT_OUTLINE, new OutlineNode((-margins.left), (-margins.top), new OutlineNode(0.0, graph.getHeight() + margins.top + margins.bottom, null))); + graph.setProperty(InternalProperties.RIGHT_OUTLINE, new OutlineNode(graph.getWidth() + margins.right, -margins.top, new OutlineNode(0.0, graph.getHeight() + margins.top + margins.bottom, null))); + System.out.println(graph.getProperty(InternalProperties.RIGHT_OUTLINE)); + // checks if this node is a leaf + if (graph.getOutgoingEdges().isEmpty()) { + System.out.println("bin ein Blatt"); + graph.setProperty(InternalProperties.MAX_DEPTH, graph.getY() + graph.getHeight()); + graph.setX(0); + } else { + System.out.println("bin ein Knoten"); + graph.setProperty(InternalProperties.MAX_DEPTH, 0.0); + // create a list with references to all children of this node. + List children = new ArrayList<>(); + for (int i = 0; i < graph.getOutgoingEdges().size(); i++) { + ElkNode child = (ElkNode) graph.getOutgoingEdges().get(i).getTargets().get(0); + yConsTreeStep(child); + graph.setProperty(InternalProperties.MAX_DEPTH, max((double) graph.getProperty(InternalProperties.MAX_DEPTH), (double) child.getProperty(InternalProperties.MAX_DEPTH))); + // ein Test + //graph.setX((double) graph.getProperty(MAX_DEPTH)); + children.add(child); + } + + // now the children of this node get sorted to form a semi-circle. + sortSubTrees(children); + System.out.println("bis hier klappts noch"); + + // now the children get stuffed together, using the outlines. + for (int i = 0; i < children.size() - 1; i++) { + putThemTogether(children.get(0), children.get(i), children.get(i + 1)); + } + + // now we need to move the root to the middle of the nodes. + // we calculate the point of the child with the lowest y-position to avoid overlapping. + // if there is more than one lowest child, the root will be positioned in the middle of them. + int lowestChildPos = 0; + double lowestChildY = 0.0; + double lowestChildStart = 0.0; + //** + while (lowestChildPos < children.size() && children.get(lowestChildPos).getY() >= lowestChildY) { + if (children.get(lowestChildPos).getY() > lowestChildY) { + lowestChildStart = children.get(lowestChildPos).getX(); + lowestChildY = children.get(lowestChildPos).getY(); + } + lowestChildPos++; + } + + double moveRoot = 0.0; + if (lowestChildPos > 0) { + moveRoot = (children.get(lowestChildPos - 1).getX() + children.get(lowestChildPos - 1).getWidth() + lowestChildStart - graph.getWidth()) / 2 - graph.getX(); + } + for(ElkNode child: children) { + child.setX(child.getX() - moveRoot); + } + + // now we need to combine the outlines of the root with the outlines of the most outer children. + graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().setNext(new OutlineNode(-moveRoot, children.get(0).getY() - graph.getHeight() - graph.getY(), children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getNext())); + double newX = children.get(children.size() - 1).getX() + children.get(children.size() - 1).getWidth() - graph.getWidth(); + double newY = children.get(children.size() - 1).getY() - graph.getHeight() - graph.getY(); + OutlineNode newNext = children.get(children.size() - 1).getProperty(InternalProperties.RIGHT_OUTLINE).getNext(); + graph.getProperty(InternalProperties.RIGHT_OUTLINE).getNext().setNext(new OutlineNode(newX, newY, newNext)); + //**/ + + + } + } + + /** + * sorts the subTrees in a half circle, uses mergesort. + * @param graph + */ + private void sortSubTrees(List children) { + + // fist, we sort the SubTrees by the Y-coordinate of their root. + Collections.sort(children, new NodeComparator()); + + // now we need to put them in a V-shape + // the deepest element gets ignored in the calculation of the widths. + List a = new ArrayList<>(); + a.add(children.get(children.size() - 1)); + List b = new ArrayList<>(); + double widthA = 0.0, widthB = 0.0; + for (int i = 1; i < children.size(); i++) { + if (widthA <= widthB) { + a.add(children.get(children.size() - 1 - i)); + widthA += children.get(children.size() - 1 - i).getWidth(); + } else { + b.add(children.get(children.size() - 1 - i)); + widthB += children.get(children.size() - 1 - i).getWidth(); + } + } + Collections.reverse(a); + a.addAll(b); + for (int i = 0; i < children.size(); i++) { + children.set(i, a.get(i)); + } + + } + + private void putThemTogether(ElkNode leftSubtree, ElkNode a, ElkNode b) { + // calculate distance between the two parts + double dist = outlineDistance(a.getProperty(InternalProperties.RIGHT_OUTLINE), a.getY(), b.getProperty(InternalProperties.LEFT_OUTLINE), b.getY(), true); + b.setX(a.getX() + dist); + + // update the left outline, if needed + if (leftSubtree.getProperty(InternalProperties.MAX_DEPTH) < b.getProperty(InternalProperties.MAX_DEPTH)) { + + // needed to calculate the position of the intercept between the two outlines. + OutlineNode leftSubtreeLast = leftSubtree.getProperty(InternalProperties.LEFT_OUTLINE); + double leftSubtreeX = leftSubtreeLast.getRelativeX(); + + // jump to last position of the outline of leftSubtree + while (!leftSubtreeLast.isLast()) { + leftSubtreeLast = leftSubtreeLast.getNext(); + leftSubtreeX += leftSubtreeLast.getRelativeX(); + } + + // move on the outline of b to the position of the intercept. + OutlineNode bLolIterator = b.getProperty(InternalProperties.LEFT_OUTLINE); + double bAbsY = b.getY() + bLolIterator.getRelativeY(); + double bX = bLolIterator.getRelativeX(); + while (bAbsY < leftSubtree.getProperty(InternalProperties.MAX_DEPTH)) { + bLolIterator = bLolIterator.getNext(); + bAbsY += bLolIterator.getRelativeY(); + bX += bLolIterator.getRelativeX(); + } + double deltaY = b.getProperty(InternalProperties.MAX_DEPTH) - leftSubtree.getProperty(InternalProperties.MAX_DEPTH); + double deltaX = 0.0; + if (bLolIterator.getRelativeY() != 0.0) { + deltaX = bLolIterator.getRelativeX() * deltaY / bLolIterator.getRelativeY(); + } + double newX = b.getX() + bX - leftSubtreeX - deltaX; + leftSubtreeLast.setNext(new OutlineNode(newX, 0.0, new OutlineNode(deltaX, deltaY, bLolIterator.getNext()))); + leftSubtree.setProperty(InternalProperties.MAX_DEPTH, b.getProperty(InternalProperties.MAX_DEPTH)); + } + //** + // update the right outline, if needed + if (a.getProperty(InternalProperties.MAX_DEPTH) > b.getProperty(InternalProperties.MAX_DEPTH)) { + + // needed to calculate the position of the intercept between the two outlines. + OutlineNode bLast = b.getProperty(InternalProperties.RIGHT_OUTLINE); + double bX = bLast.getRelativeX(); + + // jump to last position of the outline of b + while (!bLast.isLast()) { + bLast = bLast.getNext(); + bX += bLast.getRelativeX(); + } + + // move on the outline of a to the position of the intercept. + OutlineNode aRolIterator = a.getProperty(InternalProperties.RIGHT_OUTLINE); + double aAbsY = a.getY() + aRolIterator.getRelativeY(); + double aX = aRolIterator.getRelativeX(); + while (aAbsY < b.getProperty(InternalProperties.MAX_DEPTH)) { + aRolIterator = aRolIterator.getNext(); + aAbsY += aRolIterator.getRelativeY(); + aX += aRolIterator.getRelativeX(); + } + double deltaY = aAbsY - b.getProperty(InternalProperties.MAX_DEPTH); + double deltaX = 0.0; + if (aRolIterator.getRelativeY() != 0.0) { + deltaX = aRolIterator.getRelativeX() * deltaY / aRolIterator.getRelativeY(); + } + double newX = aX + a.getX() - deltaX - bX - b.getX(); + bLast.setNext(new OutlineNode(newX, 0.0, new OutlineNode(deltaX, deltaY, aRolIterator.getNext()))); + b.setProperty(InternalProperties.MAX_DEPTH, a.getProperty(InternalProperties.MAX_DEPTH)); + } + //**/ + } + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) + */ + @Override + public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacerStrategy.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacerStrategy.java new file mode 100644 index 0000000000..6701ff0361 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacerStrategy.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p3relative; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.ILayoutPhaseFactory; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public enum RelativeXPlacerStrategy implements ILayoutPhaseFactory { + + SIMPLE_XPLACING; + + @Override + public ILayoutPhase create() { + switch (this) { + case SIMPLE_XPLACING: + return new RelativeXPlacer(); + + default: + throw new IllegalArgumentException( + "No implementation is available for the node orderer " + this.toString()); + } + } + +} \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java new file mode 100644 index 0000000000..062c3318a3 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java @@ -0,0 +1,91 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p4absolute; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public class AbsoluteXPlacer implements ILayoutPhase { + + private IElkProgressMonitor pm; + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) + */ + @Override + public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { + // TODO Auto-generated method stub + pm = progressMonitor; + pm.begin("AbsolutPlacer", 1); + + try { + if (!graph.getChildren().isEmpty()){ + ElkNode parent = graph.getChildren().get(0); + + // first, move the root + parent.setX(parent.getX() - findMinimalX(parent)); + // now we update the whole tree to absolute X + absoluteTreeCoords(parent); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + pm.done(); + + } + + + private double findMinimalX(ElkNode t) { + int numOfChildren = t.getOutgoingEdges().size(); + if (numOfChildren == 0) { + return t.getX(); + } else { + double minSubtreeX = 0.0; + double testX = 0.0; + for (int i = 0; i < numOfChildren; i++) { + testX = findMinimalX((ElkNode) t.getOutgoingEdges().get(i).getTargets().get(0)); + minSubtreeX = (testX < minSubtreeX) ? testX : minSubtreeX; + } + return minSubtreeX + t.getX(); + } + } + + private void absoluteTreeCoords(ElkNode t) { + int numOfChildren = t.getOutgoingEdges().size(); + if (numOfChildren > 0) { + ElkNode child; + for (int i = 0; i < numOfChildren; i++) { + child = (ElkNode) t.getOutgoingEdges().get(i).getTargets().get(0); + child.setX(child.getX() + t.getX()); + absoluteTreeCoords(child); + } + } + } + + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) + */ + @Override + public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + // TODO Auto-generated method stub + return null; + } + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacerStrategy.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacerStrategy.java new file mode 100644 index 0000000000..884ced9669 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacerStrategy.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p4absolute; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.alg.yconstree.p3relative.RelativeXPlacer; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.ILayoutPhaseFactory; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public enum AbsoluteXPlacerStrategy implements ILayoutPhaseFactory { + + ABSOLUTE_XPLACING; + + @Override + public ILayoutPhase create() { + switch (this) { + case ABSOLUTE_XPLACING: + return new AbsoluteXPlacer(); + + default: + throw new IllegalArgumentException( + "No implementation is available for the node orderer " + this.toString()); + } + } + +} \ No newline at end of file diff --git a/plugins/org.eclipse.elk.core.debug.grandom.ide/src-gen/org/eclipse/elk/core/debug/grandom/ide/AbstractGRandomIdeModule.java b/plugins/org.eclipse.elk.core.debug.grandom.ide/src-gen/org/eclipse/elk/core/debug/grandom/ide/AbstractGRandomIdeModule.java index 32da75bebf..8196096946 100644 --- a/plugins/org.eclipse.elk.core.debug.grandom.ide/src-gen/org/eclipse/elk/core/debug/grandom/ide/AbstractGRandomIdeModule.java +++ b/plugins/org.eclipse.elk.core.debug.grandom.ide/src-gen/org/eclipse/elk/core/debug/grandom/ide/AbstractGRandomIdeModule.java @@ -9,8 +9,6 @@ *******************************************************************************/ package org.eclipse.elk.core.debug.grandom.ide; -import com.google.inject.Binder; -import com.google.inject.name.Names; import org.eclipse.elk.core.debug.grandom.ide.contentassist.antlr.GRandomParser; import org.eclipse.elk.core.debug.grandom.ide.contentassist.antlr.internal.InternalGRandomLexer; import org.eclipse.xtext.ide.DefaultIdeModule; @@ -22,8 +20,11 @@ import org.eclipse.xtext.ide.editor.contentassist.antlr.IContentAssistParser; import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.Lexer; import org.eclipse.xtext.ide.refactoring.IRenameStrategy2; -import org.eclipse.xtext.ide.server.rename.IRenameService; -import org.eclipse.xtext.ide.server.rename.RenameService; +import org.eclipse.xtext.ide.server.rename.IRenameService2; +import org.eclipse.xtext.ide.server.rename.RenameService2; + +import com.google.inject.Binder; +import com.google.inject.name.Names; /** * Manual modifications go to {@link GRandomIdeModule}. @@ -54,8 +55,8 @@ public Class bindIPrefixMatcher() { } // contributed by org.eclipse.xtext.xtext.generator.ui.refactoring.RefactorElementNameFragment2 - public Class bindIRenameService() { - return RenameService.class; + public Class bindIRenameService() { + return RenameService2.class; } // contributed by org.eclipse.xtext.xtext.generator.ui.refactoring.RefactorElementNameFragment2 diff --git a/plugins/org.eclipse.elk.core.meta.ui/src-gen/org/eclipse/elk/core/meta/ide/AbstractMetaDataIdeModule.java b/plugins/org.eclipse.elk.core.meta.ui/src-gen/org/eclipse/elk/core/meta/ide/AbstractMetaDataIdeModule.java index 2407577598..946e966a84 100644 --- a/plugins/org.eclipse.elk.core.meta.ui/src-gen/org/eclipse/elk/core/meta/ide/AbstractMetaDataIdeModule.java +++ b/plugins/org.eclipse.elk.core.meta.ui/src-gen/org/eclipse/elk/core/meta/ide/AbstractMetaDataIdeModule.java @@ -9,8 +9,6 @@ *******************************************************************************/ package org.eclipse.elk.core.meta.ide; -import com.google.inject.Binder; -import com.google.inject.name.Names; import org.eclipse.elk.core.meta.ide.contentassist.antlr.MetaDataParser; import org.eclipse.elk.core.meta.ide.contentassist.antlr.internal.InternalMetaDataLexer; import org.eclipse.xtext.ide.LexerIdeBindings; @@ -21,10 +19,13 @@ import org.eclipse.xtext.ide.editor.contentassist.antlr.IContentAssistParser; import org.eclipse.xtext.ide.editor.contentassist.antlr.internal.Lexer; import org.eclipse.xtext.ide.refactoring.IRenameStrategy2; -import org.eclipse.xtext.ide.server.rename.IRenameService; -import org.eclipse.xtext.ide.server.rename.RenameService; +import org.eclipse.xtext.ide.server.rename.IRenameService2; +import org.eclipse.xtext.ide.server.rename.RenameService2; import org.eclipse.xtext.xbase.ide.DefaultXbaseIdeModule; +import com.google.inject.Binder; +import com.google.inject.name.Names; + /** * Manual modifications go to {@link MetaDataIdeModule}. */ @@ -54,8 +55,8 @@ public Class bindIPrefixMatcher() { } // contributed by org.eclipse.xtext.xtext.generator.ui.refactoring.RefactorElementNameFragment2 - public Class bindIRenameService() { - return RenameService.class; + public Class bindIRenameService() { + return RenameService2.class; } // contributed by org.eclipse.xtext.xtext.generator.ui.refactoring.RefactorElementNameFragment2 diff --git a/plugins/org.eclipse.elk.graph.json.text/build.properties b/plugins/org.eclipse.elk.graph.json.text/build.properties index 652c6e679b..a04f5f87be 100644 --- a/plugins/org.eclipse.elk.graph.json.text/build.properties +++ b/plugins/org.eclipse.elk.graph.json.text/build.properties @@ -17,4 +17,4 @@ additional.bundles = org.eclipse.xtext.xbase,\ org.apache.commons.logging,\ org.apache.log4j,\ com.ibm.icu,\ - org.eclipse.xtext.generator + org.eclipse.xtext.xtext.generator diff --git a/plugins/pom.xml b/plugins/pom.xml index 2ae32e203e..7f8bb79d42 100644 --- a/plugins/pom.xml +++ b/plugins/pom.xml @@ -37,6 +37,7 @@ org.eclipse.elk.alg.rectpacking org.eclipse.elk.alg.spore org.eclipse.elk.alg.topdownpacking + org.eclipse.elk.alg.yconstree org.eclipse.elk.conn.gmf org.eclipse.elk.core org.eclipse.elk.core.debug From 18646bac45b99a31d6908cc1bb2c644ba24ddb90 Mon Sep 17 00:00:00 2001 From: ClaasN Date: Fri, 15 Sep 2023 23:57:18 +0200 Subject: [PATCH 02/45] ein zwischenstand --- .../elk/alg/yconstree/InternalProperties.java | 15 +- .../eclipse/elk/alg/yconstree/Yconstree.melk | 1 + .../alg/yconstree/YconstreeLayoutPhases.java | 8 +- .../yconstree/YconstreeLayoutProvider.java | 3 + .../alg/yconstree/p3relative/OutlineNode.java | 20 +- .../yconstree/p3relative/RelativeXPlacer.java | 370 ++++++++++++------ .../yconstree/p4absolute/AbsoluteXPlacer.java | 4 + .../yconstree/p5edgerouting/Edgerouter.java | 88 +++++ .../p5edgerouting/EdgerouterStrategy.java | 38 ++ 9 files changed, 406 insertions(+), 141 deletions(-) create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/EdgerouterStrategy.java diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java index 090f69a76c..8dba8f9948 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java @@ -31,8 +31,21 @@ public class InternalProperties { public static final IProperty RIGHT_OUTLINE = new Property("RIGHT_OUTLINE"); /** - * Defines the maximum depth (as a coordinate) + * Defines the maximum depth (as a coordinate) outdated */ public static final IProperty MAX_DEPTH = new Property("MAX_DEPTH"); + + /** + * Defines the maximum depth of outlines + */ + public static final IProperty OUTLINE_MAX_DEPTH = new Property("OUTLINE_MAX_DEPTH"); + + /** + * Defines the canvas of the tree + */ + public static final IProperty MIN_X = new Property("MIN_X"); + public static final IProperty MAX_X = new Property("MAX_X"); + public static final IProperty MIN_Y = new Property("MIN_Y"); + public static final IProperty MAX_Y = new Property("MAX_Y"); } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk index 358ca31d42..b981f263f9 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk @@ -56,6 +56,7 @@ algorithm yconstree(YconstreeLayoutProvider) { supports org.eclipse.elk.nodeLabels.placement supports org.eclipse.elk.portLabels.placement supports verticalConstraint + supports org.eclipse.elk.margins } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java index 634e44d184..03cb84a116 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java @@ -17,9 +17,11 @@ public enum YconstreeLayoutPhases { //P1_TREECHECKING, /** Phase 2. */ P2_NODE_Y_PLACEMENT, - /** Phase 2. */ + /** Phase 3. */ P3_NODE_RELATIV_PLACEMENT, - /** Phase 2. */ - P4_NODE_ABSOLUTE_PLACEMENT; + /** Phase 4. */ + P4_NODE_ABSOLUTE_PLACEMENT, + /** Phase 4. */ + P5_EDGE_ROUTING; } \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java index 99e1d2a483..128b9cc9a8 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java @@ -15,6 +15,7 @@ import org.eclipse.elk.alg.yconstree.p2yplacement.NodeYPlacerStrategy; import org.eclipse.elk.alg.yconstree.p3relative.RelativeXPlacerStrategy; import org.eclipse.elk.alg.yconstree.p4absolute.AbsoluteXPlacerStrategy; +import org.eclipse.elk.alg.yconstree.p5edgerouting.EdgerouterStrategy; import org.eclipse.elk.core.AbstractLayoutProvider; import org.eclipse.elk.core.alg.AlgorithmAssembler; import org.eclipse.elk.core.alg.ILayoutProcessor; @@ -54,6 +55,8 @@ public List> assembleAlgorithm(ElkNode graph) { RelativeXPlacerStrategy.SIMPLE_XPLACING); algorithmAssembler.setPhase(YconstreeLayoutPhases.P4_NODE_ABSOLUTE_PLACEMENT, AbsoluteXPlacerStrategy.ABSOLUTE_XPLACING); + algorithmAssembler.setPhase(YconstreeLayoutPhases.P5_EDGE_ROUTING, + EdgerouterStrategy.DIRECT_ROUTING); // Assemble the algorithm return algorithmAssembler.build(graph); diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java index 32fbd35421..d434a3546c 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java @@ -16,27 +16,27 @@ public class OutlineNode { private double relativeX; - private double relativeY; + private double absoluteY; private OutlineNode next; - OutlineNode(double relativeX, double relativeY, OutlineNode next){ + OutlineNode(double relativeX, double absoluteY, OutlineNode next){ this.setRelativeX(relativeX); - this.setRelativeY(relativeY); + this.setAbsoluteY(absoluteY); this.setNext(next); } /** - * @return the relativeY + * @return the absoluteY */ - public double getRelativeY() { - return relativeY; + public double getAbsoluteY() { + return absoluteY; } /** - * @param relativeY the relativeY to set + * @param absoluteY the absoluteY to set */ - public void setRelativeY(double relativeY) { - this.relativeY = relativeY; + public void setAbsoluteY(double absoluteY) { + this.absoluteY = absoluteY; } /** @@ -71,7 +71,7 @@ public void setNext(OutlineNode next) { * @return a string representation of this objects relative coordinates */ public String toString() { - return "X:" + relativeX + ", Y:" + relativeY; + return "X:" + relativeX + ", Y:" + absoluteY; } /** diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java index c6023da7bc..9bf60f3810 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java @@ -32,6 +32,10 @@ public class RelativeXPlacer implements ILayoutPhase y2) { - dist = max(dist, (x1 + (y2 - y1) * o1.getNext().getRelativeX() / o1.getNext().getRelativeY()) - x2); - } - if (y2 <= y1 && y2 + o2.getNext().getRelativeY() > y1) { - dist = max(dist, x1 - (x2 + (y1 - y2) * o2.getNext().getRelativeX() / o2.getNext().getRelativeY())); - } - if (y2 + o2.getNext().getRelativeY() < y1 + o1.getNext().getRelativeY()) { - y2 += o2.getNext().getRelativeY(); - x2 += o2.getNext().getRelativeX(); - o2 = o2.getNext(); - minO2 = min(minO2, x2); - } else { - y1 += o1.getNext().getRelativeY(); - x1 += o1.getNext().getRelativeX(); + private double outlineDistance(OutlineNode outline1, OutlineNode outline2) { + + OutlineNode changed_outline1 = new OutlineNode(outline1.getRelativeX(), minimalY, outline1.getNext()); + OutlineNode changed_outline2 = new OutlineNode(outline2.getRelativeX(), minimalY, outline2.getNext()); + + // the return value + double dist = changed_outline1.getRelativeX() - changed_outline2.getRelativeX(); + + OutlineNode o1; + OutlineNode o2; + double x1; + double x2; + double deltaX, deltaY; + double newdist; + + + // fist run (compare points of o1 with o2) + o1 = changed_outline1; + o2 = changed_outline2; + x1 = o1.getRelativeX(); + x2 = o2.getRelativeX(); + while (o1 != null && !o2.isLast()) { + if (o2.getNext().getAbsoluteY() > o1.getAbsoluteY()) { + // now we compare + deltaX = o2.getNext().getRelativeX(); + deltaY = o2.getNext().getAbsoluteY() - o2.getAbsoluteY(); + newdist = x1 - x2 - ((o1.getAbsoluteY() - o2.getAbsoluteY()) * deltaX) / deltaY; + + dist = max(dist, newdist); + + // now change o1 o1 = o1.getNext(); - maxO1 = max(maxO1, x1); - } - } - if (!o1.isLast()){ - if (y1 <= y2 && y1 + o1.getNext().getRelativeY() > y2) { - dist = max(dist, (x1 + (y2 - y1) * o1.getNext().getRelativeX() / o1.getNext().getRelativeY()) - x2); + if (o1 != null) { + x1 += o1.getRelativeX(); + } } else { - if (UseMaxDisp){ - dist = max(dist,-minO2 + o1.getRelativeX()); - } + o2 = o2.getNext(); + x2 += o2.getRelativeX(); } - } - if (!o2.isLast()) { - if (y2 <= y1) { - dist = max(dist, x1 - (x2 + (y1 - y2) * o2.getNext().getRelativeX() / o2.getNext().getRelativeY())); + } + + // second run (compare points of o2 with o1) + o1 = changed_outline1; + o2 = changed_outline2; + x1 = o1.getRelativeX(); + x2 = o2.getRelativeX(); + while (o2 != null && !o1.isLast()) { + if (o1.getNext().getAbsoluteY() > o2.getAbsoluteY()) { + // now we compare + deltaX = o1.getNext().getRelativeX(); + deltaY = o1.getNext().getAbsoluteY() - o1.getAbsoluteY(); + newdist = x1 - x2 + ((o2.getAbsoluteY() - o1.getAbsoluteY()) * deltaX) / deltaY; + + dist = max(dist, newdist); + + // now change o2 + o2 = o2.getNext(); + if (o2 != null) { + x2 += o2.getRelativeX(); + } } else { - if (UseMaxDisp){ - dist = max(dist,maxO1); - } + o1 = o1.getNext(); + x1 += o1.getRelativeX(); } + } + return dist; } @@ -148,32 +172,19 @@ private void yConsTreeStep(ElkNode graph) { ElkMargin margins = graph.getProperty(CoreOptions.MARGINS); - // set the properties for left and right outlines - graph.setProperty(InternalProperties.LEFT_OUTLINE, new OutlineNode((-margins.left), (-margins.top), new OutlineNode(0.0, graph.getHeight() + margins.top + margins.bottom, null))); - graph.setProperty(InternalProperties.RIGHT_OUTLINE, new OutlineNode(graph.getWidth() + margins.right, -margins.top, new OutlineNode(0.0, graph.getHeight() + margins.top + margins.bottom, null))); - System.out.println(graph.getProperty(InternalProperties.RIGHT_OUTLINE)); - // checks if this node is a leaf - if (graph.getOutgoingEdges().isEmpty()) { - System.out.println("bin ein Blatt"); - graph.setProperty(InternalProperties.MAX_DEPTH, graph.getY() + graph.getHeight()); - graph.setX(0); - } else { - System.out.println("bin ein Knoten"); - graph.setProperty(InternalProperties.MAX_DEPTH, 0.0); - // create a list with references to all children of this node. + makeSimpelOutlines(graph); + + if (!graph.getOutgoingEdges().isEmpty()) { + + // get all children List children = new ArrayList<>(); for (int i = 0; i < graph.getOutgoingEdges().size(); i++) { ElkNode child = (ElkNode) graph.getOutgoingEdges().get(i).getTargets().get(0); yConsTreeStep(child); - graph.setProperty(InternalProperties.MAX_DEPTH, max((double) graph.getProperty(InternalProperties.MAX_DEPTH), (double) child.getProperty(InternalProperties.MAX_DEPTH))); - // ein Test - //graph.setX((double) graph.getProperty(MAX_DEPTH)); children.add(child); } - // now the children of this node get sorted to form a semi-circle. sortSubTrees(children); - System.out.println("bis hier klappts noch"); // now the children get stuffed together, using the outlines. for (int i = 0; i < children.size() - 1; i++) { @@ -181,6 +192,83 @@ private void yConsTreeStep(ElkNode graph) { } // now we need to move the root to the middle of the nodes. + // we calculate the point of the child with the lowest y-position to avoid overlapping. + // if there is more than one lowest child, the root will be positioned in the middle of them. + int pos = 0; + double maxDepth = 0.0; + int maxDepthStartPos = 0; + while (pos < children.size() && children.get(pos).getY() >= maxDepth) { + if (children.get(pos).getY() > maxDepth) { + maxDepthStartPos = pos; + maxDepth = children.get(pos).getY(); + } + pos += 1; + } + double moveRoot = 0.0; + if (pos > 0) { + moveRoot = (children.get(maxDepthStartPos).getX() + children.get(pos-1).getX() + children.get(pos-1).getWidth()) / 2.0 - graph.getX(); + } + + double betterMoveRoot = (children.get(0).getX() + children.get(children.size()-1).getX() + children.get(children.size()-1).getWidth() - graph.getWidth()) / 2.0 - graph.getX(); + double newMoveRoot; + + //if better moveRoote is left of moveRoot + if (betterMoveRoot < moveRoot) { + OutlineNode Rol; + double RolX, posX; + for (int i=0; i < maxDepthStartPos; i++) { + for (int j = i+1; j < maxDepthStartPos + 1; j++) { + Rol = children.get(i).getProperty(InternalProperties.RIGHT_OUTLINE); + RolX = children.get(i).getX() + Rol.getRelativeX(); + posX = children.get(j).getX() + children.get(j).getWidth() / 2.0; + while (Rol != null && Rol.getAbsoluteY() < maxDepth) { + // new moveRoot + newMoveRoot = posX - graph.getWidth() / 2.0 + (posX - RolX) * ((graph.getX() + graph.getHeight()) - maxDepth) / (maxDepth - Rol.getAbsoluteY()); + betterMoveRoot = max(betterMoveRoot, newMoveRoot); + + // update Rol and RolX + Rol = Rol.getNext(); + if (Rol != null) { + RolX += Rol.getRelativeX(); + } + } + } + } + moveRoot = betterMoveRoot; + } + + //if better moveRoote is right of moveRoot + if (betterMoveRoot > moveRoot) { + OutlineNode Lol; + double LolX, posX; + for (int i=pos; i < children.size(); i++) { + for (int j = pos-1; j < i; j++) { + Lol = children.get(i).getProperty(InternalProperties.LEFT_OUTLINE); + LolX = children.get(i).getX() + Lol.getRelativeX(); + posX = children.get(j).getX() + children.get(j).getWidth() / 2.0; + while (Lol != null && Lol.getAbsoluteY() < maxDepth) { + // new moveRoot + newMoveRoot = posX - graph.getWidth() / 2.0 + (posX - LolX) * ((graph.getX() + graph.getHeight()) - maxDepth) / (maxDepth - Lol.getAbsoluteY()); + betterMoveRoot = min(betterMoveRoot, newMoveRoot); + + // update Rol and RolX + Lol = Lol.getNext(); + if (Lol != null) { + LolX += Lol.getRelativeX(); + } + } + } + } + moveRoot = betterMoveRoot; + } + + for(ElkNode child: children) { + child.setX(child.getX() - moveRoot); + } + + /** + //------------------------------------------------------------------------- + // now we need to move the root to the middle of the nodes. // we calculate the point of the child with the lowest y-position to avoid overlapping. // if there is more than one lowest child, the root will be positioned in the middle of them. int lowestChildPos = 0; @@ -199,18 +287,30 @@ private void yConsTreeStep(ElkNode graph) { if (lowestChildPos > 0) { moveRoot = (children.get(lowestChildPos - 1).getX() + children.get(lowestChildPos - 1).getWidth() + lowestChildStart - graph.getWidth()) / 2 - graph.getX(); } + + // move children for(ElkNode child: children) { child.setX(child.getX() - moveRoot); } + //---------------------------------------------------------------------------- + **/ - // now we need to combine the outlines of the root with the outlines of the most outer children. - graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().setNext(new OutlineNode(-moveRoot, children.get(0).getY() - graph.getHeight() - graph.getY(), children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getNext())); - double newX = children.get(children.size() - 1).getX() + children.get(children.size() - 1).getWidth() - graph.getWidth(); - double newY = children.get(children.size() - 1).getY() - graph.getHeight() - graph.getY(); - OutlineNode newNext = children.get(children.size() - 1).getProperty(InternalProperties.RIGHT_OUTLINE).getNext(); - graph.getProperty(InternalProperties.RIGHT_OUTLINE).getNext().setNext(new OutlineNode(newX, newY, newNext)); - //**/ + double newX; + // lol update + newX = children.get(0).getX() + children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX() - graph.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(); + graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().setNext(new OutlineNode(newX, children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getAbsoluteY(), children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getNext())); + // rol update + newX = children.get(children.size()-1).getX() + children.get(children.size()-1).getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX() - graph.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(); + graph.getProperty(InternalProperties.RIGHT_OUTLINE).getNext().setNext(new OutlineNode(newX, children.get(children.size()-1).getProperty(InternalProperties.RIGHT_OUTLINE).getAbsoluteY(), children.get(children.size()-1).getProperty(InternalProperties.RIGHT_OUTLINE).getNext())); + // update outlineMaxY + // update min und max for x and y + for (ElkNode child: children) { + graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, max(graph.getProperty(InternalProperties.OUTLINE_MAX_DEPTH), child.getProperty(InternalProperties.OUTLINE_MAX_DEPTH))); + graph.setProperty(InternalProperties.MIN_X, min(graph.getProperty(InternalProperties.MIN_X), child.getX() + child.getProperty(InternalProperties.MIN_X))); + graph.setProperty(InternalProperties.MAX_X, max(graph.getProperty(InternalProperties.MAX_X), child.getX() + child.getProperty(InternalProperties.MAX_X))); + } + graph.setProperty(InternalProperties.MAX_Y, graph.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); } } @@ -247,75 +347,91 @@ private void sortSubTrees(List children) { } + + private void makeSimpelOutlines(ElkNode graph) { + ElkMargin margins = graph.getProperty(CoreOptions.MARGINS); + + // set the properties for left and right outlines + graph.setProperty(InternalProperties.LEFT_OUTLINE, new OutlineNode((-margins.left), graph.getY() - margins.top, new OutlineNode(0.0, graph.getY() + graph.getHeight() + margins.bottom, null))); + graph.setProperty(InternalProperties.RIGHT_OUTLINE, new OutlineNode(graph.getWidth() + margins.right, graph.getY() - margins.top, new OutlineNode(0.0, graph.getY() + graph.getHeight() + margins.bottom, null))); + + // set min and max values + graph.setProperty(InternalProperties.MIN_X, graph.getX() - margins.left); + graph.setProperty(InternalProperties.MAX_X, graph.getX() + margins.right + graph.getWidth()); + graph.setProperty(InternalProperties.MIN_Y, graph.getY() - margins.top); + graph.setProperty(InternalProperties.MAX_Y, graph.getY() + margins.bottom + graph.getHeight()); + graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().getAbsoluteY()); + + } + + private void putThemTogether(ElkNode leftSubtree, ElkNode a, ElkNode b) { + + double deltaX, deltaY, change; + // calculate distance between the two parts - double dist = outlineDistance(a.getProperty(InternalProperties.RIGHT_OUTLINE), a.getY(), b.getProperty(InternalProperties.LEFT_OUTLINE), b.getY(), true); + double dist = outlineDistance(a.getProperty(InternalProperties.RIGHT_OUTLINE), b.getProperty(InternalProperties.LEFT_OUTLINE)); b.setX(a.getX() + dist); - // update the left outline, if needed - if (leftSubtree.getProperty(InternalProperties.MAX_DEPTH) < b.getProperty(InternalProperties.MAX_DEPTH)) { - - // needed to calculate the position of the intercept between the two outlines. - OutlineNode leftSubtreeLast = leftSubtree.getProperty(InternalProperties.LEFT_OUTLINE); - double leftSubtreeX = leftSubtreeLast.getRelativeX(); + // enhance the left outline + if (leftSubtree.getProperty(InternalProperties.OUTLINE_MAX_DEPTH) < b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)) { + OutlineNode lastL = leftSubtree.getProperty(InternalProperties.LEFT_OUTLINE); + double LabsX = lastL.getRelativeX() + leftSubtree.getX(); - // jump to last position of the outline of leftSubtree - while (!leftSubtreeLast.isLast()) { - leftSubtreeLast = leftSubtreeLast.getNext(); - leftSubtreeX += leftSubtreeLast.getRelativeX(); + // move to the end of leftSubtree + while (!lastL.isLast()) { + lastL = lastL.getNext(); + LabsX += lastL.getRelativeX(); } - - // move on the outline of b to the position of the intercept. - OutlineNode bLolIterator = b.getProperty(InternalProperties.LEFT_OUTLINE); - double bAbsY = b.getY() + bLolIterator.getRelativeY(); - double bX = bLolIterator.getRelativeX(); - while (bAbsY < leftSubtree.getProperty(InternalProperties.MAX_DEPTH)) { - bLolIterator = bLolIterator.getNext(); - bAbsY += bLolIterator.getRelativeY(); - bX += bLolIterator.getRelativeX(); - } - double deltaY = b.getProperty(InternalProperties.MAX_DEPTH) - leftSubtree.getProperty(InternalProperties.MAX_DEPTH); - double deltaX = 0.0; - if (bLolIterator.getRelativeY() != 0.0) { - deltaX = bLolIterator.getRelativeX() * deltaY / bLolIterator.getRelativeY(); + // find fiting position in the lol of b + OutlineNode bItterator = new OutlineNode(b.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(), minimalY, b.getProperty(InternalProperties.LEFT_OUTLINE).getNext()); + double BabsX = bItterator.getRelativeX() + b.getX(); + while (bItterator.getNext().getAbsoluteY() <= lastL.getAbsoluteY()) { + bItterator = bItterator.getNext(); + BabsX += bItterator.getRelativeX(); } - double newX = b.getX() + bX - leftSubtreeX - deltaX; - leftSubtreeLast.setNext(new OutlineNode(newX, 0.0, new OutlineNode(deltaX, deltaY, bLolIterator.getNext()))); - leftSubtree.setProperty(InternalProperties.MAX_DEPTH, b.getProperty(InternalProperties.MAX_DEPTH)); - } - //** - // update the right outline, if needed - if (a.getProperty(InternalProperties.MAX_DEPTH) > b.getProperty(InternalProperties.MAX_DEPTH)) { - - // needed to calculate the position of the intercept between the two outlines. - OutlineNode bLast = b.getProperty(InternalProperties.RIGHT_OUTLINE); - double bX = bLast.getRelativeX(); + // now we calculate the change + deltaX = bItterator.getNext().getRelativeX(); + deltaY = bItterator.getNext().getAbsoluteY() - bItterator.getAbsoluteY(); + change = ((lastL.getAbsoluteY() - bItterator.getAbsoluteY()) * deltaX) / deltaY; - // jump to last position of the outline of b - while (!bLast.isLast()) { - bLast = bLast.getNext(); - bX += bLast.getRelativeX(); - } + // now we calculate the new points + double newX = -LabsX + BabsX + change; + OutlineNode newNext = new OutlineNode(bItterator.getNext().getRelativeX() - change, bItterator.getNext().getAbsoluteY(), bItterator.getNext().getNext()); + lastL.setNext(new OutlineNode(newX, lastL.getAbsoluteY(), newNext)); + // now update outline_max_depth + leftSubtree.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); + } + + // enhance the right outline + if (b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH) < a.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)) { + OutlineNode lastB = b.getProperty(InternalProperties.RIGHT_OUTLINE); + double BabsX = lastB.getRelativeX() + b.getX(); - // move on the outline of a to the position of the intercept. - OutlineNode aRolIterator = a.getProperty(InternalProperties.RIGHT_OUTLINE); - double aAbsY = a.getY() + aRolIterator.getRelativeY(); - double aX = aRolIterator.getRelativeX(); - while (aAbsY < b.getProperty(InternalProperties.MAX_DEPTH)) { - aRolIterator = aRolIterator.getNext(); - aAbsY += aRolIterator.getRelativeY(); - aX += aRolIterator.getRelativeX(); + // move to the end of b + while (!lastB.isLast()) { + lastB = lastB.getNext(); + BabsX += lastB.getRelativeX(); } - double deltaY = aAbsY - b.getProperty(InternalProperties.MAX_DEPTH); - double deltaX = 0.0; - if (aRolIterator.getRelativeY() != 0.0) { - deltaX = aRolIterator.getRelativeX() * deltaY / aRolIterator.getRelativeY(); + // find fitting position in the rol of a + OutlineNode aItterator = new OutlineNode(a.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(), minimalY, a.getProperty(InternalProperties.RIGHT_OUTLINE).getNext()); + double AabsX = aItterator.getRelativeX() + a.getX(); + while (aItterator.getNext().getAbsoluteY() <= lastB.getAbsoluteY()) { + aItterator = aItterator.getNext(); + AabsX += aItterator.getRelativeX(); } - double newX = aX + a.getX() - deltaX - bX - b.getX(); - bLast.setNext(new OutlineNode(newX, 0.0, new OutlineNode(deltaX, deltaY, aRolIterator.getNext()))); - b.setProperty(InternalProperties.MAX_DEPTH, a.getProperty(InternalProperties.MAX_DEPTH)); + // now we calculate the change + deltaX = aItterator.getNext().getRelativeX(); + deltaY = aItterator.getNext().getAbsoluteY() - aItterator.getAbsoluteY(); + change = ((lastB.getAbsoluteY() - aItterator.getAbsoluteY()) * deltaX) / deltaY; + + // now we calculate the new points + double newX = AabsX - BabsX + change; + OutlineNode newNext = new OutlineNode(aItterator.getNext().getRelativeX() - change, aItterator.getNext().getAbsoluteY(), aItterator.getNext().getNext()); + lastB.setNext(new OutlineNode(newX, lastB.getAbsoluteY(), newNext)); + // now update outline_max_depth + b.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, a.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); } - //**/ } /* (non-Javadoc) diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java index 062c3318a3..4e235c0ef0 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java @@ -38,6 +38,8 @@ public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { // first, move the root parent.setX(parent.getX() - findMinimalX(parent)); + // a little offset + parent.setX(parent.getX() + 10.0); // now we update the whole tree to absolute X absoluteTreeCoords(parent); } @@ -68,6 +70,8 @@ private double findMinimalX(ElkNode t) { private void absoluteTreeCoords(ElkNode t) { int numOfChildren = t.getOutgoingEdges().size(); + // a little offset + t.setY(t.getY() + 10.0); if (numOfChildren > 0) { ElkNode child; for (int i = 0; i < numOfChildren; i++) { diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java new file mode 100644 index 0000000000..2255e9c785 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java @@ -0,0 +1,88 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p5edgerouting; + +import org.eclipse.elk.alg.yconstree.InternalProperties; +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; +import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkEdge; +import org.eclipse.elk.graph.ElkEdgeSection; +import org.eclipse.elk.graph.ElkNode; +import org.eclipse.elk.graph.util.ElkGraphUtil; + +/** + * @author claas + * + */ +public class Edgerouter implements ILayoutPhase { + + private IElkProgressMonitor pm; + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) + */ + @Override + public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { + // TODO Auto-generated method stub + pm = progressMonitor; + pm.begin("EdgeRouter", 1); + + try { + if (!graph.getChildren().isEmpty()){ + ElkNode parent = graph.getChildren().get(0); + + routeEdges(parent); + setCanvas(graph); + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + pm.done(); + } + + /* (non-Javadoc) + * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) + */ + @Override + public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + // TODO Auto-generated method stub + return null; + } + + + + private void routeEdges(ElkNode node) { + for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(node)) { + ElkNode target = ElkGraphUtil.connectableShapeToNode(edge.getTargets().get(0)); + ElkEdgeSection section = ElkGraphUtil.firstEdgeSection(edge, true, true); + + + double startX = node.getX() + node.getWidth() / 2; + double startY = node.getY() + node.getHeight(); + double endX = target.getX() + target.getWidth() / 2; + double endY = target.getY(); + + section.setStartLocation(startX, startY); + section.setEndLocation(endX, endY); + routeEdges(target); + } + } + + private void setCanvas(ElkNode graph) { + ElkNode parent = graph.getChildren().get(0); + graph.setHeight(parent.getProperty(InternalProperties.MAX_Y) - parent.getProperty(InternalProperties.MIN_Y) + 20.0); + graph.setWidth(parent.getProperty(InternalProperties.MAX_X) - parent.getProperty(InternalProperties.MIN_X) + 20.0); + } + +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/EdgerouterStrategy.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/EdgerouterStrategy.java new file mode 100644 index 0000000000..c624c0c277 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/EdgerouterStrategy.java @@ -0,0 +1,38 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree.p5edgerouting; + +import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.alg.yconstree.p3relative.RelativeXPlacer; +import org.eclipse.elk.core.alg.ILayoutPhase; +import org.eclipse.elk.core.alg.ILayoutPhaseFactory; +import org.eclipse.elk.graph.ElkNode; + +/** + * @author claas + * + */ +public enum EdgerouterStrategy implements ILayoutPhaseFactory { + + DIRECT_ROUTING; + + @Override + public ILayoutPhase create() { + switch (this) { + case DIRECT_ROUTING: + return new Edgerouter(); + + default: + throw new IllegalArgumentException( + "No implementation is available for the node orderer " + this.toString()); + } + } + +} \ No newline at end of file From 93141390aef10b79b2a2e670d37b30277ff6fac3 Mon Sep 17 00:00:00 2001 From: ClaasN Date: Sat, 16 Sep 2023 22:35:31 +0200 Subject: [PATCH 03/45] ein paar checks --- .../elk/alg/yconstree/InternalProperties.java | 17 ++++++---- .../alg/yconstree/YconstreeLayoutPhases.java | 2 +- .../yconstree/YconstreeLayoutProvider.java | 18 +++++++++- .../elk/alg/yconstree/YconstreeUtil.java | 33 +++++++++++++++++++ .../yconstree/p1treechecking/TreeChecker.java | 23 ++++++++++++- .../yconstree/p2yplacement/NodeYPlacer.java | 3 +- .../yconstree/p3relative/RelativeXPlacer.java | 2 +- .../yconstree/p4absolute/AbsoluteXPlacer.java | 3 +- .../yconstree/p5edgerouting/Edgerouter.java | 2 +- 9 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeUtil.java diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java index 8dba8f9948..b2d1c8e576 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java @@ -12,6 +12,7 @@ import org.eclipse.elk.alg.yconstree.p3relative.OutlineNode; import org.eclipse.elk.core.options.CoreOptions; import org.eclipse.elk.core.options.PortConstraints; +import org.eclipse.elk.graph.ElkNode; import org.eclipse.elk.graph.properties.IProperty; import org.eclipse.elk.graph.properties.Property; @@ -19,7 +20,7 @@ * @author claas * */ -public class InternalProperties { +public final class InternalProperties { /** * Defines the left outline of this subtree. */ @@ -31,21 +32,25 @@ public class InternalProperties { public static final IProperty RIGHT_OUTLINE = new Property("RIGHT_OUTLINE"); /** - * Defines the maximum depth (as a coordinate) outdated + * Defines the maximum depth (as a coordinate) outdated. */ public static final IProperty MAX_DEPTH = new Property("MAX_DEPTH"); /** - * Defines the maximum depth of outlines + * Defines the maximum depth of outlines. */ public static final IProperty OUTLINE_MAX_DEPTH = new Property("OUTLINE_MAX_DEPTH"); - /** - * Defines the canvas of the tree - */ + /** Defines the canvas of the tree. */ public static final IProperty MIN_X = new Property("MIN_X"); + /** Defines the canvas of the tree. */ public static final IProperty MAX_X = new Property("MAX_X"); + /** Defines the canvas of the tree. */ public static final IProperty MIN_Y = new Property("MIN_Y"); + /** Defines the canvas of the tree. */ public static final IProperty MAX_Y = new Property("MAX_Y"); + + /** The root node of the graph. */ + public static final IProperty ROOT_NODE = new Property("root"); } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java index 03cb84a116..9a00572a39 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java @@ -14,7 +14,7 @@ public enum YconstreeLayoutPhases { /** Phase 1. */ - //P1_TREECHECKING, + P1_TREECHECKING, /** Phase 2. */ P2_NODE_Y_PLACEMENT, /** Phase 3. */ diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java index 128b9cc9a8..fbf81eeaa6 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java @@ -19,7 +19,6 @@ import org.eclipse.elk.core.AbstractLayoutProvider; import org.eclipse.elk.core.alg.AlgorithmAssembler; import org.eclipse.elk.core.alg.ILayoutProcessor; -import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; import org.eclipse.elk.core.util.IElkProgressMonitor; import org.eclipse.elk.graph.ElkNode; @@ -37,6 +36,21 @@ public void layout(ElkNode graph, IElkProgressMonitor progressMonitor) { List> algorithm = assembleAlgorithm(graph); progressMonitor.begin("Tree layout", algorithm.size()); + + // pre calculate the root node and save it + ElkNode root = YconstreeUtil.findRoot(graph); + graph.setProperty(InternalProperties.ROOT_NODE, root); + if (root == null) { + throw new IllegalArgumentException("The given graph is not a tree!"); + } + + for (ElkNode child : graph.getChildren()) { + int numberOfParents; + numberOfParents = child.getIncomingEdges().size(); + if (numberOfParents > 1) { + throw new IllegalArgumentException("The given graph is not an acyclic tree!"); + } + } for (ILayoutProcessor processor : algorithm) { processor.process(graph, progressMonitor.subTask(1)); @@ -49,6 +63,8 @@ public List> assembleAlgorithm(ElkNode graph) { algorithmAssembler.reset(); // Configure phases + algorithmAssembler.setPhase(YconstreeLayoutPhases.P1_TREECHECKING, + TreeCheckerStrategy.SIMPLE_TREECHECKING); algorithmAssembler.setPhase(YconstreeLayoutPhases.P2_NODE_Y_PLACEMENT, NodeYPlacerStrategy.SIMPLE_YPLACING); algorithmAssembler.setPhase(YconstreeLayoutPhases.P3_NODE_RELATIV_PLACEMENT, diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeUtil.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeUtil.java new file mode 100644 index 0000000000..7514fd35d9 --- /dev/null +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeUtil.java @@ -0,0 +1,33 @@ +/******************************************************************************* + * Copyright (c) 2023 claas and others. + * + * This program and the accompanying materials are made available under the + * terms of the Eclipse Public License 2.0 which is available at + * http://www.eclipse.org/legal/epl-2.0. + * + * SPDX-License-Identifier: EPL-2.0 + *******************************************************************************/ +package org.eclipse.elk.alg.yconstree; + +import org.eclipse.elk.graph.ElkEdge; +import org.eclipse.elk.graph.ElkNode; +import org.eclipse.elk.graph.util.ElkGraphUtil; + +/** A class for smaller, independent calculation units. */ +public final class YconstreeUtil { + + /** + * Computes the root node of a graph. + * @param graph + * @return Root node of graph. + */ + public static ElkNode findRoot(final ElkNode graph) { + for (ElkNode child : graph.getChildren()) { + Iterable incomingEdges = ElkGraphUtil.allIncomingEdges(child); + if (!incomingEdges.iterator().hasNext()) { + return child; + } + } + return null; + } +} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java index 54fb32800f..fecab39f10 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java @@ -9,25 +9,46 @@ *******************************************************************************/ package org.eclipse.elk.alg.yconstree.p1treechecking; +import org.eclipse.elk.alg.yconstree.InternalProperties; import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; import org.eclipse.elk.core.alg.ILayoutPhase; import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; import org.eclipse.elk.core.util.IElkProgressMonitor; +import org.eclipse.elk.graph.ElkEdge; import org.eclipse.elk.graph.ElkNode; +import org.eclipse.elk.graph.util.ElkGraphUtil; /** * @author claas * */ public class TreeChecker implements ILayoutPhase { - + + private IElkProgressMonitor pm; + /* (non-Javadoc) * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) */ @Override public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { // TODO Auto-generated method stub + pm = progressMonitor; + pm.begin("TreeChecker", 1); + + try { + if (!graph.getChildren().isEmpty()){ + ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); + + + int numberOfParents; + + } + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + pm.done(); } /* (non-Javadoc) diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java index 63cb6541d1..45ab0058bb 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java @@ -9,6 +9,7 @@ *******************************************************************************/ package org.eclipse.elk.alg.yconstree.p2yplacement; +import org.eclipse.elk.alg.yconstree.InternalProperties; import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; import org.eclipse.elk.alg.yconstree.options.YconstreeOptions; import org.eclipse.elk.core.alg.ILayoutPhase; @@ -36,7 +37,7 @@ public void process(final ElkNode graph, IElkProgressMonitor progressMonitor) { try { if (!graph.getChildren().isEmpty()){ - ElkNode parent = graph.getChildren().get(0); + ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); setYLevels(parent,0.0); } } catch (Exception e) { diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java index 9bf60f3810..a88150cd8e 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java @@ -49,7 +49,7 @@ public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { try { if (!graph.getChildren().isEmpty()){ - ElkNode parent = graph.getChildren().get(0); + ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); yConsTreeStep(parent); // for debugging: print outlines diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java index 4e235c0ef0..e66a7bc199 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java @@ -9,6 +9,7 @@ *******************************************************************************/ package org.eclipse.elk.alg.yconstree.p4absolute; +import org.eclipse.elk.alg.yconstree.InternalProperties; import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; import org.eclipse.elk.core.alg.ILayoutPhase; import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; @@ -34,7 +35,7 @@ public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { try { if (!graph.getChildren().isEmpty()){ - ElkNode parent = graph.getChildren().get(0); + ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); // first, move the root parent.setX(parent.getX() - findMinimalX(parent)); diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java index 2255e9c785..7e0f2a4dd3 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java @@ -38,7 +38,7 @@ public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { try { if (!graph.getChildren().isEmpty()){ - ElkNode parent = graph.getChildren().get(0); + ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); routeEdges(parent); setCanvas(graph); From b7394d8fc7b2ae46c7c4b2614a508d3f679c466a Mon Sep 17 00:00:00 2001 From: ClaasN Date: Mon, 2 Oct 2023 04:23:29 +0200 Subject: [PATCH 04/45] neuere version aufs gitlab bringen --- .../elk/alg/yconstree/InternalProperties.java | 7 +- .../eclipse/elk/alg/yconstree/Yconstree.melk | 8 + .../alg/yconstree/YconstreeLayoutPhases.java | 10 +- .../yconstree/YconstreeLayoutProvider.java | 11 +- .../yconstree/p1treechecking/TreeChecker.java | 63 ---- .../p1treechecking/TreeCheckerStrategy.java | 37 --- .../yconstree/p2yplacement/NodeYPlacer.java | 15 +- .../alg/yconstree/p3relative/OutlineNode.java | 13 +- .../yconstree/p3relative/RelativeXPlacer.java | 311 ++++++++++++------ .../yconstree/p4absolute/AbsoluteXPlacer.java | 4 +- .../yconstree/p5edgerouting/Edgerouter.java | 24 +- 11 files changed, 267 insertions(+), 236 deletions(-) delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java index b2d1c8e576..1cf6b0fd3f 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/InternalProperties.java @@ -52,5 +52,10 @@ public final class InternalProperties { /** The root node of the graph. */ public static final IProperty ROOT_NODE = new Property("root"); - + + /** + * Defines the bendpoint of an edge. + */ + public static final IProperty EDGE_BEND_HEIGHT = new Property("EDGE_BEND_HEIGHT"); + } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk index b981f263f9..338ada49db 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk @@ -56,6 +56,7 @@ algorithm yconstree(YconstreeLayoutProvider) { supports org.eclipse.elk.nodeLabels.placement supports org.eclipse.elk.portLabels.placement supports verticalConstraint + supports layoutStrategy supports org.eclipse.elk.margins } @@ -64,3 +65,10 @@ option verticalConstraint: double { label "Fixed vertical position" targets nodes } + + +option layoutStrategy: String { + label "Strategy for the layout of it's children. 'straight' for straight line drawings, 'bend' for a possible bend" + targets nodes +} + diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java index 9a00572a39..0647e33165 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java @@ -14,14 +14,12 @@ public enum YconstreeLayoutPhases { /** Phase 1. */ - P1_TREECHECKING, + P1_NODE_Y_PLACEMENT, /** Phase 2. */ - P2_NODE_Y_PLACEMENT, + P2_NODE_RELATIV_PLACEMENT, /** Phase 3. */ - P3_NODE_RELATIV_PLACEMENT, + P3_NODE_ABSOLUTE_PLACEMENT, /** Phase 4. */ - P4_NODE_ABSOLUTE_PLACEMENT, - /** Phase 4. */ - P5_EDGE_ROUTING; + P4_EDGE_ROUTING; } \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java index fbf81eeaa6..cb15c0b7af 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java @@ -11,7 +11,6 @@ import java.util.List; -import org.eclipse.elk.alg.yconstree.p1treechecking.TreeCheckerStrategy; import org.eclipse.elk.alg.yconstree.p2yplacement.NodeYPlacerStrategy; import org.eclipse.elk.alg.yconstree.p3relative.RelativeXPlacerStrategy; import org.eclipse.elk.alg.yconstree.p4absolute.AbsoluteXPlacerStrategy; @@ -63,15 +62,13 @@ public List> assembleAlgorithm(ElkNode graph) { algorithmAssembler.reset(); // Configure phases - algorithmAssembler.setPhase(YconstreeLayoutPhases.P1_TREECHECKING, - TreeCheckerStrategy.SIMPLE_TREECHECKING); - algorithmAssembler.setPhase(YconstreeLayoutPhases.P2_NODE_Y_PLACEMENT, + algorithmAssembler.setPhase(YconstreeLayoutPhases.P1_NODE_Y_PLACEMENT, NodeYPlacerStrategy.SIMPLE_YPLACING); - algorithmAssembler.setPhase(YconstreeLayoutPhases.P3_NODE_RELATIV_PLACEMENT, + algorithmAssembler.setPhase(YconstreeLayoutPhases.P2_NODE_RELATIV_PLACEMENT, RelativeXPlacerStrategy.SIMPLE_XPLACING); - algorithmAssembler.setPhase(YconstreeLayoutPhases.P4_NODE_ABSOLUTE_PLACEMENT, + algorithmAssembler.setPhase(YconstreeLayoutPhases.P3_NODE_ABSOLUTE_PLACEMENT, AbsoluteXPlacerStrategy.ABSOLUTE_XPLACING); - algorithmAssembler.setPhase(YconstreeLayoutPhases.P5_EDGE_ROUTING, + algorithmAssembler.setPhase(YconstreeLayoutPhases.P4_EDGE_ROUTING, EdgerouterStrategy.DIRECT_ROUTING); // Assemble the algorithm diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java deleted file mode 100644 index fecab39f10..0000000000 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeChecker.java +++ /dev/null @@ -1,63 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 claas and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ -package org.eclipse.elk.alg.yconstree.p1treechecking; - -import org.eclipse.elk.alg.yconstree.InternalProperties; -import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; -import org.eclipse.elk.core.alg.ILayoutPhase; -import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; -import org.eclipse.elk.core.util.IElkProgressMonitor; -import org.eclipse.elk.graph.ElkEdge; -import org.eclipse.elk.graph.ElkNode; -import org.eclipse.elk.graph.util.ElkGraphUtil; - -/** - * @author claas - * - */ -public class TreeChecker implements ILayoutPhase { - - private IElkProgressMonitor pm; - - /* (non-Javadoc) - * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) - */ - @Override - public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { - // TODO Auto-generated method stub - pm = progressMonitor; - pm.begin("TreeChecker", 1); - - try { - if (!graph.getChildren().isEmpty()){ - ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); - - - int numberOfParents; - - } - } catch (Exception e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - - pm.done(); - } - - /* (non-Javadoc) - * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) - */ - @Override - public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { - // TODO Auto-generated method stub - return null; - } - -} diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java deleted file mode 100644 index a7e183d7e8..0000000000 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p1treechecking/TreeCheckerStrategy.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2023 claas and others. - * - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ -package org.eclipse.elk.alg.yconstree.p1treechecking; - -import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; -import org.eclipse.elk.core.alg.ILayoutPhase; -import org.eclipse.elk.core.alg.ILayoutPhaseFactory; -import org.eclipse.elk.graph.ElkNode; - -/** - * @author claas - * - */ -public enum TreeCheckerStrategy implements ILayoutPhaseFactory { - - SIMPLE_TREECHECKING; - - @Override - public ILayoutPhase create() { - switch (this) { - case SIMPLE_TREECHECKING: - return new TreeChecker(); - - default: - throw new IllegalArgumentException( - "No implementation is available for the node orderer " + this.toString()); - } - } - -} \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java index 45ab0058bb..8d0e3ec1a2 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java @@ -25,20 +25,18 @@ public class NodeYPlacer implements ILayoutPhase private final double STANDARD_DISTANCE = 50.0; private IElkProgressMonitor pm; - /* (non-Javadoc) - * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) - */ + @Override - public void process(final ElkNode graph, IElkProgressMonitor progressMonitor) { + public void process(final ElkNode graph, final IElkProgressMonitor progressMonitor) { // TODO Auto-generated method stub //elkGraph.setX(0.0); pm = progressMonitor; pm.begin("YPlacer", 1); try { - if (!graph.getChildren().isEmpty()){ + if (!graph.getChildren().isEmpty()) { ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); - setYLevels(parent,0.0); + setYLevels(parent, 0.0); } } catch (Exception e) { // TODO Auto-generated catch block @@ -54,7 +52,7 @@ public void process(final ElkNode graph, IElkProgressMonitor progressMonitor) { * @param node and it's children are getting updated Y-coords. * @param minHeight: Node gets minimum this height. */ - private void setYLevels(ElkNode node, double minHeight) { + private void setYLevels(final ElkNode node, double minHeight) { // TODO: Y-Level_Constraints, remove different heightlevels. if (node.hasProperty(YconstreeOptions.VERTICAL_CONSTRAINT)) { pm.log("hier hab ich einen Constraint"); @@ -73,7 +71,8 @@ private void setYLevels(ElkNode node, double minHeight) { * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) */ @Override - public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + public LayoutProcessorConfiguration + getLayoutProcessorConfiguration(final ElkNode graph) { // TODO Auto-generated method stub return null; } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java index d434a3546c..a2fb12aca6 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java @@ -19,7 +19,7 @@ public class OutlineNode { private double absoluteY; private OutlineNode next; - OutlineNode(double relativeX, double absoluteY, OutlineNode next){ + OutlineNode(final double relativeX, final double absoluteY, final OutlineNode next){ this.setRelativeX(relativeX); this.setAbsoluteY(absoluteY); this.setNext(next); @@ -35,7 +35,7 @@ public double getAbsoluteY() { /** * @param absoluteY the absoluteY to set */ - public void setAbsoluteY(double absoluteY) { + public void setAbsoluteY(final double absoluteY) { this.absoluteY = absoluteY; } @@ -49,7 +49,7 @@ public double getRelativeX() { /** * @param relativeX the relativeX to set */ - public void setRelativeX(double relativeX) { + public void setRelativeX(final double relativeX) { this.relativeX = relativeX; } @@ -63,7 +63,7 @@ public OutlineNode getNext() { /** * @param next the next to set */ - public void setNext(OutlineNode next) { + public void setNext(final OutlineNode next) { this.next = next; } @@ -82,9 +82,12 @@ public boolean isLast() { return next == null; } + /** + * Print a full outline + */ public void printFullOutline() { System.out.println(this.toString()); - if(!this.isLast()) { + if (!this.isLast()) { this.getNext().printFullOutline(); } } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java index a88150cd8e..d3195055bb 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java @@ -15,6 +15,7 @@ import org.eclipse.elk.alg.yconstree.InternalProperties; import org.eclipse.elk.alg.yconstree.YconstreeLayoutPhases; +import org.eclipse.elk.alg.yconstree.options.YconstreeOptions; import org.eclipse.elk.core.alg.ILayoutPhase; import org.eclipse.elk.core.alg.LayoutProcessorConfiguration; import org.eclipse.elk.core.math.ElkMargin; @@ -40,7 +41,7 @@ public class RelativeXPlacer implements ILayoutPhase e ? d : e; } @@ -168,7 +176,7 @@ private double max(double d, double e) { * This is the recursive function that calculates the layout for one node and it's children. * @param graph */ - private void yConsTreeStep(ElkNode graph) { + private void yConsTreeStep(final ElkNode graph) { ElkMargin margins = graph.getProperty(CoreOptions.MARGINS); @@ -188,7 +196,7 @@ private void yConsTreeStep(ElkNode graph) { // now the children get stuffed together, using the outlines. for (int i = 0; i < children.size() - 1; i++) { - putThemTogether(children.get(0), children.get(i), children.get(i + 1)); + bundleChildren(children.get(0), children.get(i), children.get(i + 1)); } // now we need to move the root to the middle of the nodes. @@ -206,30 +214,33 @@ private void yConsTreeStep(ElkNode graph) { } double moveRoot = 0.0; if (pos > 0) { - moveRoot = (children.get(maxDepthStartPos).getX() + children.get(pos-1).getX() + children.get(pos-1).getWidth()) / 2.0 - graph.getX(); + moveRoot = (children.get(maxDepthStartPos).getX() + children.get(pos - 1).getX() + + children.get(pos - 1).getWidth()) / 2.0 - graph.getX(); } - double betterMoveRoot = (children.get(0).getX() + children.get(children.size()-1).getX() + children.get(children.size()-1).getWidth() - graph.getWidth()) / 2.0 - graph.getX(); + double betterMoveRoot = (children.get(0).getX() + children.get(children.size() - 1).getX() + + children.get(children.size() - 1).getWidth() - graph.getWidth()) / 2.0 - graph.getX(); double newMoveRoot; //if better moveRoote is left of moveRoot if (betterMoveRoot < moveRoot) { - OutlineNode Rol; - double RolX, posX; - for (int i=0; i < maxDepthStartPos; i++) { - for (int j = i+1; j < maxDepthStartPos + 1; j++) { - Rol = children.get(i).getProperty(InternalProperties.RIGHT_OUTLINE); - RolX = children.get(i).getX() + Rol.getRelativeX(); + OutlineNode rol; + double rolX, posX; + for (int i = 0; i < maxDepthStartPos; i++) { + for (int j = i + 1; j < maxDepthStartPos + 1; j++) { + rol = children.get(i).getProperty(InternalProperties.RIGHT_OUTLINE); + rolX = children.get(i).getX() + rol.getRelativeX(); posX = children.get(j).getX() + children.get(j).getWidth() / 2.0; - while (Rol != null && Rol.getAbsoluteY() < maxDepth) { + while (rol != null && rol.getAbsoluteY() < maxDepth) { // new moveRoot - newMoveRoot = posX - graph.getWidth() / 2.0 + (posX - RolX) * ((graph.getX() + graph.getHeight()) - maxDepth) / (maxDepth - Rol.getAbsoluteY()); + newMoveRoot = posX - graph.getWidth() / 2.0 + (posX - rolX) * ((graph.getY() + + graph.getHeight()) - maxDepth) / (maxDepth - rol.getAbsoluteY()); betterMoveRoot = max(betterMoveRoot, newMoveRoot); // update Rol and RolX - Rol = Rol.getNext(); - if (Rol != null) { - RolX += Rol.getRelativeX(); + rol = rol.getNext(); + if (rol != null) { + rolX += rol.getRelativeX(); } } } @@ -239,22 +250,23 @@ private void yConsTreeStep(ElkNode graph) { //if better moveRoote is right of moveRoot if (betterMoveRoot > moveRoot) { - OutlineNode Lol; - double LolX, posX; - for (int i=pos; i < children.size(); i++) { - for (int j = pos-1; j < i; j++) { - Lol = children.get(i).getProperty(InternalProperties.LEFT_OUTLINE); - LolX = children.get(i).getX() + Lol.getRelativeX(); + OutlineNode lol; + double lolX, posX; + for (int i = pos; i < children.size(); i++) { + for (int j = pos - 1; j < i; j++) { + lol = children.get(i).getProperty(InternalProperties.LEFT_OUTLINE); + lolX = children.get(i).getX() + lol.getRelativeX(); posX = children.get(j).getX() + children.get(j).getWidth() / 2.0; - while (Lol != null && Lol.getAbsoluteY() < maxDepth) { + while (lol != null && lol.getAbsoluteY() < maxDepth) { // new moveRoot - newMoveRoot = posX - graph.getWidth() / 2.0 + (posX - LolX) * ((graph.getX() + graph.getHeight()) - maxDepth) / (maxDepth - Lol.getAbsoluteY()); + newMoveRoot = posX - graph.getWidth() / 2.0 + (posX - lolX) * ((graph.getY() + + graph.getHeight()) - maxDepth) / (maxDepth - lol.getAbsoluteY()); betterMoveRoot = min(betterMoveRoot, newMoveRoot); // update Rol and RolX - Lol = Lol.getNext(); - if (Lol != null) { - LolX += Lol.getRelativeX(); + lol = lol.getNext(); + if (lol != null) { + lolX += lol.getRelativeX(); } } } @@ -262,64 +274,151 @@ private void yConsTreeStep(ElkNode graph) { moveRoot = betterMoveRoot; } - for(ElkNode child: children) { + for (ElkNode child: children) { child.setX(child.getX() - moveRoot); } - /** - //------------------------------------------------------------------------- - // now we need to move the root to the middle of the nodes. - // we calculate the point of the child with the lowest y-position to avoid overlapping. - // if there is more than one lowest child, the root will be positioned in the middle of them. - int lowestChildPos = 0; - double lowestChildY = 0.0; - double lowestChildStart = 0.0; - //** - while (lowestChildPos < children.size() && children.get(lowestChildPos).getY() >= lowestChildY) { - if (children.get(lowestChildPos).getY() > lowestChildY) { - lowestChildStart = children.get(lowestChildPos).getX(); - lowestChildY = children.get(lowestChildPos).getY(); - } - lowestChildPos++; + + double newX; + // lol update + newX = children.get(0).getX() + children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX() + - graph.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(); + graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().getNext().getNext().setNext( + new OutlineNode(newX, children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getAbsoluteY(), + children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getNext())); + // rol update + newX = children.get(children.size() - 1).getX() + + children.get(children.size() - 1).getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX() + - graph.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(); + graph.getProperty(InternalProperties.RIGHT_OUTLINE).getNext().getNext().getNext().setNext( + new OutlineNode(newX, children.get(children.size() - 1).getProperty( + InternalProperties.RIGHT_OUTLINE).getAbsoluteY(), children.get(children.size() - 1). + getProperty(InternalProperties.RIGHT_OUTLINE).getNext())); + + // update outlineMaxY + // update min und max for x and y + for (ElkNode child: children) { + graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, max(graph.getProperty(InternalProperties. + OUTLINE_MAX_DEPTH), child.getProperty(InternalProperties.OUTLINE_MAX_DEPTH))); + graph.setProperty(InternalProperties.MIN_X, min(graph.getProperty(InternalProperties.MIN_X), + child.getX() + child.getProperty(InternalProperties.MIN_X))); + graph.setProperty(InternalProperties.MAX_X, max(graph.getProperty(InternalProperties.MAX_X), + child.getX() + child.getProperty(InternalProperties.MAX_X))); } + graph.setProperty(InternalProperties.MAX_Y, graph.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); - double moveRoot = 0.0; - if (lowestChildPos > 0) { - moveRoot = (children.get(lowestChildPos - 1).getX() + children.get(lowestChildPos - 1).getWidth() + lowestChildStart - graph.getWidth()) / 2 - graph.getX(); + } + } + + + + private void alternativeYConsTreeStep(final ElkNode graph) { + ElkMargin margins = graph.getProperty(CoreOptions.MARGINS); + + makeSimpelOutlines(graph); + + if (!graph.getOutgoingEdges().isEmpty()) { + + // get all children + List children = new ArrayList<>(); + for (int i = 0; i < graph.getOutgoingEdges().size(); i++) { + ElkNode child = (ElkNode) graph.getOutgoingEdges().get(i).getTargets().get(0); + alternativeYConsTreeStep(child); + children.add(child); + } + + int cs = children.size(); + + + // now the children get stuffed together, using the outlines. + for (int i = 0; i < children.size() - 1; i++) { + bundleChildren(children.get(0), children.get(i), children.get(i + 1)); } - // move children - for(ElkNode child: children) { + double moveRoot = (children.get(0).getX() + children.get(0).getWidth() / 2.0 + + children.get(children.size() - 1).getX() + children.get(children.size() - 1).getWidth() / 2.0 + - graph.getWidth()) / 2.0 - graph.getX(); + + for (ElkNode child: children) { child.setX(child.getX() - moveRoot); + child.setProperty(InternalProperties.EDGE_BEND_HEIGHT, + child.getProperty(InternalProperties.LEFT_OUTLINE).getAbsoluteY()); + } + + // set bendHeights for children right of the parent + int i = 0; + while (i < cs - 1 && children.get(i).getX() + children.get(i).getWidth() + + children.get(i).getProperty(CoreOptions.MARGINS).right - graph.getWidth() / 2.0 <= 0.0) { + i++; + } + + double globalBendHeight = children.get(i).getProperty(InternalProperties.EDGE_BEND_HEIGHT); + for (int a = 0; a < cs; a++) { + if (globalBendHeight < children.get(a).getProperty(InternalProperties.EDGE_BEND_HEIGHT)) { + children.get(a).setProperty(InternalProperties.EDGE_BEND_HEIGHT, globalBendHeight); + } else { + globalBendHeight = children.get(a).getProperty(InternalProperties.EDGE_BEND_HEIGHT); + } + } + + // set bendHeights for children left of the parent + i = cs - 1; + while (i > 0 && children.get(i).getX() - children.get(i).getProperty(CoreOptions.MARGINS).left + - graph.getWidth() / 2.0 >= 0.0) { + i--; + } + + if (i < cs) { + for (int a = i; a >= 0; a--) { + + if (globalBendHeight < children.get(a).getProperty(InternalProperties.EDGE_BEND_HEIGHT)) { + children.get(a).setProperty(InternalProperties.EDGE_BEND_HEIGHT, globalBendHeight); + } else { + globalBendHeight = children.get(a).getProperty(InternalProperties.EDGE_BEND_HEIGHT); + } + } } - //---------------------------------------------------------------------------- - **/ double newX; + OutlineNode newOutlinepart; // lol update - newX = children.get(0).getX() + children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX() - graph.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(); - graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().setNext(new OutlineNode(newX, children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getAbsoluteY(), children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getNext())); - // rol update - newX = children.get(children.size()-1).getX() + children.get(children.size()-1).getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX() - graph.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(); - graph.getProperty(InternalProperties.RIGHT_OUTLINE).getNext().setNext(new OutlineNode(newX, children.get(children.size()-1).getProperty(InternalProperties.RIGHT_OUTLINE).getAbsoluteY(), children.get(children.size()-1).getProperty(InternalProperties.RIGHT_OUTLINE).getNext())); + newX = children.get(0).getX() + children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX() + - graph.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(); + newOutlinepart = new OutlineNode(0.0, children.get(0).getProperty(InternalProperties.LEFT_OUTLINE) + .getAbsoluteY(), children.get(0).getProperty(InternalProperties.LEFT_OUTLINE).getNext()); + graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().getNext().getNext() + .setNext(new OutlineNode(newX, children.get(0).getProperty(InternalProperties.EDGE_BEND_HEIGHT), + newOutlinepart)); + + newX = children.get(cs - 1).getX() + children.get(cs - 1).getProperty(InternalProperties.RIGHT_OUTLINE) + .getRelativeX() - graph.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(); + newOutlinepart = new OutlineNode(0.0, children.get(cs - 1).getProperty(InternalProperties.RIGHT_OUTLINE) + .getAbsoluteY(), children.get(cs - 1).getProperty(InternalProperties.RIGHT_OUTLINE).getNext()); + graph.getProperty(InternalProperties.RIGHT_OUTLINE).getNext().getNext().getNext() + .setNext(new OutlineNode(newX, children.get(cs - 1).getProperty(InternalProperties + .EDGE_BEND_HEIGHT), newOutlinepart)); // update outlineMaxY // update min und max for x and y for (ElkNode child: children) { - graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, max(graph.getProperty(InternalProperties.OUTLINE_MAX_DEPTH), child.getProperty(InternalProperties.OUTLINE_MAX_DEPTH))); - graph.setProperty(InternalProperties.MIN_X, min(graph.getProperty(InternalProperties.MIN_X), child.getX() + child.getProperty(InternalProperties.MIN_X))); - graph.setProperty(InternalProperties.MAX_X, max(graph.getProperty(InternalProperties.MAX_X), child.getX() + child.getProperty(InternalProperties.MAX_X))); + graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, max(graph.getProperty(InternalProperties + .OUTLINE_MAX_DEPTH), child.getProperty(InternalProperties.OUTLINE_MAX_DEPTH))); + graph.setProperty(InternalProperties.MIN_X, min(graph.getProperty(InternalProperties.MIN_X), + child.getX() + child.getProperty(InternalProperties.MIN_X))); + graph.setProperty(InternalProperties.MAX_X, max(graph.getProperty(InternalProperties.MAX_X), + child.getX() + child.getProperty(InternalProperties.MAX_X))); } graph.setProperty(InternalProperties.MAX_Y, graph.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); } + } /** * sorts the subTrees in a half circle, uses mergesort. * @param graph */ - private void sortSubTrees(List children) { + private void sortSubTrees(final List children) { // fist, we sort the SubTrees by the Y-coordinate of their root. Collections.sort(children, new NodeComparator()); @@ -348,47 +447,60 @@ private void sortSubTrees(List children) { } - private void makeSimpelOutlines(ElkNode graph) { + private void makeSimpelOutlines(final ElkNode graph) { ElkMargin margins = graph.getProperty(CoreOptions.MARGINS); // set the properties for left and right outlines - graph.setProperty(InternalProperties.LEFT_OUTLINE, new OutlineNode((-margins.left), graph.getY() - margins.top, new OutlineNode(0.0, graph.getY() + graph.getHeight() + margins.bottom, null))); - graph.setProperty(InternalProperties.RIGHT_OUTLINE, new OutlineNode(graph.getWidth() + margins.right, graph.getY() - margins.top, new OutlineNode(0.0, graph.getY() + graph.getHeight() + margins.bottom, null))); + OutlineNode endpart; + endpart = new OutlineNode(0.0, graph.getY() + graph.getHeight() + margins.bottom, + new OutlineNode(graph.getWidth() / 2.0, graph.getY() + graph.getHeight() + margins.bottom, null)); + graph.setProperty(InternalProperties.LEFT_OUTLINE, new OutlineNode((-margins.left) + + graph.getWidth() / 2.0, graph.getY() - margins.top, new OutlineNode(-graph.getWidth() / 2.0, + graph.getY() - margins.top, endpart))); + endpart = new OutlineNode(0.0, graph.getY() + graph.getHeight() + margins.bottom, new OutlineNode( + -graph.getWidth() / 2.0, graph.getY() + graph.getHeight() + margins.bottom, null)); + graph.setProperty(InternalProperties.RIGHT_OUTLINE, new OutlineNode(graph.getWidth() / 2.0 + + margins.right, graph.getY() - margins.top, new OutlineNode(graph.getWidth() / 2.0, graph.getY() + - margins.top, endpart))); // set min and max values graph.setProperty(InternalProperties.MIN_X, graph.getX() - margins.left); graph.setProperty(InternalProperties.MAX_X, graph.getX() + margins.right + graph.getWidth()); graph.setProperty(InternalProperties.MIN_Y, graph.getY() - margins.top); graph.setProperty(InternalProperties.MAX_Y, graph.getY() + margins.bottom + graph.getHeight()); - graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, graph.getProperty(InternalProperties.LEFT_OUTLINE).getNext().getAbsoluteY()); + graph.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, graph.getProperty(InternalProperties.LEFT_OUTLINE) + .getNext().getNext().getAbsoluteY()); } - private void putThemTogether(ElkNode leftSubtree, ElkNode a, ElkNode b) { + private void bundleChildren(final ElkNode leftSubtree, final ElkNode a, final ElkNode b) { double deltaX, deltaY, change; // calculate distance between the two parts - double dist = outlineDistance(a.getProperty(InternalProperties.RIGHT_OUTLINE), b.getProperty(InternalProperties.LEFT_OUTLINE)); + double dist = outlineDistance(a.getProperty(InternalProperties.RIGHT_OUTLINE), + b.getProperty(InternalProperties.LEFT_OUTLINE)); b.setX(a.getX() + dist); // enhance the left outline - if (leftSubtree.getProperty(InternalProperties.OUTLINE_MAX_DEPTH) < b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)) { + if (leftSubtree.getProperty(InternalProperties.OUTLINE_MAX_DEPTH) + < b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)) { OutlineNode lastL = leftSubtree.getProperty(InternalProperties.LEFT_OUTLINE); - double LabsX = lastL.getRelativeX() + leftSubtree.getX(); + double lAbsX = lastL.getRelativeX() + leftSubtree.getX(); // move to the end of leftSubtree while (!lastL.isLast()) { lastL = lastL.getNext(); - LabsX += lastL.getRelativeX(); + lAbsX += lastL.getRelativeX(); } // find fiting position in the lol of b - OutlineNode bItterator = new OutlineNode(b.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(), minimalY, b.getProperty(InternalProperties.LEFT_OUTLINE).getNext()); - double BabsX = bItterator.getRelativeX() + b.getX(); + OutlineNode bItterator = new OutlineNode(b.getProperty(InternalProperties.LEFT_OUTLINE).getRelativeX(), + minimalY, b.getProperty(InternalProperties.LEFT_OUTLINE).getNext()); + double rAbsX = bItterator.getRelativeX() + b.getX(); while (bItterator.getNext().getAbsoluteY() <= lastL.getAbsoluteY()) { bItterator = bItterator.getNext(); - BabsX += bItterator.getRelativeX(); + rAbsX += bItterator.getRelativeX(); } // now we calculate the change deltaX = bItterator.getNext().getRelativeX(); @@ -396,29 +508,32 @@ private void putThemTogether(ElkNode leftSubtree, ElkNode a, ElkNode b) { change = ((lastL.getAbsoluteY() - bItterator.getAbsoluteY()) * deltaX) / deltaY; // now we calculate the new points - double newX = -LabsX + BabsX + change; - OutlineNode newNext = new OutlineNode(bItterator.getNext().getRelativeX() - change, bItterator.getNext().getAbsoluteY(), bItterator.getNext().getNext()); + double newX = -lAbsX + rAbsX + change; + OutlineNode newNext = new OutlineNode(bItterator.getNext().getRelativeX() - change, bItterator.getNext() + .getAbsoluteY(), bItterator.getNext().getNext()); lastL.setNext(new OutlineNode(newX, lastL.getAbsoluteY(), newNext)); // now update outline_max_depth - leftSubtree.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); + leftSubtree.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, + b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); } // enhance the right outline if (b.getProperty(InternalProperties.OUTLINE_MAX_DEPTH) < a.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)) { OutlineNode lastB = b.getProperty(InternalProperties.RIGHT_OUTLINE); - double BabsX = lastB.getRelativeX() + b.getX(); + double rAbsX = lastB.getRelativeX() + b.getX(); // move to the end of b while (!lastB.isLast()) { lastB = lastB.getNext(); - BabsX += lastB.getRelativeX(); + rAbsX += lastB.getRelativeX(); } // find fitting position in the rol of a - OutlineNode aItterator = new OutlineNode(a.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(), minimalY, a.getProperty(InternalProperties.RIGHT_OUTLINE).getNext()); - double AabsX = aItterator.getRelativeX() + a.getX(); + OutlineNode aItterator = new OutlineNode(a.getProperty(InternalProperties.RIGHT_OUTLINE).getRelativeX(), + minimalY, a.getProperty(InternalProperties.RIGHT_OUTLINE).getNext()); + double aAbsX = aItterator.getRelativeX() + a.getX(); while (aItterator.getNext().getAbsoluteY() <= lastB.getAbsoluteY()) { aItterator = aItterator.getNext(); - AabsX += aItterator.getRelativeX(); + aAbsX += aItterator.getRelativeX(); } // now we calculate the change deltaX = aItterator.getNext().getRelativeX(); @@ -426,8 +541,9 @@ private void putThemTogether(ElkNode leftSubtree, ElkNode a, ElkNode b) { change = ((lastB.getAbsoluteY() - aItterator.getAbsoluteY()) * deltaX) / deltaY; // now we calculate the new points - double newX = AabsX - BabsX + change; - OutlineNode newNext = new OutlineNode(aItterator.getNext().getRelativeX() - change, aItterator.getNext().getAbsoluteY(), aItterator.getNext().getNext()); + double newX = aAbsX - rAbsX + change; + OutlineNode newNext = new OutlineNode(aItterator.getNext().getRelativeX() - change, + aItterator.getNext().getAbsoluteY(), aItterator.getNext().getNext()); lastB.setNext(new OutlineNode(newX, lastB.getAbsoluteY(), newNext)); // now update outline_max_depth b.setProperty(InternalProperties.OUTLINE_MAX_DEPTH, a.getProperty(InternalProperties.OUTLINE_MAX_DEPTH)); @@ -438,7 +554,8 @@ private void putThemTogether(ElkNode leftSubtree, ElkNode a, ElkNode b) { * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) */ @Override - public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + public LayoutProcessorConfiguration + getLayoutProcessorConfiguration(ElkNode graph) { // TODO Auto-generated method stub return null; } diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java index e66a7bc199..59cf332811 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java @@ -28,13 +28,13 @@ public class AbsoluteXPlacer implements ILayoutPhase private IElkProgressMonitor pm; - /* (non-Javadoc) - * @see org.eclipse.elk.core.alg.ILayoutProcessor#process(java.lang.Object, org.eclipse.elk.core.util.IElkProgressMonitor) - */ + @Override - public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { + public void process(final ElkNode graph, final IElkProgressMonitor progressMonitor) { // TODO Auto-generated method stub pm = progressMonitor; pm.begin("EdgeRouter", 1); try { - if (!graph.getChildren().isEmpty()){ + if (!graph.getChildren().isEmpty()) { ElkNode parent = graph.getProperty(InternalProperties.ROOT_NODE); routeEdges(parent); @@ -55,14 +55,15 @@ public void process(ElkNode graph, IElkProgressMonitor progressMonitor) { * @see org.eclipse.elk.core.alg.ILayoutPhase#getLayoutProcessorConfiguration(java.lang.Object) */ @Override - public LayoutProcessorConfiguration getLayoutProcessorConfiguration(ElkNode graph) { + public LayoutProcessorConfiguration getLayoutProcessorConfiguration( + final ElkNode graph) { // TODO Auto-generated method stub return null; } - private void routeEdges(ElkNode node) { + private void routeEdges(final ElkNode node) { for (ElkEdge edge : ElkGraphUtil.allOutgoingEdges(node)) { ElkNode target = ElkGraphUtil.connectableShapeToNode(edge.getTargets().get(0)); ElkEdgeSection section = ElkGraphUtil.firstEdgeSection(edge, true, true); @@ -79,10 +80,13 @@ private void routeEdges(ElkNode node) { } } - private void setCanvas(ElkNode graph) { + + private void setCanvas(final ElkNode graph) { ElkNode parent = graph.getChildren().get(0); - graph.setHeight(parent.getProperty(InternalProperties.MAX_Y) - parent.getProperty(InternalProperties.MIN_Y) + 20.0); - graph.setWidth(parent.getProperty(InternalProperties.MAX_X) - parent.getProperty(InternalProperties.MIN_X) + 20.0); + graph.setHeight(parent.getProperty(InternalProperties.MAX_Y) + - parent.getProperty(InternalProperties.MIN_Y) + 20.0); + graph.setWidth(parent.getProperty(InternalProperties.MAX_X) + - parent.getProperty(InternalProperties.MIN_X) + 20.0); } } From 3e4fa44485e947efb9ffa69ce0ee3499e91c3b12 Mon Sep 17 00:00:00 2001 From: Max Kasperowski Date: Wed, 11 Oct 2023 14:00:46 +0200 Subject: [PATCH 05/45] remove remaining force alg references --- .../META-INF/MANIFEST.MF | 6 +- .../org.eclipse.elk.alg.yconstree/about.html | 4 +- .../build.properties | 2 +- .../images/Force.svg | 10131 ---------------- .../images/Stress.svg | 1860 --- .../images/exampleForce.elkt | 44 - .../images/force_layout.png | Bin 24084 -> 0 bytes .../images/stress_layout.png | Bin 25835 -> 0 bytes plugins/org.eclipse.elk.alg.yconstree/pom.xml | 4 +- .../eclipse/elk/alg/yconstree/Yconstree.melk | 19 +- 10 files changed, 13 insertions(+), 12057 deletions(-) delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/Force.svg delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/force_layout.png delete mode 100644 plugins/org.eclipse.elk.alg.yconstree/images/stress_layout.png diff --git a/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF b/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF index d0728f8a27..fb3abe7a2a 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF +++ b/plugins/org.eclipse.elk.alg.yconstree/META-INF/MANIFEST.MF @@ -1,8 +1,8 @@ Manifest-Version: 1.0 -Automatic-Module-Name: org.eclipse.elk.alg.force +Automatic-Module-Name: org.eclipse.elk.alg.yconstree Bundle-ManifestVersion: 2 -Bundle-Name: ELK Force Layout Algorithm -Bundle-SymbolicName: org.eclipse.elk.alg.force;singleton:=true +Bundle-Name: ELK Y Constraint Tree Layout Algorithm +Bundle-SymbolicName: org.eclipse.elk.alg.yconstree;singleton:=true Bundle-Version: 0.9.0.qualifier Bundle-Vendor: Eclipse Modeling Project Bundle-RequiredExecutionEnvironment: JavaSE-1.8 diff --git a/plugins/org.eclipse.elk.alg.yconstree/about.html b/plugins/org.eclipse.elk.alg.yconstree/about.html index 164f781a8f..7a303200e8 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/about.html +++ b/plugins/org.eclipse.elk.alg.yconstree/about.html @@ -8,7 +8,7 @@

About This Content

-

November 30, 2017

+

October 11, 2023

License

@@ -33,4 +33,4 @@

License

- \ No newline at end of file + diff --git a/plugins/org.eclipse.elk.alg.yconstree/build.properties b/plugins/org.eclipse.elk.alg.yconstree/build.properties index 90b6bbaa24..e7e38951ca 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/build.properties +++ b/plugins/org.eclipse.elk.alg.yconstree/build.properties @@ -1,5 +1,5 @@ ############################################################################### -# Copyright (c) 2011, 2015 Kiel University and others. +# Copyright (c) 2023 Kiel University and others. # # This program and the accompanying materials are made available under the # terms of the Eclipse Public License 2.0 which is available at diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/Force.svg b/plugins/org.eclipse.elk.alg.yconstree/images/Force.svg deleted file mode 100644 index 3d54a1fbdf..0000000000 --- a/plugins/org.eclipse.elk.alg.yconstree/images/Force.svg +++ /dev/null @@ -1,10131 +0,0 @@ - -image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Wednesday, May 17, 2017 10:16:58 PM CEST - - \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg b/plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg deleted file mode 100644 index fcaa29f601..0000000000 --- a/plugins/org.eclipse.elk.alg.yconstree/images/Stress.svg +++ /dev/null @@ -1,1860 +0,0 @@ - -image/svg+xml - - - - - - - - - - -Creator: FreeHEP Graphics2D Driver Producer: de.cau.cs.kieler.klighd.piccolo.freehep.SemanticSVGGraphics2D Revision Source: Date: Thursday, September 7, 2017 2:16:27 PM CEST - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt b/plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt deleted file mode 100644 index 284b2d2f69..0000000000 --- a/plugins/org.eclipse.elk.alg.yconstree/images/exampleForce.elkt +++ /dev/null @@ -1,44 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2019 Kiel University and others. - * This program and the accompanying materials are made available under the - * terms of the Eclipse Public License 2.0 which is available at - * http://www.eclipse.org/legal/epl-2.0. - * - * SPDX-License-Identifier: EPL-2.0 - *******************************************************************************/ -algorithm: force -spacing.nodeNode:100 -model:FRUCHTERMAN_REINGOLD - -edge node1 -> node2 -edge node2 -> node4 -edge node2 -> node7 -edge node4 -> node6 -edge node6 -> node10 -edge node6 -> node12 -edge node7-> node10 -edge node7-> node11 -edge node10-> node12 - - -edge node3 -> node4 -edge node3 -> node5 -edge node3 -> node6 -edge node5 -> node8 -edge node5 -> node9 -edge node9 -> node11 -edge node9 -> node12 - -node node1 -node node2 -node node3 -node node4 -node node5 - -node node6 -node node7 -node node8 -node node9 -node node10 -node node11 -node node12 diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/force_layout.png b/plugins/org.eclipse.elk.alg.yconstree/images/force_layout.png deleted file mode 100644 index f99a6e8a1d1884b8e79976641911313aa9c01ba0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 24084 zcmbSzg;!MF8}1Ap5<`fz3)P4$=C$8WdzqWH1WT2kM_^}mF1UCH#r`)^pcC1UajZ#?b}bHx#`pz z?MB|exB85g@ft?Z#>ANY(=ln?2#=BB=aXUTza>JAQWmpVV)t=!HpNiflT*lB+?d{lPR%cRFi_qp z8bwrrkO<|>i;Nv6@4kzK%CEaY=c<|7&#o?xm*%~{O2}XRP_6nnVmL`W6cWn7_rDXu z_NyxAn16bD&@r7q6WH8KSLN$@x>@Jt-F^_TUaZj(2`3+tb6)@X6B1@b7LgcIwMJUL z6-quQx!5-EmgzS<>{>PK3-bx%QB_fY>zU^T9sE>ZJKXnYH8D@tVxbDfM7dEE|89d) z-5lX#!|d%4R!A2qk=O}5Sy)z=o{tTI2+OSxU@Y>+C@*ssj8gWO2P!;f|weSRnTfm;M7t%3?H+UmT!q#?wCl)%Jw z>b;`5N`sX~#TJ*<9mw??XHf6vMz6%@C3|eE<@rTX)S52<7;#+pdy`9D8 zduMyPjJ@oftI6f-c2pa)l5Cw!V8~`l_w@n=h(wiTrmz~JmhhqSJ?oZir;v#vv)BjE zZsB|%W_S*Tju1;fLRlG39`h;u5T_Zh+BWjVXa$$Oi0L$?5P)40Y^0s|J*v1M3Z@dj zbp;iaHnz)ThYEUmLFg2F-E>I>^Luc2eTsPwa?C|qVOJ7cw^i~FaPlb?$pqR3Y!yn)Pain zTEC48R}Lg6jp%v}r-ZmaL=WeHO|ojD$)t!znjhA!>J*D-E6ndCm%hC4OI~>UUi14q zZ@ty5v>f~s@);E%Em?wS&p;+VNgxaEyHhPEI9FS?AAYuB@oac^fogfdBqz#nJWVyy zCSb#j#=69)isY(8dqu^toGl&{(lfa6)8@8EXUzJLMds2bIx_e~#_&Th>ARe^Gbfz_ zn9$t>P0Y1v4%E;p+eUdgvQ(t7lFQMNr(i89TnE1OIN|47O3H8Nk_2^DU}pq$J1*|A z0gt$mJaFrHW(Dx+Rf*7Q472-vFxBmj_vzYR($ zf5JZJN}72?Txj(}Ebk_@`OM`5AodNVe4oLjJIVp(@o)KT&$fHo+Vc!QVXWX^{C3O7 z$A?eZ+OM9mwOw!5V0xujL0LwS2Cll5=~w_iC}};?Hi-_QieAnzmY* ztLicPv4qzO9M;Fo&m{4(^l6bH-ojn|j#U%J4#F2*ve3d0#MBZy)7V@4)Ogt7sjm9M z3(@$xKe3v`%bvMzE89?bboy8QA$cr$(sbZ-`_0=l?;)B#&o_<)xCYU6^R7nYHg+ZM zI+-aozIz6fUuHb^2yrF2QP@zbP;~T!*XQRaFKkSJR{7aA1pBEsOJOIrKNXh%vsX`b zdGgu(pYN}tnT?{utW8ubSPmnKU`G`o#@J3+Z{=*|nO>WRkx=&!4rB#hP1pjwH=b!g z&izKQM>DMkmGey0Ubk-)7i&?HB>K<FWe^uFtofAnk zCv3qxCw~mjB>MbT&Y3bTb22K0-#EGP;{AK%Zp%@1x~3qZu2-TL&F|~4UMZs_aoYdo zM3+5@`AsWw%O4Fmr!{PlEIWp62wMD4_f3!b4v&gH>Sc9)+B~*B?{~Kwwk!huOir1f zSCd_5jTl6tuCn#AX|At-BZ)tQKZ(Cf$gDqdoT>p)Wc4XGEa^0JIQweren}_gL|Hpr z4HU3yNq6r{SRK++T#G*2bL#oySQXSlVOb8+^8FT+HN!%tx+c?sIF~LxPX6)gFY*4Z zeJnU~S0kvb%16@W5`5d&oBj=?TXaw_bLWz#q70~L%PxXhQ)s)O zQ22)gQ4D8^Af4DHjk;+g@qx{7a?db$bSvG|hXAyleAEYSjnizh#t7b~xA_mW`fpG= z^H`F#xKy8E+O zN8o@>74_79gf0T-uFL~maD6MvybC4TOcrGn!4J%^0&9560Bk#@C45*R1YzL6u8ykf ziR5C&7}x@yl)-L2|h7GJhq_5`w+)m#UV$VXK-a8Ggfz(AGj zJ^XJZ7W*suFgyNs_Gv4bKR)wfkhS-6mmt#FZh#GTfj&ICyXyJA13G|e0>tcp4P^#) z6#F@tD}17~T8TkI)Y|=D3Jh@K;;lJE)LH@KwPrj}1@}@L{cd<#a1t(d1v0yD{8=$Y z6h~6PeF-l+Gx@nSm{XE;EsI!q@JZ{`TPw3sQQ@lI*g2+$3COy;BwXt1usJ&}HDBY& z_V;mvS`1KWm2{sVrzO42;38Z#$JSd<*koer?i`fT1l(FBoos^sOT!B>G@(tjB|E%M#-v4UTz6Z0_)ox3pLLNEEZ^v`QikSeHmH1!hSq`!}8mLC6g<(^@3 zWI}pzdH^#DR=^blq{;Pb{XDrd!^HaXFq_6LF4d+^ovL`NAKN)Z*157_f>Fgd&e+*p zDGk|PFHC{$pGq(LQe67PMV!(t_2Pp=C$5D+Rx?Zm$!0c`eR&EE+*^NHX7G^%xe0&Ox%&?c zyq3GT50d-M?HQ)SUII|9GtU~@LO^tkwmOQftD46IUjcpC1#pYY118nJsIM2`U5_P1Jb4xUl@vOozl2U?XVsuk0#efXA*z6OUq+wSpH+H( zldy&z8fiw3G^CX#V_uvS{63}vNtE;+J8Y(e^pf9yKGSLdR78uh@dR9-I~*|!uaS_A zmT-$xN7PH4%Do)R^tz3#hhJ0%bY+95hLD+SK~A}*&@uHx-__rpeX3R>kaAlg4trO= z5HGxE${p{_zP)b&?PCe~4n5@Q0~U}GF+#?cAFjG&+gf-9ZoRx~=lwj;=qj} zDF=8th0wYqw~=!8+u4EDkQEV|dUaFROAK0ferp)T=;Bxe8tsgs4LU+jG4K=;`?u*{ z@uSYX0BHS>>WGY_04Oo0507u)OmkyFp=e3ILUGHY%u*EU8{|Go8V7_>YYxj*l|i4tqXaQF z=L_f@856MLoX=b)Zhs%UCE&dm`pji5nE}zrEX|(LCvOQ@CrICMX1yL4jYUJ_YNa6G z{s8SUQiCo#2_LHoEVJgyRg&F*9?X$7o^S!T#2dLffgt@_^T zH$T;{B?YAk5BnJfHGmzGnJ1n+1>f|Kier;@RAbnp>5kiuYUH@E~f z+Y%;-F{ONNG+6;DvLk{|7?Bug%Kd0FJf{gqV1qjOX9@5WE?YH2>I50BjF&kDKArp2 zOL&P9B8uY#ncRubiJluyT0;TUGjH%7%E8)3r1Bwe;Y~O`#s$g~GJ6IIklWgJ=KZ_Y zb#mduJ}m}hwct_Z6m^ZoxBQkIIM1gB{dH2LA$tS9G;6NYusNOYmQKbI>yx>>dxuir zu+U{z?8*GC-uRQqSta@)pBGe_rJ!}%ceaRhY1UCl`YtHM{3Bi*@JAK!r@~Ds{M7+H ztaL$3Zv-C|Nf%>&*iBf_^SLOC-GKkpE!-X^(!8kk51Ir4`F~@r@*Z<>rKW8+1ipNS z0U_>!Zqwb7ho^YWcUa6(P}~gWYFF#il0l9W2jTF36oT~{jCzWzDk;R>rFKsz!C{K} zC9P3fz0)Y^GPj`9A$(gbE*GzdT5bfH4}Bl2t3MM^xKjy zRztCMtCPlry+R-EU{wbnSQdG)AZA%l=!(3$!sKNBeXg0}*X61Y&AOoN^PP+CA!opo zhqu5pGN&`>^^zcvj5q%#v0ZfwZk43h2cRTj@Gu{@6*DE>ct1;GdIsNmSiNW zmkWp)Ko)gW6U_ShnmXF2V>8$LaFAPUDWIzZhmfo}ljfzhY%MR|0;H&>hpg+^5 zI!>`OR!srjwQ*A^bg5oVt80AIcvX0@S3Jn9_cyq$J@N+KKzwvXVlZ*h)BA7$M91v} zCJYWdnBYFtgK^uY+EhgMZ)~>@YTaZ2=bh+qC!+aD&mNy1FI9W>cvT+Wv48Vy%(FVV zQgNU9GmYzmWqL$0n;W_@jvRP)kIcrBEPU(ich9%KuY}ip{;&dB@iNt=c)nb_Hs8^B zLg>cfyJ36W4;>cgWwa#3|HSG|J^tzm4ZEOjkp7h|fZT)(NC+~ZxnTUyW{q})X^%Xt zBAEYetsVzl9j4he?|npy^bHWA580s5C8v)%iWbYZ?1|uuB2|4J0$&W?p^t1iw`-g; zJ(gtX$oRAffwcJJy2%0~?#E=8=`JgcVDBRNX%fH~u-x`i> zN23AWjn#VY8<&^-IK1TvZPIbi>RZ4gI17eRN(yF0B{7>x_gy80Jrn=@X!AVauk2r# zkldcYO=0tfMe@baRr>hF8cyrbQ(I4FtDh5|Q}N&>5euaNzBybk8jE5Ec9*R}1H!Q4 zc-cK{I!Ca_4YN+q7o4rX)$VC#P-Ydke^=LGQc8`s?-M!Auzh`bIyAHH9aaN;I$w>9 zPjbd;3NOE{oU;Zh;vu1-Sky?Q@OWlK+}v50uymgB$8%+TvGB*%8GrC*9;= zCE}G9BA+__7L3ratXg`E{|HGglRz)%1_PIR8Ky5$^5W}6{ZC>Mu~ zD2f?)LbjT$KYPsi8FkbSev`}dlQ010P)yK%q>Xm{J%g+K18O z=El)E^M3meK`mT zqxzF`nDqQ11?0HIpno+2@?#a$2w`B<0y%J4Q+eT@%TY<^FA_5Y4V7WNg`wzczk{4p zXVEi;l+KCmx9Z-^W;2>R>)OV%yk!-t0&J>LXRoeF*q&T?xc+G6aH>JeeJiTIjt|PH zI=B^#tTK6~hK7o z<5!cF0d``dhy`ZU+SuLI0V2zy>RX6L5^2R>*(G3?cBYrXi62_UE@D;si?`@Le1qm7 z8Cx48o&CBui?=#iU+eFqQqwt3@LOT`Z$S*BX{v!R5F&YDARAvJgerhSb95|#-sTFl12@;I%|j;4kKbn`zQ*qQ>jFoW|MC z;*yz43JX>05#&HB2XYkNXTw__1a3*W$ZX2HR{J6(<{+s&D>n`!>!DK4z9n_C;IOs-J{Whxtb}+ zh#aS3hm*7%@6q9DvE$>F#4D-F?&2PU)~G=!dXrNpa;NLfs3#jvtD_>}&3M8^TcST> z$2~J0s1xxqQgCyIy3KfE_Pl^0$(|JlC6{Nyrj=oH6}x>I!t%5(8|;j@#xQaql9qggrNuijDB1ae5kzinHe{h2wa(Es$b!@TE-+uW$q zkqCad0NeUr9=NA={LC<+u+UkgL;r|Wry$k#NYjPBSoyQiPjUv{z5zZq7?WFr0sd~V zjR+wj;d;}_kEBtXwAQ9R-zz%IXR zRDne5z>uIHh27U-sS15L6UvsHro%0K*Wq`)6J`mJ05rWN?j+4n>TmyG=>@NY`Sa}u zI`(cz>uS%E=6WV^vjn0?$)u{E!f5&dRC-12c=J4EveM|kScFMw?c~#ZEz9tAH`sacH^%bxk4iB z6`oMfLESm5Zb$CU!dSdp?A(ktO7dY-$Bn$;d%n6KXx{K-ciub`B&0N%Y|Im}>kH3u znt8vNh`YOt8|&@@PyN2(`?2sa`V!3KnH>}`e{0e*LWTb~yue~={Rfy@R!K3l#P5Fk zHIqz-A+awkY1(V|NI4<=A`h3J!ki63^f-syg<4*t8Rzyjrqh7l=QOD-4WDbicqqFUOAj!nn+8ct}sF1Gg>YJh0L;2WOA&R|5n6(0hHJnO>qS(joKd23k^o zFHY>L9<){6=uF~8atnM8q9`KP>0?QDCz>hS&TcuL)Qp$=i3ZVTXBD7!3Li_r3UAB) zZx30YpJd#=_0gKP=8Ivg()22?Rl^iuA0NK$9OI|}8d@9MuX^W%>8CX=G=K=#UcqD} z3I)PcD;==y7zI(I!8!;RUN6&&H29EfBbdqyg(j%Zj-lt5_G~ZL`R9v=^UtjT%duM* zGVup`r~+9JJP+P6WXn0C^0+rce68!d{o~33?#H}!T3q$QTMJ2}OYCI({A1d{)$0w` zk8FDeYC{y=_l|Ul;$h!zqDy*nqu4*>nt$?=FxD?)nqD{{Atao{X%ko`4cb8NFO4)* zO5S>l;ZppB16kx_8^=CpN%>J;$3=1Rg!f(C}i zAlRw`pJ;>awH*>^?9RpgG%8H~cJ!v5!5eBJ{RsU%Ta}h=I4Q-q8iI4y`R3*Yt`& z{{SHmc8?rz#9~N7%8sfMcsfL>_?1#mfno*=hF9l z{}HF(SJplJ2+6pE?N>LIeM;+^rRoekqApQ0Dtz{cdo&y0@I$A{C$DwBqi2iQ^`TTe zmIBaS?Kqy5r=2=cNLgvwMxc?@wZZ-NemW>5xPH1I67`nVuEK357hXm#r(bBLz#Ydt zG+N_y$Ex~P0~%o0UTE$YkXKNM3tx+N7ELt2!SWF#@B9u`&O363A7Y}>YQ^UI$~9AN zZ$mISbRHbPLwwtCh(e~0d*9@N#Ao}#u%ip(fjQ)iZ(@sIOm?bA}=c(sRe#a2Mr z&M^iKo>KYnl7meI4b%-HrbSus=eX{ltgbtg^^WxIu6+@F53!nh%SyKO?O>bvO7a(& zy+)x^)*=;cZ`qgfRq0~R(olI?Y4*o-R#p@(Skj4fpGOu}=)*pdidH3$C~zYSct;K} zQ76{nR&9?Tt{7`Yza}{G+|bz=d8_*BA>Sh6-C3Xe`R{Gvs)bo3aw{n@K1m!|O=x^p zMy0RR(n4Ty< zcL;6BXYoeiahM3xKi!?5vY30{wG%Y_dskvw_q;Xw{}o`ly#NC^-EH$YWj%J@|AkZqI}hD@FGo;ntO1KL=ad+@RA12zqAQ8>2j+AUKeY{!=S zWd8oJA8Lu;Doe{*ednzkJDJ~z0*F%|H#3gWN)tVPv@*4XKZ+0K?|S;s&G@7&tR}?@ zTW~aRLkUN7XEEW9h%(9;4q(c`(*U$53Mz59ZXRga4`H=F{rlPsP{mpGTwHWiVKI*sm(T-91pQ% z;fdwtdbQ^Z#EE+wqqgv3JD*tqS=78zoo@e+3*abk03{+jlml()&CimiFS~`nrpFg1 zWuM}r!Z_hf&*~WajuhjJBX%B}&0r!kq*m&!o$q=6x&^u1@Pn(6*Nvg)Y|ZB~%dS9{ zb^O^UE+O-W+AM6UErlsxW6844RZw=`^&ypFayF!z32^*->wAw-b)CU@9UDC_UW;Yl z^~lraKpKV#{+%Odez3^+uSq*{obRy31nlp;^LQ+f znsTP{agMs@MhS)xY%-Ymje_o^WYmcxIA`UDzlKhKXg7^Ym)>5H0RuxF=ksrfqC5By z?62qpb!x{1Opaz?;QeePEyy*4et${AaL0NS)k9x7 zJ_tWkMhSIA{w1vUSf$w~0E4a|IV3*X1(`p4KnxA|!lc8&0Oh2os@4Vp5(yHMy zJohcg#_aPhfM)FzKVbu}TlGA}FN{JJYYF(3|F=~JA_q1?lBbOVOz>1OdA2hjh$ZFy zNsI?h{@brXqayKyVeU>_1a(QQ;jbGWgsoOZaaP{RKdZXYW|@9(*u{j*BM%fodhvM} z&$P-@bdko<)ZNo9qA{3U$5Gp0Aw~ox4z;cPIrF%G|DYb*5=}AGQU(qo$z}({P!3cA z_mQHn+;9HA(WcEfizQ({jg<{^y;I<(MD3enG&%RxV=i6)f-(Fyzy9P0@U$8{B9J7E zC$#EmA=$RUJ0g>mKS{>2(8YX_8DYX|(j#OnQ4pe;M%jsa$}*Mz6aqsdO{gg6rED?k7PyNo z#s2J!x_nQ0d#HiRLcDBUZ7I1JxtBgSlifv>^%7_naQRn<@f;{OD({cmwUZI2Csi@U=dYo+>J z@4*AKPbKKv7g+9We}GUk9o-iA{OFPg(P)A4rP#&SP31(Eq1H%kWIaSBS>)Lp5cljA z9sq@Ex9resAqj(7yo1X7-%f8m2n{g@^j_bNM5He*ML<<+(;mA7l>MBRp5K@%c}Q2t zUiCe96Yy~$_%5S$`?@FBhHrZB)t=C2K7r{soP!ZqfevjVACpO{{CFNR%OY)#WV~C^ z6iTo0d=rpy=BO9FuWb{6$<41JS2`-FI&LdiwRd#a*XZeSrnKFe%xXmBGpZgPJ3n1% zakhiyAjPO8&Ox1Yh6KldzJoO!qjr`>Q>vy7r;L@fBE&T|T0sG^BDJ6JERO36!568! zx5VfXPjoD6zoki^LeS^p(}3jT6a? z7g8lAEqZ)`6o~Z=qna(x+LvNI3vx?;@~L_}f_zezI?+2UsB5I(BrKdv@@a>SE3 z;EO_h1MyPu=P&DvXoi2E0aSsUu|#k*I2A3MUF4C+cR#&|Jz~;~iSl{ew`xt4E*=~4 z$D*e-hPr-JudvU%2}*b>-8wl4+mKc;FJFT1jtblT%V&s#<)O11ZGVtR4O@C9r;@GI z4_P@SC$b;`s(^b#b(%T@Cy#uZNVe9)1U}CN^U z3zROInQMU7{&F*(Me>2o1ybFXC8j{VG94I!AdI z=&t#&=xHMO;yoBrb#)wq(WpX&;n^s;w(a{N7?H@nSWT-t4N#{QDMnrLK8V)o$)_8% zhmc>_g7H|fUY714bb~$za?UnZrNl1j=O&7ARMsOe1_nGT1NTa{p3Hp9!N>4a70zwp zI&fc21N#|CTX$Rtt2 zl>w8K>0KvxZP0v%J6&RNFL0OL_fB3QvpY7o|M9W2pK^{ykTH)xiJGNlEe08oLL2=zeOQ+Qo;Hs{dhKDd$;to2P6w5O4A2 zi7lt(IKGeZr1yN8qmQ1}qC_wf*AkvOEzbvh>wl0(12G6~ zGeO)dFwnT0ql^~uGcsk~svMMfAh$GdL*->pUi#ym*x@HV=}{@@Q22={V3L;CYL2@K z>w-zTOkjt~+uvsS?rC=o*XL^HX{Jo74VE%~{kOJI-*7d>Y}T~qUfJ^*A2=NURNIX3 zq-q=P98#P4?*s<0TK!?-3BmU3xY`C@gNiF2NY1@*ZB$*Kt2YzO8W!YS9ct|V@&!?P zF&LL0-^Z)Ok#ZrTQ`=Ot@!uKy3{$}-W)%4JnAL5b&=ThH_cxE%pI*M0%Buv3HR_3W?>XptpAO+erurt zMZ^#2$B4W+e-wc26<6S6L}F~!#J>u(Pkqs<=NnD|CPh5jvertgkk{6t&6%53OZAa1 zO?HkVpylk<&C^W3@8&(l1^V>7r9y_~vYY6|fc1b%(tj6KY!g-83MZG{gDp!*KXamj zk;%tqaa`5U4JK_7QFM&|xY5FPfL)p`+Y83_4OP@GZiB+gV3HG(S&OwJ`=_Q(?UBv! zI#S72^_8%#!q$%8qMM&p@L32oZw<8C`QbEP{A|fR?-v;qk}+e1XMfH}YyM;U#Tfin zL$e@;%b?b9(mnq*kMF`?gw!*Fr%50sdNK>s`+r+p&xR@o(V zHVR&uCOie&Bq)yxSeE`!Nhu6p%ee{Lk>#!sEc@mc@7AR6NW80! z=r_wFW4w1oXl^$p7FDv9`8c1C-F8Q(^lVQhB~+ZtflzXR<6q$0ISDtb`Eo4!(Nd$X z`f@oPCX=3T`Dy2h=JIoZmDN#%zQCZfjvTlYrGKF3w3R%dB_-*-Mb)#D>X=wXEAvc~ zxnB$Nr&pNm&fP5VR44rV9aWtoW7|)OnerSr&UWJHxg35K8EDnZJkjxd@A4;3=I8CH z{6Bf^MfjQ$9n5=AT(kP4(i@%XXlTKu>2=fPHA>_-3N=ET=qH--fy2~Or8iF3%A$=` zL9FhlN(w84q5o&J`xEN_KFBVj`V5O7_`?xD+|{o5EA16T_H@nL!+b9ch&D>Kd)XuB z-qumdcn@L}$9yOXy%-?Y$zeH=bXq$d@ew1^`$)2;lfZXJPySWNOq$IA?ZNvvz9;gl z!hO_F(+mb&Z*nV)eKZ5^Sfm4yzoZ zM=@8hGQdX;P_O`^Aa+;fiw%d|9~rjR`}?haY1^0JU>Ltp%q-6Zp#YvQffaqCo?5}z zKxU8k-BFi#G8|~6mo!8SYJCXgKpjsy2xN}HYK9^vpHHq^&L2O&c?q2QO$#fHtbNX>!ZMD(G!xH?c)N)AoG>!B z->Bo^!hnGMTjYO-A8V20G$%y-z`l@ER1R%4F;eX2-R>4r_IOz~=Y{Y)*)x`3ce}F& z>|YZuk|`}EAG?cB9u}b-7;J7+d#_nXGEOYM2V)11ce5a9n%iDYAa@XPHx?~H0gEsWqh6VNN`J-x5-_b|2(Gu z3$Bdx_Z8;wlE^s#X*k7+424lt{X3d|AJ3y*ZCr#ZAlv6Qwssb+ECF?2OM(*|NJ1Q$ zYtiFE0k5D@Gn51WGE67^2)>mp?a1`o>T4m`)beI!hNVHS+t8i0a2TGAFC;w7ql*IZ zH|@GMs{#_;F%JNr$J#G_2jj2;eSE5ZMw5C-N*=>%v!Z8k=vF8ZZ#WL7bk&7 zyRv2W_+v&&xbQYxy2wt{2Q1GYIT1SA!ehXPLq@$w+Jo7{-@llI-yk#v9ElgGlt=!3 zXRn2xE7^K|cQyK5DJ>sFeM(8HcokyC@`itaHkyFBhy%w0EQoLUd%fM4qTiO-8GN_? zoqqd6cjRC7r*$EZ`5;~%hRd?sbvg}Jk6*tTG#fq0eP^@V__0*~hsNWW|9}y??@x{; zbPBlf`!?Te65192yd=o5LlsDFLM1gQA{5hNG zo6gw&N!+T;`M=nAGnRRFp$P#Gr$~TwVSmaYU2_5m!fb45!%gddpoVS&@`(4$`Ze9W zO4NH2A-j|AabrQj>L@EBA(&9#rQ{Wrv>r;xVDdQswWvmPS)Tc?*)+2|Xj8JC_DY`D zw7_Ar;mD}3Wzn144i9&ATc&I6p^$-}L!%d-p1MdJ5n&(3%*a?Xg;=5svQEP4j zsvc$Jsaa&-%jrlRBJ`vCJ#k#N$ALhI!l3_nI5{ALNPJkePDYG(Mia^x_nZ7T3QHB7 z{oy=(CEq!^zjY>f5;Jr4ukC(!`M`AEINfSwEvZ9`{x!P#rSeSHLpA(+0WAY)NTS}& ziamZOTlG=U6yaq3mwU=(aGP!kO`|SO36(8ja$&wWMw}=29!TzQ0U?D_o#!fm5?x|Et{syR zCKz^!dyDiU+<(p%;$#G2<6Qq$snBoSvVzt1G_^;q#}b?U;B~#}dte1Q6(i&-Y%@GyV(h_!Ssq>khZ`OvKYGSPMauPL!ym|E z@s$7RK)W&m3*bR_j63VCtW4B)^FF{NK&J3n+dX{boBkvhjshums{z5UHxAWYs7Tnw z_|9Tt4;1n-uj%*@G6;Sxn54{^aq@4J@`{JC6$vEteff|U2&u{GPv{PM$PPTeR7Jgm z$=TMavWk+w=QW+2Gr)O_!gMHs3wr5?C?Z>`%rm?w7%}w3iK$95)j&DB-bc;btC_r= z{>Kb6vT13e?Cqb)s^1_I*>G|=JYeDOmOtOCWutmp$cfKr3QLJ15qlC`j?x0i!z$t7 zuR|WENjO4qORt7k8Fkckxn~iPcG-E8nhF$HU3AqzwZWQfTF2&~3-ePk?IM-H-f*`RnkM9?P!BPqSEFHE#M+0c_mA0p?n_P zrtms7606f4esKd}y#~LML{&qPh7|q?+G3@uwdfYwV&xHs^Jq=}mDZ07C!0(2(krTg z)`j07R^h2FQOU%TjcR%0Atj~K5kU-^*U&XR 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 diff --git a/plugins/org.eclipse.elk.alg.yconstree/images/stress_layout.png b/plugins/org.eclipse.elk.alg.yconstree/images/stress_layout.png deleted file mode 100644 index 6848d9864b18f18363e686e012dcfee809437280..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25835 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

-8$*3bfGGskOC+Gh-BLy`j;|n6BRiP76SM(sO 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 b-E*a{w3?aU8kfKalR)&ej1g6L(NF&eQ@~b= diff --git a/plugins/org.eclipse.elk.alg.yconstree/pom.xml b/plugins/org.eclipse.elk.alg.yconstree/pom.xml index b8c1772e09..8c4349fb6f 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/pom.xml +++ b/plugins/org.eclipse.elk.alg.yconstree/pom.xml @@ -19,9 +19,9 @@ org.eclipse.elk org.eclipse.elk.alg.yconstree - ELK Force Layout Algorithm + ELK Y Constraint Tree Layout Algorithm 0.9.0-SNAPSHOT - Tree drawing algorithm with y-level constrains. + Tree drawing algorithm with y-level constraints. eclipse-plugin diff --git a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk index 338ada49db..0346439698 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk +++ b/plugins/org.eclipse.elk.alg.yconstree/src/org/eclipse/elk/alg/yconstree/Yconstree.melk @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2015, 2020 Kiel University and others. + * Copyright (c) 2023 Kiel University and others. * * This program and the accompanying materials are made available under the * terms of the Eclipse Public License 2.0 which is available at @@ -15,7 +15,7 @@ import org.eclipse.elk.core.util.ExclusiveBounds import org.eclipse.elk.core.options.TopdownNodeTypes /** - * Declarations for the ELK Force layout algorithm. + * Declarations for the ELK Y Constraint Tree layout algorithm. */ bundle { metadataClass options.YconstreeMetaDataProvider @@ -23,22 +23,13 @@ bundle { } algorithm yconstree(YconstreeLayoutProvider) { - label "ELK Yconstree" + label "ELK Y Constraint Tree" description - "Force-based algorithm provided by the Eclipse Layout Kernel. Implements methods that - follow physical analogies by simulating forces that move the nodes into a balanced - distribution. Currently the original Eades model and the Fruchterman - Reingold model are - supported." + "Tree layout algorithm that allows defining set vertical positions for nodes + rather than automatically placing nodes on levels according to their topology." metadataClass options.YconstreeOptions category org.eclipse.elk.tree features multi_edges, edge_labels - preview images/force_layout.png - supports org.eclipse.elk.priority = 1 - documentation "Priorities set on nodes determine the order in which connected components are placed: - components with a higher sum of node priorities will end up - before components with a lower sum. - Priorities set on edges usually directly influence the attractive force of a connection, - with higher priorities corresponding to greater attractive forces." supports org.eclipse.elk.spacing.nodeNode = 80 supports org.eclipse.elk.spacing.edgeLabel = 5 supports org.eclipse.elk.aspectRatio = 1.6f From 426e6e43257c90ee261024bd3a3123325c46c69b Mon Sep 17 00:00:00 2001 From: Max Kasperowski Date: Thu, 12 Oct 2023 10:15:01 +0200 Subject: [PATCH 06/45] Update Copyright notices --- plugins/org.eclipse.elk.alg.yconstree/pom.xml | 2 +- .../src/org/eclipse/elk/alg/yconstree/InternalProperties.java | 2 +- .../org/eclipse/elk/alg/yconstree/YconstreeLayoutPhases.java | 2 +- .../org/eclipse/elk/alg/yconstree/YconstreeLayoutProvider.java | 2 +- .../src/org/eclipse/elk/alg/yconstree/YconstreeUtil.java | 2 +- .../org/eclipse/elk/alg/yconstree/p2yplacement/NodeYPlacer.java | 2 +- .../elk/alg/yconstree/p2yplacement/NodeYPlacerStrategy.java | 2 +- .../eclipse/elk/alg/yconstree/p3relative/NodeComparator.java | 2 +- .../org/eclipse/elk/alg/yconstree/p3relative/OutlineNode.java | 2 +- .../eclipse/elk/alg/yconstree/p3relative/RelativeXPlacer.java | 2 +- .../elk/alg/yconstree/p3relative/RelativeXPlacerStrategy.java | 2 +- .../eclipse/elk/alg/yconstree/p4absolute/AbsoluteXPlacer.java | 2 +- .../elk/alg/yconstree/p4absolute/AbsoluteXPlacerStrategy.java | 2 +- .../org/eclipse/elk/alg/yconstree/p5edgerouting/Edgerouter.java | 2 +- .../elk/alg/yconstree/p5edgerouting/EdgerouterStrategy.java | 2 +- 15 files changed, 15 insertions(+), 15 deletions(-) diff --git a/plugins/org.eclipse.elk.alg.yconstree/pom.xml b/plugins/org.eclipse.elk.alg.yconstree/pom.xml index 8c4349fb6f..01a189ff7e 100644 --- a/plugins/org.eclipse.elk.alg.yconstree/pom.xml +++ b/plugins/org.eclipse.elk.alg.yconstree/pom.xml @@ -1,6 +1,6 @@