Skip to content

Commit 5c39435

Browse files
authored
Move axis widget (#168)
Follow up for #167
1 parent ade0713 commit 5c39435

File tree

2 files changed

+125
-124
lines changed

2 files changed

+125
-124
lines changed

egui_plot/src/lib.rs

Lines changed: 0 additions & 123 deletions
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@ use std::cmp::Ordering;
2020
use std::ops::RangeInclusive;
2121

2222
use ahash::HashMap;
23-
use axis::AxisWidget;
2423
use egui::Color32;
2524
use egui::Id;
2625
use egui::NumExt as _;
27-
use egui::Rect;
2826
use egui::Response;
2927
use egui::Ui;
3028
use egui::Vec2;
@@ -170,127 +168,6 @@ pub struct PlotResponse<R> {
170168

171169
// ----------------------------------------------------------------------------
172170

173-
/// Returns the rect left after adding axes.
174-
fn axis_widgets<'a>(
175-
mem: Option<&PlotMemory>,
176-
show_axes: impl Into<Vec2b>,
177-
complete_rect: Rect,
178-
[x_axes, y_axes]: [&'a [AxisHints<'a>]; 2],
179-
) -> ([Vec<AxisWidget<'a>>; 2], Rect) {
180-
// Next we want to create this layout.
181-
// Indices are only examples.
182-
//
183-
// left right
184-
// +---+---------x----------+ +
185-
// | | X-axis 3 |
186-
// | +--------------------+ top
187-
// | | X-axis 2 |
188-
// +-+-+--------------------+-+-+
189-
// |y|y| |y|y|
190-
// |-|-| |-|-|
191-
// |A|A| |A|A|
192-
// y|x|x| Plot Window |x|x|
193-
// |i|i| |i|i|
194-
// |s|s| |s|s|
195-
// |1|0| |2|3|
196-
// +-+-+--------------------+-+-+
197-
// | X-axis 0 | |
198-
// +--------------------+ | bottom
199-
// | X-axis 1 | |
200-
// + +--------------------+---+
201-
//
202-
let show_axes = show_axes.into();
203-
204-
let mut x_axis_widgets = Vec::<AxisWidget<'_>>::new();
205-
let mut y_axis_widgets = Vec::<AxisWidget<'_>>::new();
206-
207-
// Will shrink as we add more axes.
208-
let mut rect_left = complete_rect;
209-
210-
if show_axes.x {
211-
// We will fix this later, once we know how much space the y axes take up.
212-
let initial_x_range = complete_rect.x_range();
213-
214-
for (i, cfg) in x_axes.iter().enumerate().rev() {
215-
let mut height = cfg.min_thickness;
216-
if let Some(mem) = mem {
217-
// If the labels took up too much space the previous frame, give them more space
218-
// now:
219-
height = height.max(mem.x_axis_thickness.get(&i).copied().unwrap_or_default());
220-
}
221-
222-
let rect = match VPlacement::from(cfg.placement) {
223-
VPlacement::Bottom => {
224-
let bottom = rect_left.bottom();
225-
*rect_left.bottom_mut() -= height;
226-
let top = rect_left.bottom();
227-
Rect::from_x_y_ranges(initial_x_range, top..=bottom)
228-
}
229-
VPlacement::Top => {
230-
let top = rect_left.top();
231-
*rect_left.top_mut() += height;
232-
let bottom = rect_left.top();
233-
Rect::from_x_y_ranges(initial_x_range, top..=bottom)
234-
}
235-
};
236-
x_axis_widgets.push(AxisWidget::new(cfg.clone(), rect));
237-
}
238-
}
239-
if show_axes.y {
240-
// We know this, since we've already allocated space for the x axes.
241-
let plot_y_range = rect_left.y_range();
242-
243-
for (i, cfg) in y_axes.iter().enumerate().rev() {
244-
let mut width = cfg.min_thickness;
245-
if let Some(mem) = mem {
246-
// If the labels took up too much space the previous frame, give them more space
247-
// now:
248-
width = width.max(mem.y_axis_thickness.get(&i).copied().unwrap_or_default());
249-
}
250-
251-
let rect = match HPlacement::from(cfg.placement) {
252-
HPlacement::Left => {
253-
let left = rect_left.left();
254-
*rect_left.left_mut() += width;
255-
let right = rect_left.left();
256-
Rect::from_x_y_ranges(left..=right, plot_y_range)
257-
}
258-
HPlacement::Right => {
259-
let right = rect_left.right();
260-
*rect_left.right_mut() -= width;
261-
let left = rect_left.right();
262-
Rect::from_x_y_ranges(left..=right, plot_y_range)
263-
}
264-
};
265-
y_axis_widgets.push(AxisWidget::new(cfg.clone(), rect));
266-
}
267-
}
268-
269-
// The loops iterated through {x,y}_axes in reverse order, so we have to reverse
270-
// the {x,y}_axis_widgets vec as well. Otherwise, the indices are messed up
271-
// and the plot memory (mem.{x,y}_axis_thickness) will access the wrong axis
272-
// given an index.
273-
x_axis_widgets.reverse();
274-
y_axis_widgets.reverse();
275-
276-
let mut plot_rect = rect_left;
277-
278-
// If too little space, remove axis widgets
279-
if plot_rect.width() <= 0.0 || plot_rect.height() <= 0.0 {
280-
y_axis_widgets.clear();
281-
x_axis_widgets.clear();
282-
plot_rect = complete_rect;
283-
}
284-
285-
// Now that we know the final x_range of the plot_rect,
286-
// assign it to the x_axis_widgets (they are currently too wide):
287-
for widget in &mut x_axis_widgets {
288-
widget.rect = Rect::from_x_y_ranges(plot_rect.x_range(), widget.rect.y_range());
289-
}
290-
291-
([x_axis_widgets, y_axis_widgets], plot_rect)
292-
}
293-
294171
/// User-requested modifications to the plot bounds. We collect them in the plot
295172
/// build function to later apply them at the right time, as other modifications
296173
/// need to happen first.

egui_plot/src/plot.rs

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ use crate::CursorLinkGroups;
3535
use crate::GridInput;
3636
use crate::GridMark;
3737
use crate::GridSpacer;
38+
use crate::HPlacement;
3839
use crate::LabelFormatter;
3940
use crate::Legend;
4041
use crate::LinkedBounds;
@@ -46,6 +47,8 @@ use crate::PlotPoint;
4647
use crate::PlotResponse;
4748
use crate::PlotTransform;
4849
use crate::PlotUi;
50+
use crate::VPlacement;
51+
use crate::axis::AxisWidget;
4952
use crate::items;
5053
use crate::items::horizontal_line;
5154
use crate::items::rulers_color;
@@ -850,7 +853,7 @@ impl<'a> Plot<'a> {
850853

851854
let plot_id = id.unwrap_or_else(|| ui.make_persistent_id(id_source));
852855

853-
let ([x_axis_widgets, y_axis_widgets], plot_rect) = crate::axis_widgets(
856+
let ([x_axis_widgets, y_axis_widgets], plot_rect) = axis_widgets(
854857
PlotMemory::load(ui.ctx(), plot_id).as_ref(), // TODO #164: avoid loading plot memory twice
855858
show_axes,
856859
complete_rect,
@@ -1612,3 +1615,124 @@ impl PreparedPlot<'_> {
16121615
(cursors, hovered_plot_item_id)
16131616
}
16141617
}
1618+
1619+
/// Returns the rect left after adding axes.
1620+
fn axis_widgets<'a>(
1621+
mem: Option<&PlotMemory>,
1622+
show_axes: impl Into<Vec2b>,
1623+
complete_rect: Rect,
1624+
[x_axes, y_axes]: [&'a [AxisHints<'a>]; 2],
1625+
) -> ([Vec<AxisWidget<'a>>; 2], Rect) {
1626+
// Next we want to create this layout.
1627+
// Indices are only examples.
1628+
//
1629+
// left right
1630+
// +---+---------x----------+ +
1631+
// | | X-axis 3 |
1632+
// | +--------------------+ top
1633+
// | | X-axis 2 |
1634+
// +-+-+--------------------+-+-+
1635+
// |y|y| |y|y|
1636+
// |-|-| |-|-|
1637+
// |A|A| |A|A|
1638+
// y|x|x| Plot Window |x|x|
1639+
// |i|i| |i|i|
1640+
// |s|s| |s|s|
1641+
// |1|0| |2|3|
1642+
// +-+-+--------------------+-+-+
1643+
// | X-axis 0 | |
1644+
// +--------------------+ | bottom
1645+
// | X-axis 1 | |
1646+
// + +--------------------+---+
1647+
//
1648+
let show_axes = show_axes.into();
1649+
1650+
let mut x_axis_widgets = Vec::<AxisWidget<'_>>::new();
1651+
let mut y_axis_widgets = Vec::<AxisWidget<'_>>::new();
1652+
1653+
// Will shrink as we add more axes.
1654+
let mut rect_left = complete_rect;
1655+
1656+
if show_axes.x {
1657+
// We will fix this later, once we know how much space the y axes take up.
1658+
let initial_x_range = complete_rect.x_range();
1659+
1660+
for (i, cfg) in x_axes.iter().enumerate().rev() {
1661+
let mut height = cfg.min_thickness;
1662+
if let Some(mem) = mem {
1663+
// If the labels took up too much space the previous frame, give them more space
1664+
// now:
1665+
height = height.max(mem.x_axis_thickness.get(&i).copied().unwrap_or_default());
1666+
}
1667+
1668+
let rect = match VPlacement::from(cfg.placement) {
1669+
VPlacement::Bottom => {
1670+
let bottom = rect_left.bottom();
1671+
*rect_left.bottom_mut() -= height;
1672+
let top = rect_left.bottom();
1673+
Rect::from_x_y_ranges(initial_x_range, top..=bottom)
1674+
}
1675+
VPlacement::Top => {
1676+
let top = rect_left.top();
1677+
*rect_left.top_mut() += height;
1678+
let bottom = rect_left.top();
1679+
Rect::from_x_y_ranges(initial_x_range, top..=bottom)
1680+
}
1681+
};
1682+
x_axis_widgets.push(AxisWidget::new(cfg.clone(), rect));
1683+
}
1684+
}
1685+
if show_axes.y {
1686+
// We know this, since we've already allocated space for the x axes.
1687+
let plot_y_range = rect_left.y_range();
1688+
1689+
for (i, cfg) in y_axes.iter().enumerate().rev() {
1690+
let mut width = cfg.min_thickness;
1691+
if let Some(mem) = mem {
1692+
// If the labels took up too much space the previous frame, give them more space
1693+
// now:
1694+
width = width.max(mem.y_axis_thickness.get(&i).copied().unwrap_or_default());
1695+
}
1696+
1697+
let rect = match HPlacement::from(cfg.placement) {
1698+
HPlacement::Left => {
1699+
let left = rect_left.left();
1700+
*rect_left.left_mut() += width;
1701+
let right = rect_left.left();
1702+
Rect::from_x_y_ranges(left..=right, plot_y_range)
1703+
}
1704+
HPlacement::Right => {
1705+
let right = rect_left.right();
1706+
*rect_left.right_mut() -= width;
1707+
let left = rect_left.right();
1708+
Rect::from_x_y_ranges(left..=right, plot_y_range)
1709+
}
1710+
};
1711+
y_axis_widgets.push(AxisWidget::new(cfg.clone(), rect));
1712+
}
1713+
}
1714+
1715+
// The loops iterated through {x,y}_axes in reverse order, so we have to reverse
1716+
// the {x,y}_axis_widgets vec as well. Otherwise, the indices are messed up
1717+
// and the plot memory (mem.{x,y}_axis_thickness) will access the wrong axis
1718+
// given an index.
1719+
x_axis_widgets.reverse();
1720+
y_axis_widgets.reverse();
1721+
1722+
let mut plot_rect = rect_left;
1723+
1724+
// If too little space, remove axis widgets
1725+
if plot_rect.width() <= 0.0 || plot_rect.height() <= 0.0 {
1726+
y_axis_widgets.clear();
1727+
x_axis_widgets.clear();
1728+
plot_rect = complete_rect;
1729+
}
1730+
1731+
// Now that we know the final x_range of the plot_rect,
1732+
// assign it to the x_axis_widgets (they are currently too wide):
1733+
for widget in &mut x_axis_widgets {
1734+
widget.rect = Rect::from_x_y_ranges(plot_rect.x_range(), widget.rect.y_range());
1735+
}
1736+
1737+
([x_axis_widgets, y_axis_widgets], plot_rect)
1738+
}

0 commit comments

Comments
 (0)