| <!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>Layout Options (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>Layout Options</h1> |
| |
| <p>Layout options are key-value pairs that configure the behavior of automatic layout algorithms. Let’s look at all of the involved classes first before we concentrate on how to actually use them in practice.</p> |
| <h2 id="involved-classes">Involved Classes</h2> |
| <p>Layout options are represented by annotating objects with properties. There are two main types we need to cover: the properties themselves, and the objects we can configure through properties.</p> |
| <h3 id="properties">Properties</h3> |
| <p>The most important type when it comes to properties is the <code>IProperty</code> interface. Instances of that interface describe the abstract attributes of each kind of property has:</p> |
| <ol> |
| <li>An identifier that, well, identifies the kind of property.</li> |
| <li>A default value that is used if a property has not been explicitly set.</li> |
| <li>Optional lower and upper bounds that define the valid range of values for that property.</li> |
| </ol> |
| <p>Note the <code>IProperty</code> is actually <code>IProperty<T></code>, whose type parameter <code>T</code> corresponds to the type of the property’s values.</p> |
| <p>The most important implementation of <code>IProperty</code> is the <code>Property</code> class. Chances are you won’t have to provide your own implementation of <code>IProperty</code> since the <code>Property</code> class should cover all your needs.</p> |
| <h3 id="property-holders">Property Holders</h3> |
| <p>Classes that implement <code>IPropertyHolder</code> are basically maps from properties (described by <code>IProperty</code> instances) to property values (objects whose type depends on the property). All graph elements implement the <code>IPropertyHolder</code> interface. Thus, every graph element has properties associated with it.</p> |
| <p>Here’s one more detail that will become interesting when we talk about retrieving property values. We just said that property holders are maps from properties to property values. But if properties are described by <code>IProperty</code> instances, why not simply say that property holders map <code>IProperty</code> instances to property values? To answer that question we have to return to what actually identifies a property: its identifier. Accordingly, if multiple <code>IProperty</code> instances share the same identifier, they effectively describe the same property and are treated by property holders as such. Why this is important will become clearer once we get around to retrieving property values below.</p> |
| <h2 id="working-with-properties">Working With Properties</h2> |
| <p>There are two aspects of working with properties: accessing them (which is what both users and developers of layout algorithms usually do) and defining properties (which is what developers of layout algorithms sometimes do).</p> |
| <h3 id="setting-property-values">Setting Property Values</h3> |
| <p>To set a property’s value on a property holder, use this code:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">ElkGraphElement graphElement <span style="color:#f92672">=</span> <span style="color:#f92672">...;</span> |
| graphElement<span style="color:#f92672">.</span><span style="color:#a6e22e">setProperty</span><span style="color:#f92672">(</span>CoreOptions<span style="color:#f92672">.</span><span style="color:#a6e22e">DEBUG_MODE</span><span style="color:#f92672">,</span> <span style="color:#66d9ef">true</span><span style="color:#f92672">);</span> |
| </code></pre></div><p>Note that the available property objects used to set property values are</p> |
| <h3 id="retrieving-property-values">Retrieving Property Values</h3> |
| <p>To get hold of the properties of a graph element, use code such as this:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-java" data-lang="java">ElkGraphElement graphElement <span style="color:#f92672">=</span> <span style="color:#f92672">...;</span> |
| <span style="color:#75715e">// Note that we do not use CoreOptions to access the property |
| </span><span style="color:#75715e">// (see below for why that is) |
| </span><span style="color:#75715e"></span><span style="color:#66d9ef">boolean</span> debugMode <span style="color:#f92672">=</span> graphElement<span style="color:#f92672">.</span><span style="color:#a6e22e">getProperty</span><span style="color:#f92672">(</span>MyAlgorithmOptions<span style="color:#f92672">.</span><span style="color:#a6e22e">DEBUG_MODE</span><span style="color:#f92672">);</span> |
| </code></pre></div><p>Of course, since <code>IProperty</code> is a generic type, there is no explicit type casting involved here. Also, if the <code>MyAlgorithmOptions.DEBUG_MODE</code> property is not set on <code>graphElement</code>, the <code>getProperty(...)</code> method will simply return the property’s default value, which in this case is <code>false</code>. Why is it <code>false</code>, though? Where does the default value come from?</p> |
| <p>When the <code>getProperty(...)</code> method determines that the property whose value it should retrieve is not actually configured, it asks the passed <code>IProperty</code> instance for the default value to be returned. This has an important consequence. Consider the following code:</p> |
| <div class="highlight"><pre tabindex="0" 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">final</span> IProperty<span style="color:#f92672"><</span>Boolean<span style="color:#f92672">></span> FALSE_DEFAULT <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Property<span style="color:#f92672"><>(</span><span style="color:#e6db74">"an.excellent.example.property"</span><span style="color:#f92672">,</span> <span style="color:#66d9ef">false</span><span style="color:#f92672">);</span> |
| <span style="color:#66d9ef">final</span> IProperty<span style="color:#f92672"><</span>Boolean<span style="color:#f92672">></span> TRUE_DEFAULT <span style="color:#f92672">=</span> <span style="color:#66d9ef">new</span> Property<span style="color:#f92672"><>(</span><span style="color:#e6db74">"an.excellent.example.property"</span><span style="color:#f92672">,</span> <span style="color:#66d9ef">true</span><span style="color:#f92672">);</span> |
| |
| <span style="color:#75715e">// Setting the property value to null effectively undefines the |
| </span><span style="color:#75715e">// property for the property holder |
| </span><span style="color:#75715e"></span>propertyHolder<span style="color:#f92672">.</span><span style="color:#a6e22e">setProperty</span><span style="color:#f92672">(</span>FALSE_DEFAULT<span style="color:#f92672">,</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">);</span> |
| System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span>propertyHolder<span style="color:#f92672">.</span><span style="color:#a6e22e">getProperty</span><span style="color:#f92672">(</span>FALSE_DEFAULT<span style="color:#f92672">));</span> |
| propertyHolder<span style="color:#f92672">.</span><span style="color:#a6e22e">setProperty</span><span style="color:#f92672">(</span>FALSE_DEFAULT<span style="color:#f92672">,</span> <span style="color:#66d9ef">null</span><span style="color:#f92672">);</span> |
| System<span style="color:#f92672">.</span><span style="color:#a6e22e">out</span><span style="color:#f92672">.</span><span style="color:#a6e22e">println</span><span style="color:#f92672">(</span>propertyHolder<span style="color:#f92672">.</span><span style="color:#a6e22e">getProperty</span><span style="color:#f92672">(</span>TRUE_DEFAULT<span style="color:#f92672">));</span> |
| </code></pre></div><p>This code will produce the following output:</p> |
| <div class="highlight"><pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-plain" data-lang="plain">false |
| true |
| </code></pre></div><p>This means that you can define multiple <code>IProperty</code> instances that describe the same property, but with different default values. That seems like an inconsistency, but it has an important reason. The layout options known to the Eclipse Layout Kernel are registered with the <code>LayoutMetaDataService</code>. Most are registered with a global default value. Layout algorithms declare which of those options they support, and in doing so can override that default value. Accordingly, they need their own <code>IProperty</code> instance with their own default value to retrieve property values. This is why the ELK metadata tooling generates a separate layout metadata provider for each layout algorithm, complete <code>IProperty</code> objects for each supported layout option to retrieve its value with. Which <code>IProperty</code> object is used to <em>set</em> the property value does not matter, though.</p> |
| <p>That is the reason why the first example above does not use <code>CoreOptions.DEBUG_MODE</code> to retrieve the property value, but <code>MyAlgorithmOptions.DEBUG_MODE</code> (where <code>MyAlgorithmOptions</code> is the metadata class generated for your layout algorithm).</p> |
| <h3 id="checking-for-the-presence-of-property-values">Checking for the Presence of Property Values</h3> |
| <p>We can always call <code>getProperty(...)</code> on a graph element and get a (more or less) sensible result, but we may not be able to distinguish a default value from a value explicitly set on that element. If we need to, we can check whether a property was explicitly set through <code>hasProperty(...)</code>:</p> |
| <div class="highlight"><pre tabindex="0" 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">if</span> <span style="color:#f92672">(</span>propertyHolder<span style="color:#f92672">.</span><span style="color:#a6e22e">hasProperty</span><span style="color:#f92672">(</span>MyAlgorithmOptions<span style="color:#f92672">.</span><span style="color:#a6e22e">OPTIONAL_GIZMO</span><span style="color:#f92672">))</span> <span style="color:#f92672">{</span> |
| Gizmo g <span style="color:#f92672">=</span> propertyHolder<span style="color:#f92672">.</span><span style="color:#a6e22e">getProperty</span><span style="color:#f92672">(</span>MyAlgorithmOptions<span style="color:#f92672">.</span><span style="color:#a6e22e">OPTIONAL_GIZMO</span><span style="color:#f92672">);</span> |
| <span style="color:#f92672">}</span> |
| </code></pre></div><h2 id="defining-properties">Defining Properties</h2> |
| <p>Most of the time, algorithm developers do not have to worry about declaring their own <code>IProperty</code> objects. The options officially supported by a layout algorithm constitute a part of the algorithm’s interface and metadata and are thus declared in the algorithm’s <a href="../../../documentation/algorithmdevelopers/metadatalanguage.html">metadata file</a>. The ELK SDK automatically generates the required <code>IProperty</code> instances.</p> |
| <p>The only time custom <code>IProperty</code> instances have to be declared is when an algorithm uses internal properties during its execution to pass information between its different phases. Internal options do not have to be declared anywhere since they are not supposed to be set by users anyway. To define such options, simply add new <code>Property</code> instances to any one of your internally used classes. Use these instances to set and retrieve options.</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 active"> |
| 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"> |
| 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 © 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> |