# Layout Options

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.

## Involved Classes

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.

### Properties

The most important type when it comes to properties is the `IProperty` interface. Instances of that interface describe the abstract attributes of each kind of property has:

1. An identifier that, well, identifies the kind of property.
2. A default value that is used if a property has not been explicitly set.
3. Optional lower and upper bounds that define the valid range of values for that property.

Note the `IProperty` is actually `IProperty<T>`, whose type parameter `T` corresponds to the type of the property’s values.

The most important implementation of `IProperty` is the `Property` class. Chances are you won’t have to provide your own implementation of `IProperty` since the `Property` class should cover all your needs.

### Property Holders

Classes that implement `IPropertyHolder` are basically maps from properties (described by `IProperty` instances) to property values (objects whose type depends on the property). All graph elements implement the `IPropertyHolder` interface. Thus, every graph element has properties associated with it.

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 `IProperty` instances, why not simply say that property holders map `IProperty` instances to property values? To answer that question we have to return to what actually identifies a property: its identifier. Accordingly, if multiple `IProperty` 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.

## Working With Properties

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).

### Setting Property Values

To set a property’s value on a property holder, use this code:

    ElkGraphElement graphElement = ...;
    graphElement.setProperty(CoreOptions.DEBUG_MODE, true);

Note that the available property objects used to set property values are

### Retrieving Property Values

To get hold of the properties of a graph element, use code such as this:

    ElkGraphElement graphElement = ...;
    // Note that we do not use CoreOptions to access the property
    // (see below for why that is)
    boolean debugMode = graphElement.getProperty(MyAlgorithmOptions.DEBUG_MODE);

Of course, since `IProperty` is a generic type, there is no explicit type casting involved here. Also, if the `MyAlgorithmOptions.DEBUG_MODE` property is not set on `graphElement`, the `getProperty(...)` method will simply return the property’s default value, which in this case is `false`. Why is it `false`, though? Where does the default value come from?

When the `getProperty(...)` method determines that the property whose value it should retrieve is not actually configured, it asks the passed `IProperty` instance for the default value to be returned. This has an important consequence. Consider the following code:

    final IProperty<Boolean> FALSE_DEFAULT = new Property<>("an.excellent.example.property", false);
    final IProperty<Boolean> TRUE_DEFAULT = new Property<>("an.excellent.example.property", true);

    // Setting the property value to null effectively undefines the
    // property for the property holder
    propertyHolder.setProperty(FALSE_DEFAULT, null);
    System.out.println(propertyHolder.getProperty(FALSE_DEFAULT));
    propertyHolder.setProperty(FALSE_DEFAULT, null);
    System.out.println(propertyHolder.getProperty(TRUE_DEFAULT));

This code will produce the following output:

    false
    true

This means that you can define multiple `IProperty` 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 `LayoutMetaDataService`. 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 `IProperty` 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 `IProperty` objects for each supported layout option to retrieve its value with. Which `IProperty` object is used to set the property value does not matter, though.

That is the reason why the first example above does not use `CoreOptions.DEBUG_MODE` to retrieve the property value, but `MyAlgorithmOptions.DEBUG_MODE` (where `MyAlgorithmOptions` is the metadata class generated for your layout algorithm).

### Checking for the Presence of Property Values

We can always call `getProperty(...)` 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 `hasProperty(...)`:

    if (propertyHolder.hasProperty(MyAlgorithmOptions.OPTIONAL_GIZMO)) {
        Gizmo g = propertyHolder.getProperty(MyAlgorithmOptions.OPTIONAL_GIZMO);
    }

## Defining Properties

Most of the time, algorithm developers do not have to worry about declaring their own `IProperty` 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 metadata file. The ELK SDK automatically generates the required `IProperty` instances.

The only time custom `IProperty` 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 `Property` instances to any one of your internally used classes. Use these instances to set and retrieve options.

- Tool Developers
- Graph Data Structure
- Coordinate System
- Layout Options
- JSON Format
- ELK Text Format
- Using Algorithms Directly
- Using Plain Java Layout
- Using Eclipse Layout
- Connecting to ELK
- Advanced Configuration
- Layout View Support
- Dependency Injection
- Algorithm Developers
- Getting Eclipse Ready
- Creating a New Project
- ELK Metadata Language
- Automatic Builds
- Algorithm Implementation
- Structuring Algorithms
- Algorithm Debugging
- Random Graph Generation
- Unit Tests
- ELK Contributors
- Development Setup
- Development Workflow
- Installing With Oomph
- Building ELK