Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 10 Next »

We haven't finished writing this page yet.

This page describes how automatic layout can be configured for a given application. This includes how layout options can be set on graph elements, and how they are applied by KIML during the layout process. After having read this, you should be able to answer the following questions:

  • What are layout options?
  • How do layout algorithms support layout options?
  • How do layout options end up in KGraph elements?
  • How can I set layout options on elements programmatically?

This page does not list the available layout options, and neither does it explain any of them. You can find a list of layout options provided by KIML over here.

 

Contents

Layout Options and What They Are Good For

Even the most basic layout algorithm provides some settings for you to play with. This might be something as simple as the space left between different nodes, or something as complex as changing how node labels are placed and how that influences the size of each node. Each such setting must be registered with KIML as a layout option, and each algorithm must specify exactly which of these options it supports. Registering a layout option is done through one of KIML's extension points and can look like this:

<extension point="de.cau.cs.kieler.kiml.layoutProviders">
    <layoutOption
        id="de.cau.cs.kieler.nodeLabelPlacement"
        name="Node Label Placement"
        description="Hints for where node labels are to be placed; if empty, the node label's position is not modified."
        advanced="true"
        appliesTo="nodes"
        type="enumset"
        class="de.cau.cs.kieler.kiml.options.NodeLabelPlacement"
        default="">
    </layoutOption>
</extension>

Let's walk through the parameters available for layout options (not every available parameter appears in the example above):

  • id – A unique identifier for this layout option. It is recommended that the identifier be prefixed by the plug-in name, to guarantee uniqueness.
  • type – Defines the data type of this option; must be either boolean, string, int, float, enum, enumset, or object. The types enum, enumset, and object require the class attribute to be set.
  • name – A user friendly name of this layout option, to be displayed in the UI.
  • description – A user friendly description of this layout option, to be displayed in the UI. The description should contain all information needed to understand what this option does.
  • advanced – Whether the option should only be shown in advanced mode in the layout view; default is false.
  • appliesTo – A comma separated list of targets on which the layout option can be applied; a target can be either parents (for nodes that contain further nodes), nodes (for all nodes regardless of whether they contain further nodes or not), edges, ports, or labels. If omitted, the layout option is not shown to the user in the layout view, which is a good thing for options that will be set programmatically anyway.
  • class – An optional Java class giving more detail on the data type. For enum and enumset options this attribute must hold the Enum class of the option. For object options it must hold the class name of an IDataObject implementation.
  • default – The default value to use when no other value can be determined for this option.
  • lowerBound – An optional lower bound on the values of this layout option. This is used when a layout configuration is determined automatically.
  • upperBound – An optional upper bound on the values of this layout option. This is used when a layout configuration is determined automatically.
  • variance – An optional variance for values of this layout option. This is used when a layout configuration is determined automatically. The variance is taken as multiplier for Gaussian distributions when new values are determined. Options with uniform distibution, such as Boolean or enumeration types, do not need a variance value, since all values have equal probability. A variance of 0 implies that the option shall not be used in automatic configuration, regardless of its type.

ToDo

Provide a better explanation of what the latter three parameters are used for. Are they only relevant to evolutionary layout?

If a layout algorithm supports a particular layout option, it must tell KIML so. Here's an example:

<extension point="de.cau.cs.kieler.kiml.layoutProviders">
    <layoutAlgorithm ...>
        <knownOption
            option="de.cau.cs.kieler.borderSpacing"
            default="20">
        </knownOption>
    </layoutAlgorithm>
</extension>

This tells KIML that the defined layout algorithm supports the border spacing option. And even more, it overrides the default value declared by the layout option and sets it to 20.

The Layout Options Manager

By now, we have an idea of what layout options do and why they are important in the first place. However, we haven't looked at how layout options end up on KGraph elements yet. This is where the LayoutOptionsManager comes in.

The KIML page has a high-level explanation of what happens when during the layout process. To take a look at it if you haven't already – it will make the following concepts easier to understand. Plus, there's a nice picture that took Miro quite some time to create.

After a layout manager has finished turning a given diagram into its KGraph representation, the layout options manager is asked to enrich the KGraph elements with layout options. The option values can come from different sources: the user might have set some using the layout view; there might be some defaults for certain kinds of diagrams; or the programmer might have decided to attach some layout options to certain elements for just this one layout run. Whatever the source, the options manager is in charge of collecting all these layout option values and making sure they find their way to the correct KGraph element. To start off with a clean plate, it first makes sure there are no layout options attached to the KGraph elements. It then does two things: collect every eligible source of layout options, and transfer layout options to the correct KGraph elements. Sounds easy enough.

Since the options manager starts by removing all layout options set on graph elements, setting layout options on the graph elements in the layout manager is a futile endeavor.

The question remains how the layout options sources work. Each source is represented by a class that implements the ILayoutConfig interface, called a layout configuration. KIML currently provides the following layout configurations, each representing a particular source of layout options:

  • DefaultLayoutConfig – Sets fixed default values defined for layout options.
  • EclipseLayoutConfig – Users can define default layout options to be set on elements that meet certain criteria via the KIML preference page. This layout configuration takes these options and applies them.
  • SemanticLayoutConfigDOCUMENT THIS
  • GmfLayoutConfig / GraphitiLayoutConfig – These configurations apply layout options set by the user in the layout view or stored in the notation model file of a diagram.
  • VolatileLayoutConfig – A configuration whose only purpose it is to make sure certain layout options are set on certain diagram elements in a particular layout run.

The options manager collects all available and applicable layout configurations and sorts them by priority (incidentally, the configurations were sorted by increasing priority just now). For every graph element, each configuration is asked to provide layout options, starting with the default layout configuration and working through the priority chain.

A Few Details on Layout Configurations

What we just learned is a bit of a simplification of what happens. Before we look at the details, let's take a look at the methods each layout configuration provides:

public interface ILayoutConfig {
    int getPriority();
    void enrich(LayoutContext context);
    Object getValue(LayoutOptionData<?> optionData, LayoutContext context);
    void transferValues(KLayoutData layoutData, LayoutContext context);
} 

It is not hard to guess what getPriority() does: it returns the priority a given layout configuration has. If two layout configurations set a layout option to different values on a given graph element, the value set by the configuration with higher priority wins. The other three methods look a bit more obscure, so we have to provide more details on what the options manager does, exactly.

ENRICHING (+ WHAT IS A LAYOUT CONTEXT)

The transferValues(...) method is the main workhorse of the interface. This is where a KGraph element, identified by the given layout context, is equipped with the layout option values a layout configuration deems necessary. It thus becomes the most important part of a layout configuration that you absolutely have to implement, no excuses. If for example every KNode should have its port constraints set to FIXED_POS, this is the place to do it.

With all these layout configurations active, it's by no means clear which layout option values KGraph elements will end up with during the layout process. Enter the getValue(...) method. For a given element and layout option, it returns the value it would set on the element if transferValues(...) was called. This method is mainly used by the Layout view to inform the user about the layout option values of whatever graph element he (or she) has clicked on. It is also the method you can safely neglect to implement if your final product won't include the layout view anyway.

Implementing a Layout Configuration

ToDo

deciding what options are applicable depending on the context object; setting the options;


Programmatically Setting Layout Options

ToDo

Write this section. This will be about when to use the different kinds of layout configurations, mainly SemanticLayoutConfig and VolatileLayoutConfig.


  • No labels