Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "GEF/GEF4/Layout"

< GEF‎ | GEF4
m
m
Line 28: Line 28:
 
==== ILayoutAlgorithm ====
 
==== ILayoutAlgorithm ====
  
<code>ILayoutAlgorithm</code> is the base abstraction for all layout algorithm implementations. A <code>ILayoutAlgorithm</code> needs a reference to an [[#ILayoutContext, AbstractLayoutContext|ILayoutContext]], which provides information about what is to be layouted in terms of [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IEntityLayouts]] and [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IConnectionLayouts]] abstractions), which will have to be attributed in addition with respective properties that are required by the algorithm.
+
<code>ILayoutAlgorithm</code> is the base abstraction for all layout algorithm implementations. An <code>ILayoutAlgorithm</code> needs a reference to an [[#ILayoutContext, AbstractLayoutContext|ILayoutContext]], which provides information about what is to be layouted in terms of [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IEntityLayouts]] and [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IConnectionLayouts]] abstractions), which will have to be attributed in addition with respective properties that are required by the algorithm.
  
 
==== ILayoutContext, AbstractLayoutContext ====
 
==== ILayoutContext, AbstractLayoutContext ====
  
An <code>ILayoutContext</code> provides the necessary context information needed by an [[#ILayoutAlgorithm| ILayoutAlgorithm]]. The <code>ILayoutContext</code> is the central entry point for clients to trigger layout. It provides references to the [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IEntityLayout]] and [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IConnectionLayout]] representations that indicate ''what'' is to be layouted. These information is based on an underlying data model, for example, [[GEF/GEF4/Graph|GEF4 Graph]] provides a graph data model for which [[GEF/GEF4/Zest|GEF4 Zest]] provides an <code>ILayoutContext</code> implementation.
+
An <code>ILayoutContext</code> provides the necessary context information needed by an [[#ILayoutAlgorithm|ILayoutAlgorithm]]. The <code>ILayoutContext</code> is the central entry point for clients to trigger layout. It provides references to the [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IEntityLayout]] and [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IConnectionLayout]] representations that indicate ''what'' is to be layouted. These information is based on an underlying data model, for example, [[GEF/GEF4/Graph|GEF4 Graph]] provides a graph data model for which [[GEF/GEF4/Zest|GEF4 Zest]] provides an <code>ILayoutContext</code> implementation.
  
 
The <code>ILayoutContext</code> also contains references to a ''dynamic'' and ''static'' layout algorithm which may be applied. The difference between ''static'' and ''dynamic'' layout algorithms is that a dynamic layout algorithm is not re-initialized before applying the layout. Moreover, it supports notifying registered listeners upon changes to the context, i.e. addition/removal of nodes/edges, etc. This can be used by layout algorithms to update their internal state. Furthermore, it supports scheduling ''pre-layout-passes'' and ''post-layout-passes'' which are executed before or after applying a layout, respectively. These can, for example, be used to update the information which the <code>ILayoutContext</code> provides, prior to applying a layout, or transfering information back from the <code>ILayoutContext</code> to the underlying data model after applying a layout.
 
The <code>ILayoutContext</code> also contains references to a ''dynamic'' and ''static'' layout algorithm which may be applied. The difference between ''static'' and ''dynamic'' layout algorithms is that a dynamic layout algorithm is not re-initialized before applying the layout. Moreover, it supports notifying registered listeners upon changes to the context, i.e. addition/removal of nodes/edges, etc. This can be used by layout algorithms to update their internal state. Furthermore, it supports scheduling ''pre-layout-passes'' and ''post-layout-passes'' which are executed before or after applying a layout, respectively. These can, for example, be used to update the information which the <code>ILayoutContext</code> provides, prior to applying a layout, or transfering information back from the <code>ILayoutContext</code> to the underlying data model after applying a layout.
Line 44: Line 44:
 
==== ILayoutFilter ====
 
==== ILayoutFilter ====
  
An <code>ILayoutFilter</code> is used to filter out layout entities and edges from an [[#ILayoutContext|ILayoutContext]], so that they are not returned by the context, and therefore, are not layed out. For example, this is how [[GEF/GEF4/Zest|GEF4 Zest]] filters out hidden nodes and edges:
+
An <code>ILayoutFilter</code> is used to filter out layout entities and edges from an [[#ILayoutContext, AbstractLayoutContext|ILayoutContext]], so that they are not returned by the context, and therefore, are not layed out. For example, this is how [[GEF/GEF4/Zest|GEF4 Zest]] filters out hidden nodes and edges:
  
 
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
Line 69: Line 69:
 
==== LayoutProperties ====
 
==== LayoutProperties ====
  
The <code>LayoutProperties</code> class defines the layout properties for [[#ILayoutContext|ILayoutContext]], [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IEntityLayout]], [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|INodeLayout]], [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|ISubgraphLayout]], and [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IConnectionLayout]], as well as accessors for those properties. Layout algorithms access these properties to read/write node locations and sizes, among other things.
+
The <code>LayoutProperties</code> class defines the layout properties for [[#ILayoutContext, AbstractLayoutContext|ILayoutContext]], [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IEntityLayout]], [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|INodeLayout]], [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|ISubgraphLayout]], and [[#IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout|IConnectionLayout]], as well as accessors for those properties. Layout algorithms access these properties to read/write node locations and sizes, among other things.
  
 
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">
 
<div style="border-style:solid;border-color:#f2f2f2;border-width:1px;padding:10px;margin-bottom:10px">

Revision as of 09:47, 22 May 2015

Note to non-wiki readers: This documentation is generated from the Eclipse wiki - if you have corrections or additions it would be awesome if you added them in the original wiki page.


Introduction

The GEF4 Layout component provides basic abstractions for layout algorithms and related listeners, as well as a set of layout algorithm implementations. It is internally decomposed into the single Layout module.


Layout

  • bundle: org.eclipse.gef4.layout

The Layout module of the GEF4 Layout component provides an interface-based facade to exchange layout information with layout algorithms ({Root}), concrete implementations of layout algorithms (Algorithms), as well as listeners to hook into the layout computation (Listeners).


{Root}

  • package: org.eclipse.gef4.layout

Automatic layout is performed by ILayoutAlgorithm implementations. Each ILayoutAlgorithm is bound to an ILayoutContext, which provides all necessary information about what is to be layouted and how. The what is described in terms of IEntityLayout and IConnectionLayout abstractions, where an IEntityLayout may represent a simple node (INodeLayout) or a subgraph (ISubgraphLayout). An ILayoutFilter can be used to sort out layout abstractions (currently) not of relevance. Details about the what can be inferred from properties (LayoutProperties) that can be attributed to all layout abstractions. These can also be used to influence how the layout algorithm performs the layout.

GEF4-Layout-layout.png

ILayoutAlgorithm

ILayoutAlgorithm is the base abstraction for all layout algorithm implementations. An ILayoutAlgorithm needs a reference to an ILayoutContext, which provides information about what is to be layouted in terms of IEntityLayouts and IConnectionLayouts abstractions), which will have to be attributed in addition with respective properties that are required by the algorithm.

ILayoutContext, AbstractLayoutContext

An ILayoutContext provides the necessary context information needed by an ILayoutAlgorithm. The ILayoutContext is the central entry point for clients to trigger layout. It provides references to the IEntityLayout and IConnectionLayout representations that indicate what is to be layouted. These information is based on an underlying data model, for example, GEF4 Graph provides a graph data model for which GEF4 Zest provides an ILayoutContext implementation.

The ILayoutContext also contains references to a dynamic and static layout algorithm which may be applied. The difference between static and dynamic layout algorithms is that a dynamic layout algorithm is not re-initialized before applying the layout. Moreover, it supports notifying registered listeners upon changes to the context, i.e. addition/removal of nodes/edges, etc. This can be used by layout algorithms to update their internal state. Furthermore, it supports scheduling pre-layout-passes and post-layout-passes which are executed before or after applying a layout, respectively. These can, for example, be used to update the information which the ILayoutContext provides, prior to applying a layout, or transfering information back from the ILayoutContext to the underlying data model after applying a layout.

When applying a layout, the configured algorithm will include all layout entities (nodes and subgraphs) and edges returned by the ILayoutContext when computing the layout. Therefore, a context should only return those entities and edges which should be layed out. However, you do not need to remove all entities and edges from the context which should not be layed out, but can add an appropriate ILayoutFilter to the context which filters out all those entities and edges.

IEntityLayout, INodeLayout, ISubgraphLayout, IConnectionLayout

The IEntityLayout, INodeLayout, ISubgraphLayout, and IConnectionLayout abstractions represent layout entities (nodes and subgraphs), and edges between those entities. Usually, they are derived from an underlying data model. They provide a general property mechanism to store layout relevant data. The corresponding properties can be accessed using the LayoutProperties class.

ILayoutFilter

An ILayoutFilter is used to filter out layout entities and edges from an ILayoutContext, so that they are not returned by the context, and therefore, are not layed out. For example, this is how GEF4 Zest filters out hidden nodes and edges:

// add layout filter for hidden/layout irrelevant elements
final HidingModel hidingModel = getHost().getRoot().getViewer().getAdapter(HidingModel.class);
layoutContext.addLayoutFilter(new ILayoutFilter() {
	@Override
	public boolean isLayoutIrrelevant(IConnectionLayout connectionLayout) {
		return ZestProperties.getLayoutIrrelevant(((GraphEdgeLayout) connectionLayout).getEdge(), true)
			|| isLayoutIrrelevant(connectionLayout.getSource())
			|| isLayoutIrrelevant(connectionLayout.getTarget());
	}
	@Override
	public boolean isLayoutIrrelevant(INodeLayout nodeLayout) {
		org.eclipse.gef4.graph.Node node = (org.eclipse.gef4.graph.Node) nodeLayout.getItems()[0];
		return ZestProperties.getLayoutIrrelevant(node, true)
			|| hidingModel.isHidden(node);
	}
});

LayoutProperties

The LayoutProperties class defines the layout properties for ILayoutContext, IEntityLayout, INodeLayout, ISubgraphLayout, and IConnectionLayout, as well as accessors for those properties. Layout algorithms access these properties to read/write node locations and sizes, among other things.

public static void main(String[] args) {
	// create graph
	Graph graph = new Graph();
	Node n1 = new Node();
	n1.setGraph(graph);
	Node n2 = new Node();
	n2.setGraph(graph);
	graph.getNodes().addAll(Arrays.asList(new Node[] { n1, n2 }));
	Edge e = new Edge(n1, n2);
	e.setGraph(graph);
	// create layout context
	GraphLayoutContext context = new GraphLayoutContext(graph);
	// set layout bounds
	LayoutProperties.setBounds(context, new Rectangle(0, 0, 100, 100));
	// set node layout sizes
	LayoutProperties.setSize(context.getNodeLayout(n1), 25, 25);
	LayoutProperties.setSize(context.getNodeLayout(n2), 25, 25);
	// set layout algorithm
	context.setStaticLayoutAlgorithm(new SpringLayoutAlgorithm());
	// apply layout
	context.applyStaticLayout(true);
	// read locations after layout
	System.out.println("n1 at " + LayoutProperties.getLocation(context.getNodeLayout(n1)));
	System.out.println("n2 at " + LayoutProperties.getLocation(context.getNodeLayout(n2)));
}

Algorithms

  • package: org.eclipse.gef4.layout.algorithms

This package provides different implementations of concrete layout algorithms. There are a couple of simple algorithms that arrange nodes in a grid (GridLayoutAlgorithm), a single column or row (BoxLayoutAlgorithm), or which simply prevent overlapping of nodes (HorizontalShiftLayoutAlgorithm).

GEF4-Layout-algorithms-simple.png

There are also tree-based algorithms that arrange nodes in a classical (TreeLayoutAlgorithm) or radial tree (RadialLayoutAlgorithm), as well as a dedicated algorithm that optimizes folding and unfolding of sub-trees based on the available size (SpaceTreeLayoutAlgorithm).

GEF4-Layout-algorithms-treebased.png

Last, there is the implementation (SugiyamaLayoutAlgorithm) of a rank-based algorithm as published by Kozo Sugiyama, Shojiro Tagawa, and Mitsuhiko Toda in their paper about Methods for Visual Understanding of Hierarchical System Structures.

GEF4-Layout-algorithms-sugiyama.png

GridLayoutAlgorithm

A GridLayoutAlgorithm is a simple layout algorithm that places all elements into a grid, where the number of columns and rows is computed by the algorithm.

BoxLayoutAlgorithm

A BoxLayoutAlgorithm is a simple layout algorithm that places all elements in a single column or row, depending on a specifiable orientation.

SpringLayoutAlgorithm

GEF4-Layout-spring.png

HorizontalShiftLayoutAlgorithm

A HorizontalShiftLayoutAlgorithm is a simple layout algorithm that shifts overlapping nodes to the right.

TreeLayoutAlgorithm

The TreeLayoutAlgorithm was designed with the PDE Dependency Visualization in mind and is based on its layout algorithm. Initially only nodes without predecessors are expanded. Other nodes become visible if they have at least one direct predecessor which is visible and expanded. Collapsed nodes can have outcoming connections if the target node is visible because of a predecessor. There's an option to hide such connections.

Zest-tree-layout-dag.png

RadialLayoutAlgorithm

A RadialLayoutAlgorithm lays out a tree in a circular fashion, where the roots are located in the center.

GEF4-Layout-radial.png

SpaceTreeLayoutAlgorithm

The SpaceTreeLayoutAlgorithm keeps track of node positions all the time, always trying to form a nice tree structure. This means movement of nodes with the mouse is somehow restricted (you can move a node within its current layer, but only if it doesn't cause nodes to be pushed out of the graph area. When an expand operation is requested on a node, the node is centered and its subtree is shown, as long as there's enough space (other parts of the tree can be collapsed to extend available space).

Zest-tree-layout-spacetree.png

SugiyamaLayoutAlgorithm

GEF4-Layout-sugiyama.png


Listeners

  • package: org.eclipse.gef4.layout.listeners

GEF4-Layout-layoutlisteners.png


Migration from Zest 1.x to GEF4 Layout

The layout API that was part of Zest 1.x has been migrated into the GEF4 Layout component, where it has been reworked (see [#372365] for details).

Custom Layouts

To define custom layouts, instead of extending AbstractLayoutAlgorithm implement ILayoutAlgorithm (see example below and full code in CustomLayoutExample.java in the examples bundle).

ILayoutAlgorithm layoutAlgorithm = new ILayoutAlgorithm() {
  private ILayoutContext context;
 
  @Override
  public void applyLayout(boolean clean) {
    IEntityLayout[] entitiesToLayout = context.getEntities();
    int totalSteps = entitiesToLayout.length;
    double distance = LayoutProperties.getBounds(context).getWidth() / totalSteps;
    int xLocation = 0;
 
    for (int currentStep = 0; currentStep < entitiesToLayout.length; currentStep++) {
      IEntityLayout layoutEntity = entitiesToLayout[currentStep];
      LayoutProperties.setLocation(layoutEntity, xLocation,
      /* LayoutProperties.getLocation(layoutEntity).y */0);
      xLocation += distance;
    }
  }
 
  @Override
  public ILayoutContext getLayoutContext() {
    return context;
  }
 
  @Override
  public void setLayoutContext(ILayoutContext context) {
    this.context = context;
  }
};

Back to the top