GanttEx.Layout (GanttEx v0.1.0)

Copy Markdown View Source

Computes the geometry of the chart: one bar per visible row and one path per visible link.

Tasks rendered with render: :split draw their children as segments on their own row (and links reach the segments while the branch is collapsed), and tasks with rollup: true also appear as rollups on the rows of their ancestor projects.

The layout is pure data, so it can be tested without rendering anything:

iex> store = GanttEx.Store.new!(
...>   [
...>     %{id: 1, text: "A", start_date: ~D[2025-01-01], duration: 2},
...>     %{id: 2, text: "B", start_date: ~D[2025-01-04], type: :milestone}
...>   ],
...>   [%{id: 1, source: 1, target: 2}]
...> )
iex> timeline = GanttEx.Timeline.new(scales: [[unit: :day]], start_date: ~N[2025-01-01 00:00:00], end_date: ~N[2025-01-10 00:00:00], column_width: 40)
iex> layout = GanttEx.Layout.build(store, GanttEx.Store.rows(store), timeline, row_height: 36, bar_height: 24)
iex> [a, b] = layout.bars
iex> {a.x, a.width, a.y, a.kind}
{0.0, 80.0, 6.0, :task}
iex> {b.x, b.width, b.kind}
{108.0, 24, :milestone}
iex> [link] = layout.links
iex> link.d
"M80 18L92 18L92 54L102 54"
iex> layout.height
72

Summary

Types

A positioned task bar.

A positioned link.

A task shown on the row of an ancestor project.

t()

Functions

Builds the layout for the given rows (see GanttEx.Store.rows/2).

Types

bar()

@type bar() :: %{
  key: GanttEx.Store.key(),
  task: GanttEx.Task.t(),
  row: non_neg_integer(),
  kind: GanttEx.Task.type(),
  x: float(),
  y: float(),
  width: float(),
  height: number(),
  progress: float(),
  baseline:
    %{x: float(), y: float(), width: float(), milestone: boolean()} | nil,
  uid: String.t(),
  segment: boolean()
}

A positioned task bar.

rollup()

@type rollup() :: %{
  uid: String.t(),
  task: GanttEx.Task.t(),
  row: non_neg_integer(),
  kind: GanttEx.Task.type(),
  x: float(),
  y: float(),
  width: float()
}

A task shown on the row of an ancestor project.

t()

@type t() :: %{
  bars: [bar()],
  segments: [bar()],
  rollups: [rollup()],
  bar_index: %{required(GanttEx.Store.key()) => bar()},
  links: [link_path()],
  width: non_neg_integer(),
  height: non_neg_integer()
}

Functions

build(store, rows, timeline, opts \\ [])

Builds the layout for the given rows (see GanttEx.Store.rows/2).

Options

  • :row_height - defaults to 36.
  • :bar_height - defaults to row_height - 12.
  • :min_bar_width - defaults to 6, so very short tasks stay visible.
  • :baselines - make room below the bars for the baselines (:planned_start / :planned_end). Defaults to false.