hobdrive-docs

HobDrive Layout Specification

Index English Russian

This document collects the layout tags, attributes and options used by HobDrive UI layout files.

Table of Contents

Layout Contract

Top-level tags

Example:

<include file="default-tripcomp.layout" if='${!sexists("GasTrigger")}'/>

section

Defines a logical screen/page block. Common attributes:

Example:

<section name="GPS">
  ...
</section>
<section name="Fuel Trims" if="STFT1">
  ...
</section>

config elements

Example:

<config id="Layout_ECUFuel" type="bool" default="false"
        title="Use Fuel Level data from ECU"
        descr="If enabled - fuel level will be shown from ECU. Otherwise - estimated from fuel consumption"
        title-ru="Показывать уровень топлива из ЭБУ"
        descr-ru="Если включено - уровень топлива будет браться из ЭБУ. Иначе - показывается оценочный уровень топлива"/>

Layout containers

Example (cycle temperature sensors every 4 seconds):

<switch if='${Layout_RollTemp = true}' index='$${ svalue("DateTime") / 4000 }'>
  <item id="ATFTemp" .../>
  <item id="CVTTemp" .../>
  <item id="EngineOilTemp" .../>
</switch>

item

Represents a widget in a grid or stack. Common attributes and usages:

Example usages:

<item id="FuelLevel" if='${Layout_ECUFuel != true}' inherit="_FuelIndicator, _EditAction" onclick="NewFueling"/>
<item id="Odometer" if="${Layout_ECU_Odometer != true}" actions="SetupOdometer" size="large" inherit="_EditAction"/>

Examples:

Special item types

  • type=”button” — clickable button. Use action=”invoke(NAME)” to call ECU/service action.
  • type=”static” — static text block. E.g. type="static" size="micro"
  • gauge / chart / image decorators — declared either as item with nested decorators or in gauge/theme files; can accept decorators.

Decorators and nested elements

item may contain nested decorators. Example syntax:

image decorator

Attributes: image-zorder, image-path, image-scale, image-width, image-height, image-rotate (can contain dynamic expressions).

Many attributes can accept dynamic expressions such as image-rotate='$${ Sensor_Value - 45 }'.

progress decorator

<item id="Speed" decorator-10="touch-progress"/>

This is a system decorator, used to draw dynamic line on press.

tile decorator

<item id="Speed" decorator-10="tile"/>

Draws a tile behind the gauge.

padding decorator

Padding decorator is used to “pad” space in iitem. Values are for TOP, RIGHT, BOTTOM, LEFT.

You can use percentage values.

<item id="Speed">
    <padding padding="0 0 0 120"/>
</item/>

crop decorator

Crop decorator cuts (hides) part of the previously rendered widget.

<item id="Test" border-opacity="1" type='roundbar' red-green="150,0">
  <crop crop="10% 10% 10% 10%"/>
</item>

visibile / visibility decorator

This decorator just enables/disables drawing in runtime. You can use dynamic $$ evaluation.

<item id="AT_R" visibility='$${Sensor_Value}'/>

filter decorator

The filter decorator is a powerful tool for applying visual effects and transformations to UI elements. It supports both draw effects (visual filters) and matrix transformations (geometric changes).

Attributes

  • effect — semicolon-separated list of filter functions to apply. Each filter is a function call with parameters.
  • mode — controls when the filter is applied in the rendering pipeline:
    • before — applies filter before rendering the target element, then renders the element normally
    • in (default) — applies filter to the target element only
    • after — renders the target element first, then applies filter
  • interval — optional; update interval in milliseconds for dynamic filter expressions (using $${} syntax)

Draw Effects

These filters modify the visual appearance without changing geometry. Multiple filters can be chained with semicolons.

blur(radiusX, radiusY)

  • Applies Gaussian blur to the element
  • radiusX — horizontal blur radius in pixels
  • radiusY — vertical blur radius in pixels
  • Example: effect="blur(2,2)" — applies 2px blur in both directions

drop-shadow(dx, dy, sigmaX, sigmaY)

  • Creates a drop shadow effect
  • dx — horizontal shadow offset in pixels
  • dy — vertical shadow offset in pixels
  • sigmaX — horizontal blur sigma
  • sigmaY — vertical blur sigma (optional, defaults to sigmaX if omitted)
  • Shadow color is black
  • Example: effect="drop-shadow(5,5,3,3)" — shadow offset 5px right and down with 3px blur

transparent(alpha)

  • Adjusts element transparency
  • alpha — opacity reduction (0.0 = fully transparent, 1.0 = no change)
  • Example: effect="transparent(0.5)" — makes element 50% more transparent

dilate(radiusX, radiusY)

  • Expands bright areas (morphological dilation)
  • radiusX — horizontal dilation radius in pixels
  • radiusY — vertical dilation radius in pixels
  • Example: effect="dilate(2,2)" — expands bright areas by 2px

erode(radiusX, radiusY)

  • Shrinks bright areas (morphological erosion)
  • radiusX — horizontal erosion radius in pixels
  • radiusY — vertical erosion radius in pixels
  • Example: effect="erode(2,2)" — erodes bright areas by 2px

brightness(factor)

  • Adjusts brightness of the element
  • factor — brightness multiplier (0.0 = black, 1.0 = original, >1.0 = brighter)
  • Example: effect="brightness(1.5)" — increases brightness by 50%

contrast(factor)

  • Adjusts contrast of the element
  • factor — contrast multiplier (0.0 = gray, 1.0 = original, >1.0 = higher contrast)
  • Example: effect="contrast(1.3)" — increases contrast by 30%

invert()

  • Inverts colors (negative effect)
  • No parameters
  • Example: effect="invert()" — creates color negative

sepia()

  • Applies sepia tone (warm brownish tint)
  • No parameters
  • Example: effect="sepia()" — vintage photo effect

grayscale()

  • Converts to grayscale (luminance-based)
  • No parameters
  • Uses standard luminance weights (R: 0.2126, G: 0.7152, B: 0.0722)
  • Example: effect="grayscale()" — black and white effect

saturate(amount)

  • Adjusts color saturation
  • amount — saturation change (-1.0 = desaturate, 0.0 = no change, >0.0 = more saturated)
  • Example: effect="saturate(0.5)" — increases saturation by 50%
  • Example: effect="saturate(-0.3)" — reduces saturation by 30%

colorfilter(r, g, b)

  • Tints the element with a specific color while preserving brightness
  • r — red component (0-255)
  • g — green component (0-255)
  • b — blue component (0-255)
  • Converts image to grayscale then applies color tint
  • Example: effect="colorfilter(255,100,50)" — orange tint

remove-black()

  • Makes black pixels transparent (useful for removing black backgrounds)
  • No parameters
  • Alpha channel becomes proportional to pixel brightness
  • Example: effect="remove-black()" — removes black background from images

Matrix Transformations

Important: Matrix transformations (rotate, offset, zoom) modify geometry and should not be mixed with draw effects in the same filter. Use separate <filter> decorators if you need both.

rotate(angle, [pivotX, pivotY])

  • Rotates the element
  • angle — rotation angle in degrees
  • pivotX — optional; horizontal pivot point (percentage or pixels, default: 50%)
  • pivotY — optional; vertical pivot point (percentage or pixels, default: 50%)
  • Example: effect="rotate(45)" — rotates 45° around center
  • Example: effect="rotate(90,0%,0%)" — rotates 90° around top-left corner
  • Dynamic example: effect="rotate($${Sensor_Value})" — rotates based on sensor value

offset(dx, dy)

  • Translates (moves) the element
  • dx — horizontal offset (percentage or pixels)
  • dy — vertical offset (percentage or pixels)
  • Example: effect="offset(10,20)" — moves 10px right, 20px down
  • Example: effect="offset(50%,0)" — moves 50% of width to the right

zoom(scale) or zoom(scaleX, scaleY, [pivotX, pivotY])

  • Scales the element
  • scale — uniform scale factor (1.0 = original size)
  • OR:
  • scaleX — horizontal scale factor
  • scaleY — vertical scale factor
  • pivotX — optional; horizontal scaling center (percentage or pixels)
  • pivotY — optional; vertical scaling center (percentage or pixels)
  • Example: effect="zoom(1.5)" — scales to 150% around center
  • Example: effect="zoom(2,1)" — doubles width only
  • Example: effect="zoom(0.5,0.5,0%,0%)" — scales to 50% from top-left corner

Usage Examples

Simple blur effect:

<item id="Speed">
  <filter effect="blur(2,2)"/>
</item>

Multiple chained effects:

<item id="Temperature">
  <filter effect="grayscale();saturate(0.5);brightness(1.2)"/>
</item>

Dynamic rotation based on sensor value:

<item id="Compass">
  <filter effect="rotate($${Sensor_Value},50%,50%)" interval="100"/>
</item>

Mode usage with multiple decorators:

<item id="Speed" type="chart" chart='line'>
  <break/>
  <image image-zorder="bottom" image-path="images/ui/arrow.png"/>
  <filter effect="rotate($${180+Sensor_Value%360},50%,50%)" mode="in" interval="100"/>
  <filter effect="blur(1,1)" mode="after"/>
  <padding padding="0 0 0 120"/>
</item>

Color tinting:

<item id="Warning">
  <filter effect="colorfilter(255,0,0)"/>  <!-- Red tint -->
</item>

Best Practices

  • Chain multiple draw effects in a single filter using semicolons for better performance
  • Don’t mix matrix transformations with draw effects in the same effect attribute
  • Use interval attribute only when you have dynamic $${} expressions that need periodic updates
  • Use mode="in" (default) for most cases; use mode="before" or mode="after" for special layering needs
  • Pair <break/> decorator before filters when you want to apply effects only to subsequent decorators, not the base element

break decorator

You can use break to abort overlaying of other decorators. Break means drawing pipeline starts from empty.

In this example break is used to apply filters only to the image decorator. not to the original content of “Speed” gauge (value and chart).

<item id="Speed" type="chart" chart='line'>
  <break/>
  <image image-zorder="bottom" image-path="images/ui/arrow-circle-right.png" image-scale="0.6"/>
  <filter effect="rotate($${180+Sensor_Value%360},50%,50%)" mode="in" interval="100"/>
  <filter effect="blur(1,1)"/>
  <padding padding="0 0 0 120"/>
</item>

Layout-level attributes and features from changelog

  • if — conditional rendering for section or item. Can use sensor names, boolean flags like PortraitLayout, LandscapeLayout, or compound expressions.
  • ignore-gauges in section — ignores global gauge attributes for all elements inside the section.
  • gauge local definitions — gauge definitions can be declared inside section to scope them locally.
  • swap-direction on gauges: swap-direction="true" to change direction of bar or roundbar.
  • horizontal-offset in roundbar.
  • break decorator — <break/> splits rendering into independent stages.
  • maximize-focus, controls="autohide" — useful for dash panels.
  • time-scale — used in charts to compress/expand time axis.
  • text-evaluator — advanced gauge attribute (returns arbitrary dynamic text), used in tank/description rendering.

Additional attributes and behaviors observed in layout files and changelogs:

  • optional / volatile on section (controls visibility rules in some hosts).
  • period on item — refresh period in milliseconds.
  • precision — numeric formatting or special formats (e.g., 6fixed).
  • colspan / rowspan — grid spanning.

Example of a chart item with filters and custom description:

Sensor and expression features

  • Sensors can be referenced directly by id in if attributes or as item ids.
  • TinyExe helpers and eval expressions available in ecuxml. Variables and functions accessible include: Pi, E, PositiveInfinity, NegativeInfinity and other globals from themes or gauge definitions.
  • Filters for sensors (wrap) as above.

TinyExe / eval example (from changelogs):

image-rotate='$${ Sensor_Value - 45 }'

Sensor formatted access example:

<item id="TripTime[fillup]"/> — uses extradata from sensor history APIs.

Sensor lists and autogenerated panels

  • section with class="SensorList" and ns="<namespace>" generates a screen listing sensors for a namespace. Use exclude regex to filter out unwanted sensor IDs. Example:

Conditional expressions

  • The if attribute can be a simple sensor presence test (e.g., if="STFT1") or a full expression referencing theme variables, day/night flags, layout flags, and sensor values. Example seen: if="SY_ABS_TEVES.ABS_ControlModuleVoltage, Chery_A21_ABS_TRW.ABS_ControlModuleVoltage"

Notes: if can contain comma-separated identifiers which act as OR conditions in practice (layout files often list multiple sensors/namespaces separated by commas).

Interpolation in Expressions

In addition to unadorned expressions, two interpolation styles are available:

  • ${ } interpolation: Evaluated once when the layout is built. Use this form for static computations or one-time assignments. Applicable for any attributes.

  • $${ } interpolation: Evaluated dynamically, making it suitable for values that update over time (e.g., animations or periodic sensor updates). Only applicable to the selected elements/attributes:

    • text-evaluator, switch[index], visibility, image-rotate, image-path, crop

These forms allow embedding TinyExe expressions within attribute values to achieve either static or dynamic evaluation as needed.

Grid sizing hints

  • rows and cols accept comma separated values. Empty entries are flexible cells, numbers provide fixed size hints. Example: rows="30,,," cols="30,,30".

You can nest grid elements to create complex responsive regions.

Other useful attributes and behaviors (from changelog and examples)

  • period on item — sets refresh period for the widget.
  • precision — formatting precision or special tags like 6fixed.
  • description="aside" — places descriptive text aside.
  • inherit — reuses widget styling (colors/formatting) from theme or other definitions.
  • text-values and custom-units allow mapping numeric values to textual labels or alternate unit systems.
  • min-limit / max-limit — clamp values for charts.

Widget and decorator attributes (observed in user.layout)

  • type (examples): bar, roundbar, chart, text, static — many visual widgets are selected via type on the item.

  • cache-interval — UI cache/refresh hint (milliseconds or unit) used to control smoothing/plotting; frequently used on chart and gauge-like widgets. Example: cache-interval="6".

  • red-green — color threshold list; comma-separated numbers indicating color boundaries (interpretation depends on widget). Examples: red-green="100,5", red-green="10,120,150".

  • bars-count — number of bars or segments used by bar/roundbar widgets. Example: bars-count="10".

  • transparenttrue/false whether background is transparent for the widget.

  • border-width / border-opacity — visual border control. Example: border-width="3", border-opacity="1".

  • colored-value — whether value text is colored according to thresholds: colored-value="true".

  • fade-coeff — visual fading coefficient used on charts/gauges to control trail transparency: fade-coeff="0.8".

  • width-compression — compress drawing horizontally: width-compression="0.9".

  • item-size / item-width / item-height / item-spacing — sizing controls for roundbars and similar widgets (absolute/logical units). Example: item-size="25", item-width="10", item-height="10", item-spacing="20".

  • small-radius-delta / small-radis-delta (typo variants observed) — small radius adjustments used for roundbars.

  • start-angle / end-angle / radius / vertical-offset — roundbar geometry attributes to control arc start/end and offset.

  • item-width/item-height vs item-size — some widgets use item-size while others use width/height pair.

  • corn-angle / middle-angle — additional roundbar geometry attributes (observed in test layouts).

  • decorator-p (padding) and p-padding — decorator shorthand for padding decorator. Example: decorator-p="padding" p-padding="10 10 10 10".

  • decorator-i / decorator-iN pattern — numbered decorators for multiple images on a single item. Use decorator-i1="image" and i1-image-path, i1-image-rotate, i1-image-zorder, i1-image-rotate-align, etc. The unnumbered decorator-i="image" with nested <image> elements is also supported.

    Examples: ```xml


- rotate / scale attributes on nested `<image>` decorators — `rotate` can contain dynamic TinyExe expressions and `scale` applies an image scale.

- custom-units — used on `DateTime` to show time variants: `custom-units="time12"`, `time`, `timesec`, `datetime`, `seconds`.

- border-opacity used on static/test items to preview borders: `border-opacity="1"`.

- numeric `size` on `item` — static items can use numeric `size` values (e.g., `size="72"`, `size="32"`) besides named sizes (`small`, `normal`, `large`).


Common `type` values seen in dashkits:

- `type="text"` — textual rendering of a sensor with `text-values` mapping.
- `type="chart"` — time-series chart for sensor.
- `type="button"` — user-invokable action.

Example: `text-values` and `type=text` usage in dashb3 kits:

`<item id="RPM" wrap="predict(50, 0.7)" text-values="0:" type="text" description="hidden">`

## Advanced: ecuxml and sensor definitions
- sensor definitions and `eval` expressions live in ecuxml files. Key features mentioned across changelogs:
  - `<eval>` expressions for computed sensors
  - `base-data` / `base-raw` for raw bytes
  - functions `get(offset)`, `get_word()` etc.
  - `text` tag with offset/length for string sensors

## Best practices and tips
- Use `if` broadly to keep layout files modular; layout files are only loaded for relevant ECUs, but `if` helps avoid rendering empty sections.
- Use `SensorList` sections for generic sensor browsing screens and `exclude` to filter noisy sensors.
- Prefer nested decorators for complex visuals; they are simpler and localized.
- Use `wrap` filters on noisy sensors (GPS, speed, MAF) for smoother rendering.
- Keep gauges local to section when possible using `ignore-gauges` and local `gauge` declarations to reduce global side-effects.

## Appendix — common attributes quick reference
- section: `name`, `fixed`, `if`, `class`, `ns`, `exclude`, `maximize-focus`, `controls`
- grid: `rows`, `cols`
- item: `id`, `type`, `text`, `action`, `size`, `precision`, `inherit`, `colspan`, `rowspan`, `description`, `period`, `wrap`
- decorators: `image` (`image-path`, `image-scale`, `image-zorder`, `image-rotate`, `image-width`/`image-height`)

## Try it — ready templates
Copy these minimal examples into a skin file to try the patterns.

GPS panel (minimal)
```xml
<ui>
  <section name="GPS">
    <grid rows=",," cols=",,">
      <item id='Latitude' precision='6fixed' size="normal"/>
      <item id='Longitude' precision='6fixed' size="normal"/>
      <item id='GPSSpeed' precision='1' />
    </grid>
  </section>
</ui>

Fan control (buttons + inherit)

<ui>
  <section name="FAN" fixed="false" if="PortraitLayout">
    <grid rows=",," cols="">
      <item id="FAN_Status" inherit="_ColoredOnOff" size='large'/>
      <item type="button" text="Fan On" action="invoke(FAN_ON)" size='extralarge' />
      <item type="button" text="Fan Off" action="invoke(FAN_OFF)" size='extralarge' />
    </grid>
  </section>
</ui>

Hybrid summary example

<ui>
  <section name="Hybrid">
    <grid rows="30,,," cols="30,,30">
      <item id="Efficiency_Battery" size='huge' />
      <item id="FuelEconomy_NoBattery" size='huge' />
      <item id="BatteryCurrent" />
      <item id="SoC" />
    </grid>
  </section>
</ui>