blob: 40518ad37e5b435cac9f82bf70d73286823aa9d2 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="icon" type="image/svg+xml" href="img/elk_fav.svg">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<link rel="stylesheet" href="https://www.eclipse.org/elk/css/elk.css">
<link rel="stylesheet" href="https://www.eclipse.org/elk/css/prism.css">
<title>Connecting to ELK (ELK)</title>
</head>
<body>
<nav class="navbar navbar-expand-lg navbar-dark">
<button class="navbar-toggler navbar-toggler-right" type="button" data-toggle="collapse" data-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="https://www.eclipse.org/elk/">
<img src="img/elk_small_light.svg" height="30" class="d-inline-block align-top mr-1" alt="">
Eclipse Layout Kernel
</a>
<div class="collapse navbar-collapse" id="navbarCollapse">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link" href="../../../downloads.html">Downloads</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../../../gettingstarted.html">Getting Started</a>
</li>
<li class="nav-item active">
<a class="nav-link" href="../../../documentation.html">Documentation <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="../../../reference.html">Reference</a>
</li>
<li class="nav-item">
<a class="nav-link" href="../../../support.html">Support</a>
</li>
<li class="nav-item">
<a class="nav-link" href="https://github.com/eclipse/elk">GitHub</a>
</li>
</ul>
</div>
</nav>
<div class="container px-3 py-5">
<div class="row">
<div class="col-sm-9">
<h1>Connecting to ELK</h1>
<p>In our <a href="../../../documentation/tooldevelopers/usingeclipselayout.html">our basic introduction to automatic layout in Eclipse</a>, we have seen how the diagram layout engine needs someone to extract a proper ElkGraph from whatever layout is invoked on. This is what you, as a tool developer, have to supply. While there are already implementations for different graph editing frameworks to build upon, this page describes how doing so from scratch works.</p>
<p>To connect to ELK, there are two things you will have to do:</p>
<ol>
<li>Create an <code>ILayoutSetup</code> implementation and register it with our extension point.</li>
<li>Create an <code>IDiagramLayoutConnector</code> implementation.</li>
</ol>
<p>The rest of this page will look at each of these in turn.</p>
<h2 id="the-layout-setup">The Layout Setup</h2>
<p>An <code>ILayoutSetup</code> implementation consists of just two methods:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">boolean</span> <span style="color:#a6e22e">supports</span><span style="color:#f92672">(</span>Object object<span style="color:#f92672">);</span>
Injector <span style="color:#a6e22e">createInjector</span><span style="color:#f92672">(</span>Module defaultModule<span style="color:#f92672">);</span>
</code></pre></div><p>To be able to implement the interface, you may have to add a dependency to <code>org.eclipse.elk.core.service</code> to your project. Then register your layout setup with the <code>org.eclipse.elk.core.service.layoutConnectors</code> extension point.</p>
<h3 id="the-supports-method">The <code>supports(...)</code> Method</h3>
<p>This method is called by the diagram layout engine to determine if a given setup instance supports extracting an ElkGraph from the given object. The question now of course becomes what that object is. There are two cases. In the first case, it will be an implementation of <code>IWorkbenchPart</code>. This is the case if layout is invoked on a diagram editor. If the setup states that it supports that workbench part, the diagram layout connector it supplies knows how to get its hands at the editor&rsquo;s content and how to turn that content into an ElkGraph. In the second case, the object passed to <code>supports(...)</code> will be an object from that editor&rsquo;s content. For GMF editors, this will be an implementation of <code>IGraphicalEditPart</code>.</p>
<p>A typical implementation of this method will look something like this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">public</span> <span style="color:#66d9ef">boolean</span> <span style="color:#a6e22e">supports</span><span style="color:#f92672">(</span><span style="color:#66d9ef">final</span> Object object<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
<span style="color:#75715e">// This method may be invoked on a whole collection of elements selected
</span><span style="color:#75715e"></span> <span style="color:#75715e">// in an editor
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>object <span style="color:#66d9ef">instanceof</span> Collection<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
<span style="color:#75715e">// Check if we support layout on at least one of the selected objects
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">for</span> <span style="color:#f92672">(</span>Object o <span style="color:#f92672">:</span> <span style="color:#f92672">(</span>Collection<span style="color:#f92672">&lt;?&gt;)</span> object<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
<span style="color:#66d9ef">if</span> <span style="color:#f92672">(</span>o <span style="color:#66d9ef">instanceof</span> SomeDiagramElementClassWeSupport<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">true</span><span style="color:#f92672">;</span>
<span style="color:#f92672">}</span>
<span style="color:#f92672">}</span>
<span style="color:#66d9ef">return</span> <span style="color:#66d9ef">false</span><span style="color:#f92672">;</span>
<span style="color:#f92672">}</span>
<span style="color:#75715e">// If it is not a collection, it may be either a workbench part we support
</span><span style="color:#75715e"></span> <span style="color:#75715e">// or the diagram element class we already checked for above
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">return</span> object <span style="color:#66d9ef">instanceof</span> WorkbenchPartImplementation
<span style="color:#f92672">||</span> object <span style="color:#66d9ef">instanceof</span> SomeDiagramClassWeSupport<span style="color:#f92672">;</span>
<span style="color:#f92672">}</span>
</code></pre></div><h3 id="the-createinjector-method">The <code>createInjector(...)</code> Method</h3>
<p>If the diagram layout engine has determined which setup supports layout on a given object, it will use that setup to get its hands on an injector that can supply implementations of the different components involved in the layout process. The most important of these is an implementation of <code>IDiagramLayoutConnector</code>, which we will look at in a minute. A typical implementation will look something like this:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java"><span style="color:#66d9ef">public</span> Injector <span style="color:#a6e22e">createInjector</span><span style="color:#f92672">(</span><span style="color:#66d9ef">final</span> Module defaultModule<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
<span style="color:#75715e">// Modules basically provide a mapping between types and implementations
</span><span style="color:#75715e"></span> <span style="color:#75715e">// to instantiate whenever an instance of the type is requested. We use
</span><span style="color:#75715e"></span> <span style="color:#75715e">// the default module supplied by ELK and override that with custom
</span><span style="color:#75715e"></span> <span style="color:#75715e">// overrides to get our IDiagramLayoutConnector to enter the picture.
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">return</span> Guice<span style="color:#f92672">.</span><span style="color:#a6e22e">createInjector</span><span style="color:#f92672">(</span>
Modules<span style="color:#f92672">.</span><span style="color:#a6e22e">override</span><span style="color:#f92672">(</span>defaultModule<span style="color:#f92672">).</span><span style="color:#a6e22e">with</span><span style="color:#f92672">(</span><span style="color:#66d9ef">new</span> AwesomeLayoutModule<span style="color:#f92672">()));</span>
<span style="color:#f92672">}</span>
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">static</span> <span style="color:#66d9ef">class</span> <span style="color:#a6e22e">AwesomeLayoutModule</span> <span style="color:#66d9ef">implements</span> Module <span style="color:#f92672">{</span>
<span style="color:#a6e22e">@Override</span>
<span style="color:#66d9ef">public</span> <span style="color:#66d9ef">void</span> <span style="color:#a6e22e">configure</span><span style="color:#f92672">(</span><span style="color:#66d9ef">final</span> Binder binder<span style="color:#f92672">)</span> <span style="color:#f92672">{</span>
<span style="color:#75715e">// This is the most important binding
</span><span style="color:#75715e"></span> binder<span style="color:#f92672">.</span><span style="color:#a6e22e">bind</span><span style="color:#f92672">(</span>IDiagramLayoutConnector<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">)</span>
<span style="color:#f92672">.</span><span style="color:#a6e22e">to</span><span style="color:#f92672">(</span>MyAwesomeDiagramLayoutConnector<span style="color:#f92672">.</span><span style="color:#a6e22e">class</span><span style="color:#f92672">);</span>
<span style="color:#f92672">}</span>
<span style="color:#f92672">}</span>
</code></pre></div><p>An implementation can of course add more bindings. See our section on dependency injection for more information on what makes sense here.</p>
<h2 id="the-layout-connector">The Layout Connector</h2>
<p>An <code>IDiagramLayoutConnector</code> implementation consists of the following methods:</p>
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">LayoutMapping <span style="color:#a6e22e">buildLayoutGraph</span><span style="color:#f92672">(</span>IWorkbenchPart workbenchPart<span style="color:#f92672">,</span> Object diagramPart<span style="color:#f92672">);</span>
<span style="color:#66d9ef">void</span> <span style="color:#a6e22e">applyLayout</span><span style="color:#f92672">(</span>LayoutMapping mapping<span style="color:#f92672">,</span> IPropertyHolder settings<span style="color:#f92672">);</span>
</code></pre></div><p>These methods pretty much correspond to the beginning and the end of the layout process: extracting the layout graph from whatever layout is invoked on, and applying the layout information back to the diagram. Let&rsquo;s take a look at how these methods should be implemented.</p>
<h3 id="the-buildlayoutgraph-method">The <code>buildLayoutGraph(...)</code> Method</h3>
<p>This is the method that turns a diagram into an ElkGraph that ELK can then work with. It produces an instance of the <code>LayoutMapping</code> class, which contains information so important to the layout process that we should list them all:</p>
<ul>
<li>The root of the created ElkGraph. This is what is later fed into the recursive diagram layout engine to run automatic layout on.</li>
<li>The top-level diagram part that layout was originally invoked on. This will usually be something that represents the diagram or a part of it in the diagram editor (think <code>IGraphicalEditPart</code> for GMF).</li>
<li>A bi-directional mapping between diagram parts and the ElkGraph elements that were created for them. This is probably the most important bit: it will later allow us to apply the layout information contained in the ElkGraph back to the correct diagram elements.</li>
<li>The workbench part layout was invoked on, if any. Admittedly, this is less important, which is why it comes last in this list.</li>
</ul>
<p>Since this method determines the structure of the graph layout algorithms will be run on, it is what has the most impact on what your results will look like. It is thus a good idea to spend some time (and thought) on how to implement it. You should think about the following two aspects: the layout graph&rsquo;s structure, and the layout configuration.</p>
<p>Regarding the layout graph&rsquo;s structure, the main task is to decide which of your diagram elements map to which kinds of layout graph elements. Should an element be represented as a node? Is it a label? Should my nodes have explicit points for edges to attach to? Do certain nodes contain other nodes? Which diagram elements need to be represented in the layout graph in the first place?</p>
<p>Regarding the layout configuration, your layout connector is expected to build a fully configured ElkGraph (except for some advanced configuration issues, which we will look at on another page). This primarily includes setting the correct layout options that yield the results you want. However, this may also include writing the current coordinates of diagram elements into the ElkGraph. This is mostly important for what we call <em>interactive layout algorithms</em>: layout algorithms that take current positions into account when calculating new ones instead of simply calculating new coordinates from scratch.</p>
<h3 id="the-applylayout-method">The <code>applyLayout(...)</code> Method</h3>
<p>This method accepts two arguments: the <code>LayoutMapping</code> created by <code>buildLayoutGraph(...)</code>, and an <code>IPropertyHolder</code> that may hold additional options controlling the layout process. These options will usually include things such as whether the application of the layout should be animated and whether the diagram zoomed and positioned such that it is completely visible in the editor.</p>
<p>The most important thing the <code>applyLayout(...)</code> implementation will do is to iterate over the diagram elements and to apply the layout results back to them. At best, this just means copying values over. At worst, this will include transforming coordinates from the ElkGraph coordinate system back to whatever coordinate system the diagram editor uses.</p>
</div>
<div class="secnav col-sm-3">
<ul>
<a href="../../../documentation/tooldevelopers.html">
<li class="navlevel-1">
Tool Developers
</li>
</a>
<a href="../../../documentation/tooldevelopers/graphdatastructure.html">
<li class="navlevel-2">
Graph Data Structure
</li>
</a>
<a href="../../../documentation/tooldevelopers/graphdatastructure/coordinatesystem.html">
<li class="navlevel-3">
Coordinate System
</li>
</a>
<a href="../../../documentation/tooldevelopers/graphdatastructure/layoutoptions.html">
<li class="navlevel-3">
Layout Options
</li>
</a>
<a href="../../../documentation/tooldevelopers/graphdatastructure/jsonformat.html">
<li class="navlevel-3">
JSON Format
</li>
</a>
<a href="../../../documentation/tooldevelopers/graphdatastructure/elktextformat.html">
<li class="navlevel-3">
ELK Text Format
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingalgorithmsdirectly.html">
<li class="navlevel-2">
Using Algorithms Directly
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingplainjavalayout.html">
<li class="navlevel-2">
Using Plain Java Layout
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingeclipselayout.html">
<li class="navlevel-2">
Using Eclipse Layout
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingeclipselayout/connectingtoelk.html">
<li class="navlevel-3 active">
Connecting to ELK
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingeclipselayout/advancedconfiguration.html">
<li class="navlevel-3">
Advanced Configuration
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingeclipselayout/layoutviewsupport.html">
<li class="navlevel-3">
Layout View Support
</li>
</a>
<a href="../../../documentation/tooldevelopers/usingeclipselayout/dependencyinjection.html">
<li class="navlevel-3">
Dependency Injection
</li>
</a>
<a href="../../../documentation/algorithmdevelopers.html">
<li class="navlevel-1">
Algorithm Developers
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/gettingeclipseready.html">
<li class="navlevel-2">
Getting Eclipse Ready
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/creatinganewproject.html">
<li class="navlevel-2">
Creating a New Project
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/metadatalanguage.html">
<li class="navlevel-2">
ELK Metadata Language
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/metadatalanguage/automaticbuilds.html">
<li class="navlevel-3">
Automatic Builds
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/algorithmimplementation.html">
<li class="navlevel-2">
Algorithm Implementation
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/algorithmimplementation/algorithmstructure.html">
<li class="navlevel-3">
Structuring Algorithms
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/algorithmdebugging.html">
<li class="navlevel-2">
Algorithm Debugging
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/randomgraphs.html">
<li class="navlevel-2">
Random Graph Generation
</li>
</a>
<a href="../../../documentation/algorithmdevelopers/unittesting.html">
<li class="navlevel-2">
Unit Tests
</li>
</a>
<a href="../../../documentation/contributors.html">
<li class="navlevel-1">
ELK Contributors
</li>
</a>
<a href="../../../documentation/contributors/developmentsetup.html">
<li class="navlevel-2">
Development Setup
</li>
</a>
<a href="../../../documentation/contributors/developmentworkflow.html">
<li class="navlevel-2">
Development Workflow
</li>
</a>
<a href="../../../documentation/contributors/developmentworkflow/installingwithoomph.html">
<li class="navlevel-3">
Installing With Oomph
</li>
</a>
<a href="../../../documentation/contributors/buildingelk.html">
<li class="navlevel-2">
Building ELK
</li>
</a>
</ul>
<div class="incubation-egg">
<a href="https://www.eclipse.org/projects/what-is-incubation.php">
<img src="https://www.eclipse.org/images/egg-incubation.png" alt="Incubation" />
</a>
</div>
</div>
</div>
</div>
<footer role="contentinfo" class="footer">
<div class="container">
<div class="row">
<div class="col">
<span class="hidden-print">
<a href="https://www.eclipse.org"><img class="logo-eclipse-white img-responsive" alt="logo" src="../../../img/eclipse_foundation_logo.svg"/></a>
</span>
</div>
<div class="col">
</div>
</div>
<div class="row">
<div class="col hidden-print">
<a href="http://www.eclipse.org/">Eclipse Foundation</a><br/>
<a href="http://www.eclipse.org/legal/privacy.php">Privacy Policy</a><br/>
<a href="http://www.eclipse.org/legal/termsofuse.php">Website Terms of Use</a><br/>
<a href="http://www.eclipse.org/legal/copyright.php">Copyright Agent</a><br/>
<a href="http://www.eclipse.org/legal">Legal</a>
</div>
<div class="col">
<p class="copyright-text">Copyright &copy; Eclipse Foundation, Inc. All Rights Reserved.</p>
</div>
</div>
</div>
</footer>
<script src="https://code.jquery.com/jquery-3.1.1.slim.min.js" integrity="sha384-A7FZj7v+d/sdmMqp/nOQwliLvUsJfDHW+k9Omg/a/EheAdgtzNs3hpfag6Ed950n" crossorigin="anonymous"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/tether/1.4.0/js/tether.min.js" integrity="sha384-DztdAPBWPRXSA/3eYEEUWrWCy7G5KFbe8fFjk5JAIxUYHKkDx6Qin1DkWx51bBrb" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
<script src="https://www.eclipse.org/elk/js/prism.js"></script>
<script>$(function() { $('table').addClass('table'); })</script>
</body>
</html>