Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions examples/advanced.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ impl Pane {
struct TreeBehavior {
simplification_options: egui_tiles::SimplificationOptions,
tab_bar_height: f32,
max_tab_bar_rows: usize,
gap_width: f32,
add_child_to: Option<egui_tiles::TileId>,
}
Expand All @@ -69,6 +70,7 @@ impl Default for TreeBehavior {
Self {
simplification_options: Default::default(),
tab_bar_height: 24.0,
max_tab_bar_rows: 1,
gap_width: 2.0,
add_child_to: None,
}
Expand All @@ -80,6 +82,7 @@ impl TreeBehavior {
let Self {
simplification_options,
tab_bar_height,
max_tab_bar_rows,
gap_width,
add_child_to: _,
} = self;
Expand All @@ -106,6 +109,14 @@ impl TreeBehavior {
);
ui.end_row();

ui.label("Max tab bar rows:");
ui.add(egui::Slider::new(max_tab_bar_rows, 1..=4))
.on_hover_text(
"Above 1, a tab bar too crowded for one row wraps into further rows \
instead of scrolling. Add tabs with ➕, or narrow the window, to see it.",
);
ui.end_row();

ui.label("Gap width:");
ui.add(egui::DragValue::new(gap_width).range(0.0..=20.0).speed(1.0));
ui.end_row();
Expand Down Expand Up @@ -163,6 +174,10 @@ impl egui_tiles::Behavior<Pane> for TreeBehavior {
self.tab_bar_height
}

fn max_tab_bar_rows(&self) -> usize {
self.max_tab_bar_rows
}

fn gap_width(&self, _style: &egui::Style) -> f32 {
self.gap_width
}
Expand Down
26 changes: 25 additions & 1 deletion src/behavior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ pub(crate) struct LayoutContext<'a> {
pub tab_bar_height: f32,
pub grid_auto_column_count: &'a dyn Fn(usize, Rect, f32) -> usize,

/// How many rows a given tab bar took last frame.
///
/// A wrapped tab bar is as tall as the rows it needed, and how many that is depends on how
/// wide the tabs turned out — which the layout pass runs too early to know. So it reads what
/// the last frame measured, and a bar that has just changed shape is one frame behind.
pub tab_bar_rows: &'a dyn Fn(TileId) -> usize,

/// Set by the layout pass if it had to pick an active tab for a [`crate::Tabs`] container.
///
/// Reported back to the caller rather than straight to [`Behavior::on_edit`]: laying out
Expand All @@ -63,6 +70,7 @@ pub(crate) fn layout_tiles<Pane, TilesPane>(
root: Option<TileId>,
behavior: &dyn Behavior<Pane>,
style: &egui::Style,
tab_bar_rows: &dyn Fn(TileId) -> usize,
rect: Rect,
) -> bool {
let Some(root) = root else {
Expand All @@ -78,6 +86,7 @@ pub(crate) fn layout_tiles<Pane, TilesPane>(
gap_width: behavior.gap_width(style),
tab_bar_height: behavior.tab_bar_height(style),
grid_auto_column_count: &grid_auto_column_count,
tab_bar_rows,
tab_auto_selected: &tab_auto_selected,
};

Expand Down Expand Up @@ -343,11 +352,26 @@ pub trait Behavior<Pane> {
) {
}

/// The height of the bar holding tab titles.
/// The height of one row of the bar holding tab titles.
fn tab_bar_height(&self, _style: &egui::Style) -> f32 {
24.0
}

/// How many rows a tab bar may wrap into before it starts scrolling instead.
///
/// The default of `1` keeps a tab bar to a single row that scrolls once the
/// tabs no longer fit, with arrows at either end. Raising it lets a crowded
/// bar break into further rows first, which is worth it wherever a tab bar
/// is narrow — a side panel of eight tabs otherwise hides half of them
/// behind an arrow, and a tab you cannot see is a tab you will not use.
///
/// Tabs wrap only if they fit within this many rows; beyond that the bar
/// falls back to a single scrolling row rather than growing without end.
/// Returning `0` is read as `1`.
fn max_tab_bar_rows(&self) -> usize {
1
}

/// Width of the gap between tiles in a horizontal or vertical layout,
/// and between rows/columns in a grid layout.
fn gap_width(&self, _style: &egui::Style) -> f32 {
Expand Down
9 changes: 8 additions & 1 deletion src/container/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,14 @@ mod tests {

for _ in 0..1000 {
let root = tree.root.unwrap();
crate::behavior::layout_tiles(&mut tree.tiles, Some(root), &behavior, &style, area);
crate::behavior::layout_tiles(
&mut tree.tiles,
Some(root),
&behavior,
&style,
&|_| 1,
area,
);

// Add some tiles:
for _ in 0..rng.rand_u64() % 3 {
Expand Down
4 changes: 3 additions & 1 deletion src/container/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ mod tabs;
pub use grid::{Grid, GridLayout};
pub use linear::{Linear, LinearDir, Shares};
pub use tabs::Tabs;
pub(crate) use tabs::tab_bar_rows;

// ----------------------------------------------------------------------------

Expand Down Expand Up @@ -239,13 +240,14 @@ impl Container {
tiles: &mut Tiles<Pane>,
layout: &LayoutContext<'_>,
rect: Rect,
tile_id: TileId,
) {
if self.is_empty() {
return;
}

match self {
Self::Tabs(tabs) => tabs.layout(tiles, layout, rect),
Self::Tabs(tabs) => tabs.layout(tiles, layout, rect, tile_id),
Self::Linear(linear) => {
linear.layout(tiles, layout, rect);
}
Expand Down
Loading