Skip to content

Create Multiple Panels

Split a figure into coordinated viewports.

Several data views arranged as panels in one figure

At a glance

Status: Supported retained grid and free-placement layouts · Languages: Python and C Prerequisites: One figure plus prepared visuals for the intended panels Result: One figure containing independently configurable panel viewports

Task workflow

Create one figure, define a panel grid or multiple panels, attach visuals to each panel, and bind controllers per panel or share controllers when views should move together.

Choose the layout path first:

Need Use
One full-canvas view dvz_panel_full()
Regular rows and columns dvz_figure_grid() with dvz_grid_panel()
A panel spanning grid cells dvz_grid_panel_span()
Custom inset or irregular layout dvz_panel() with a normalized DvzPanelDesc

Panels are viewports inside one figure and scene. They do not create separate scenes, data stores, or controller state automatically.

Grid call sequence

Prerequisite: create one figure and two prepared visuals. The result is a one-row, two-column figure with one visual per panel. These are fragments; see the complete Multiple Panels example.

import datoviz as dvz

grid = dvz.dvz_figure_grid(figure, 1, 2)
left = dvz.dvz_grid_panel(grid, 0, 0)
right = dvz.dvz_grid_panel(grid, 0, 1)
if not grid or not left or not right:
    raise RuntimeError("panel grid creation failed")
dvz.dvz_panel_add_visual(left, visual_a, None)
dvz.dvz_panel_add_visual(right, visual_b, None)
DvzGrid* grid = dvz_figure_grid(figure, 1, 2);
DvzPanel* left = dvz_grid_panel(grid, 0, 0);
DvzPanel* right = dvz_grid_panel(grid, 0, 1);
dvz_panel_add_visual(left, visual_a, NULL);
dvz_panel_add_visual(right, visual_b, NULL);

Use dvz_grid_set_margins() and dvz_grid_set_gutter() when the panels need reserved space or consistent spacing.

dvz_grid_set_margins(
    grid,
    &(DvzPanelReserve){
        .left_px = 48.0f, .right_px = 32.0f, .top_px = 32.0f, .bottom_px = 48.0f});
dvz_grid_set_gutter(grid, 24.0f, 20.0f);

With the minimal 1 × 2 grid, the expected result is two equal-width panels. Margins shrink the outer grid area; the horizontal gutter separates the columns; neither setting reserves axis space inside a panel.

Rows and columns default to equal weight. Use fixed-pixel or weighted row/column sizes when one panel is a sidebar, overview, or shared control strip:

dvz_grid_set_col_size(grid, 0, DVZ_GRID_SIZE_WEIGHT, 2.0f);
dvz_grid_set_col_size(grid, 1, DVZ_GRID_SIZE_WEIGHT, 1.0f);
dvz_grid_set_row_size(grid, 0, DVZ_GRID_SIZE_FIXED_PX, 160.0f);

Spanning panels

Use a spanning panel when one plot should occupy several cells:

DvzGrid* grid = dvz_figure_grid(figure, 2, 2);
DvzPanel* top_left = dvz_grid_panel(grid, 0, 0);
DvzPanel* top_right = dvz_grid_panel(grid, 0, 1);
DvzPanel* bottom = dvz_grid_panel_span(grid, 1, 0, 1, 2);

Spans must cover contiguous grid cells. Use manual panels when the layout is truly irregular.

Manual panels

For inset panels or layouts that do not fit a grid, create panels directly in normalized figure coordinates:

DvzPanel* left = dvz_panel(
    figure, &(DvzPanelDesc){.x = 0.08f, .y = 0.16f, .width = 0.40f, .height = 0.68f});
DvzPanel* right = dvz_panel(
    figure, &(DvzPanelDesc){.x = 0.52f, .y = 0.16f, .width = 0.40f, .height = 0.68f});

Use dvz_panel_set_desc() when a retained panel needs a new normalized rectangle after creation.

Plot reserves and padding

Grid margins and gutters position panel rectangles. Panel reserves and padding affect the content inside one panel.

Use panel reserves for axes, labels, colorbars, scale bars, or readouts that need stable logical-pixel bands around the plot area:

dvz_panel_set_reserve(
    panel,
    &(DvzPanelReserve){.left_px = 72.0f, .right_px = 20.0f, .top_px = 16.0f, .bottom_px = 56.0f});

Use panel padding to inset the whole panel content before reserves are resolved. dvz_panel_full() is still a good choice for single-panel scenes; add reserve or padding only when adornments need it.

Controllers

Bind controllers per panel. Separate controllers make panels move independently:

DvzController* left_panzoom = dvz_panzoom(scene, NULL);
DvzController* right_panzoom = dvz_panzoom(scene, NULL);
dvz_panel_bind_controller(left, left_panzoom, DVZ_DIM_MASK_XY);
dvz_panel_bind_controller(right, right_panzoom, DVZ_DIM_MASK_XY);

Share one controller pointer when views should move together:

DvzController* shared = dvz_panzoom(scene, NULL);
dvz_panel_bind_controller(left, shared, DVZ_DIM_MASK_XY);
dvz_panel_bind_controller(right, shared, DVZ_DIM_MASK_XY);

Use a narrower dimension mask, such as DVZ_DIM_MASK_X, when only one axis should be linked. See Link panels and controllers for linked-controller patterns.

Important details

Panels are viewports in one figure and scene, not separate scenes. Share data and controllers deliberately; do not duplicate the whole scene unless the runtime really needs separate lifetimes.

Attaching a visual to one panel does not attach it to every panel. Call dvz_panel_add_visual() for each panel that should draw that visual, and use an explicit DvzVisualAttachDesc when the same visual needs data-coordinate attachment, a different draw layer, or panel-fixed coordinates.

Panel domains, cameras, backgrounds, borders, techniques, axes, colorbars, and annotations are panel-specific. Configure each panel explicitly unless a helper or shared object is meant to link state.

Destroying a grid detaches grid-owned panels at their last resolved positions; it does not destroy the panels. Prefer keeping the grid alive for ordinary retained layouts.

Common mistakes

  • Adding one visual to the wrong panel and debugging the controller instead.
  • Assuming every panel shares a controller automatically.
  • Recreating figures to make subplots.
  • Using manual normalized panels for a regular grid that should use dvz_figure_grid().
  • Expecting grid margins to reserve space for axes inside each panel; use panel reserves for that.
  • Linking panels with incompatible domains or cameras.
  • Forgetting to attach a shared visual to every panel that should draw it.

See also

Complete and related examples
  • Canonical complete example: Panel Grid - Source: examples/c/features/panel_grid.c
  • Multiple Panels - Source: examples/c/features/panel_multi.c
  • Linked Panels - Source: examples/c/features/panel_linked.c