Skip to content

Rearchitected Layout Engine

Pre-release
Pre-release
Compare
Choose a tag to compare
@teamdandelion teamdandelion released this 16 May 23:40
· 8728 commits to master since this release

v0.12.0 - Rearchitected Layout Engine

The Old Approach

The original Plottable layout engine computed the width and height for Component independently. Components would report how much space they wanted independent of what was available, and fail out if they were not given enough space.

This was very convenient for the initial implementation, but meant we couldn't intelligently handle cases where the width of an object might depend on its height and vice versa; principle examples being Labels and Category Axes.

Furthermore, for simplicity we assumed that the layout (eg size or position) of a Component would never change. This meant that if you changed the domain of a colorScale hooked into a Legend, or changed the text on a Label, the layout of the Table would not update appropriately.

The New Layout Engine

As of this release, when Components are being laid out the parent calls Component._requestedSpace(offeredWidth, offeredHeight). Now, components with cross-dimension dependencies like Labels can report how much of the width and space they will use, and may signal if they would like more space if possible. As such, we've removed two calls from the base Component class: minimumWidth(newVal?: number) and minimumHeight(newVal?: number), thus reducing the size of the public API.
Also, components are now expected to be able to accept any amount of width or space, and degrade gracefully rather than throwing an error. This should improve the reliability and stability of Plottable charts.

This enables some more intelligent behavior by existing components. For example, it used to be that the user was responsible for figuring out an appropriate Legend size by setting Legend.minimumWidth(x) through trial and error. Now, the legend will compute an appropriate width on its own. Looking into the future, this lays the groundwork for us to write a more intelligent Category Axis that uses space and word-wrapping more efficiently.

Furthermore, Components now have an _invalidateLayout() call which will schedule the entire Component tree to be re-laid out. This is hooked into the requestAnimationFrame cycle so that multiple layout-invalidating changes will be batched together for perf efficiency. All component calls that should cause the layout to change now automatically call _invalidateLayout, so if you change the text on a label or the alignment on a Table, it will automatically re-size, re-locate, and re-render.

API Breaking Changes

Component.minimumWidth and Component.minimumHeight have been removed from the API. If you were using these in your code, that code is now broken. In most cases, you can remove it and not think about it. For the case of axes, they now have equivalent methods xAxis.height(x), yAxis.width(x) which allow you to manually set the dimensions and thus effect the old functionality.
This was an obscure part of the API so I don't think this will cause much inconvenience for downstream consumers.

We have also renamed ComponentGroup.empty() to ComponentGroup.removeAll(). ComponentGroup.empty() now is a boolean check which returns true iff the ComponentGroup is empty. This is more intuitive and consistent with the d3 API.