mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 13:50:04 -04:00
Simplify shares and use Rect/interacto for resize
This commit is contained in:
@@ -166,6 +166,7 @@ impl Linear {
|
|||||||
|
|
||||||
// ------------------------
|
// ------------------------
|
||||||
// resizing:
|
// resizing:
|
||||||
|
|
||||||
let parent_rect = nodes.rect(parent_id).unwrap();
|
let parent_rect = nodes.rect(parent_id).unwrap();
|
||||||
for (i, (left, right)) in self.children.iter().tuple_windows().enumerate() {
|
for (i, (left, right)) in self.children.iter().tuple_windows().enumerate() {
|
||||||
let resize_id = egui::Id::new((parent_id, "resize", i));
|
let resize_id = egui::Id::new((parent_id, "resize", i));
|
||||||
@@ -176,49 +177,46 @@ impl Linear {
|
|||||||
|
|
||||||
let mut resize_state = ResizeState::Idle;
|
let mut resize_state = ResizeState::Idle;
|
||||||
if let Some(pointer) = ui.ctx().pointer_latest_pos() {
|
if let Some(pointer) = ui.ctx().pointer_latest_pos() {
|
||||||
let we_are_on_top = ui
|
let line_rect = Rect::from_center_size(
|
||||||
.ctx()
|
pos2(x, parent_rect.center().y),
|
||||||
.layer_id_at(pointer)
|
vec2(
|
||||||
.map_or(true, |top_layer_id| top_layer_id == ui.layer_id());
|
2.0 * ui.style().interaction.resize_grab_radius_side,
|
||||||
|
parent_rect.height(),
|
||||||
let mouse_over_resize_line = we_are_on_top
|
),
|
||||||
&& parent_rect.y_range().contains(&pointer.y)
|
);
|
||||||
&& (x - pointer.x).abs() <= ui.style().interaction.resize_grab_radius_side;
|
let response = ui.interact(line_rect, resize_id, egui::Sense::click_and_drag());
|
||||||
|
if response.double_clicked() {
|
||||||
if ui.input(|i| i.pointer.any_pressed() && i.pointer.any_down())
|
// double-click to center the split between left and right:
|
||||||
&& mouse_over_resize_line
|
let mean = 0.5 * (self.shares[*left] + self.shares[*right]);
|
||||||
{
|
self.shares.insert(*left, mean);
|
||||||
ui.memory_mut(|mem| mem.set_dragged_id(resize_id));
|
self.shares.insert(*right, mean);
|
||||||
}
|
} else if response.dragged() {
|
||||||
if ui.memory(|mem| mem.is_being_dragged(resize_id)) {
|
|
||||||
resize_state = ResizeState::Dragging;
|
resize_state = ResizeState::Dragging;
|
||||||
} else {
|
} else if response.hovered() {
|
||||||
let dragging_something_else =
|
resize_state = ResizeState::Hovering;
|
||||||
ui.input(|i| i.pointer.any_down() || i.pointer.any_pressed());
|
|
||||||
if mouse_over_resize_line && !dragging_something_else {
|
|
||||||
resize_state = ResizeState::Hovering;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if resize_state == ResizeState::Dragging {
|
if resize_state == ResizeState::Dragging {
|
||||||
|
let node_width = |node_id: NodeId| nodes.rect(node_id).unwrap().width();
|
||||||
|
|
||||||
let dx = pointer.x - x;
|
let dx = pointer.x - x;
|
||||||
if pointer.x < x {
|
if pointer.x < x {
|
||||||
// Expand right, shrink stuff to the left:
|
// Expand right, shrink stuff to the left:
|
||||||
*self.shares.shares.entry(*right).or_insert(1.0) += shrink_shares(
|
self.shares[*right] += shrink_shares(
|
||||||
behavior,
|
behavior,
|
||||||
nodes,
|
|
||||||
&mut self.shares,
|
&mut self.shares,
|
||||||
&self.children[0..=i].iter().copied().rev().collect_vec(),
|
&self.children[0..=i].iter().copied().rev().collect_vec(),
|
||||||
dx.abs(),
|
dx.abs(),
|
||||||
|
node_width,
|
||||||
);
|
);
|
||||||
} else if x < pointer.x {
|
} else if x < pointer.x {
|
||||||
// Expand the left, shrink stuff to the right:
|
// Expand the left, shrink stuff to the right:
|
||||||
*self.shares.shares.entry(*left).or_insert(1.0) += shrink_shares(
|
self.shares[*left] += shrink_shares(
|
||||||
behavior,
|
behavior,
|
||||||
nodes,
|
|
||||||
&mut self.shares,
|
&mut self.shares,
|
||||||
&self.children[i + 1..],
|
&self.children[i + 1..],
|
||||||
dx.abs(),
|
dx.abs(),
|
||||||
|
node_width,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -254,18 +252,20 @@ impl Linear {
|
|||||||
/// making sure no child gets smaller than its minimum size.
|
/// making sure no child gets smaller than its minimum size.
|
||||||
fn shrink_shares<Leaf>(
|
fn shrink_shares<Leaf>(
|
||||||
behavior: &dyn Behavior<Leaf>,
|
behavior: &dyn Behavior<Leaf>,
|
||||||
nodes: &Nodes<Leaf>,
|
|
||||||
shares: &mut Shares,
|
shares: &mut Shares,
|
||||||
children: &[NodeId],
|
children: &[NodeId],
|
||||||
target_in_points: f32,
|
target_in_points: f32,
|
||||||
|
size_in_point: impl Fn(NodeId) -> f32,
|
||||||
) -> f32 {
|
) -> f32 {
|
||||||
assert!(!children.is_empty());
|
if children.is_empty() {
|
||||||
|
return 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
let mut total_shares = 0.0;
|
let mut total_shares = 0.0;
|
||||||
let mut total_points = 0.0;
|
let mut total_points = 0.0;
|
||||||
for &child in children {
|
for &child in children {
|
||||||
total_shares += shares.shares.get(&child).copied().unwrap_or(1.0);
|
total_shares += shares[child];
|
||||||
total_points += nodes.rect(child).unwrap().width();
|
total_points += size_in_point(child);
|
||||||
}
|
}
|
||||||
|
|
||||||
let shares_per_point = total_shares / total_points;
|
let shares_per_point = total_shares / total_points;
|
||||||
@@ -276,7 +276,7 @@ fn shrink_shares<Leaf>(
|
|||||||
let mut total_shares_lost = 0.0;
|
let mut total_shares_lost = 0.0;
|
||||||
|
|
||||||
for &child in children {
|
for &child in children {
|
||||||
let share = shares.shares.entry(child).or_insert(1.0);
|
let share = &mut shares[child];
|
||||||
let shrink_by = (target_in_shares - total_shares_lost)
|
let shrink_by = (target_in_shares - total_shares_lost)
|
||||||
.min(*share - min_size_in_points)
|
.min(*share - min_size_in_points)
|
||||||
.max(0.0);
|
.max(0.0);
|
||||||
|
|||||||
@@ -36,10 +36,14 @@ pub struct Shares {
|
|||||||
///
|
///
|
||||||
/// For instance, the shares `[1, 2, 3]` means that the first child gets 1/6 of the space,
|
/// For instance, the shares `[1, 2, 3]` means that the first child gets 1/6 of the space,
|
||||||
/// the second gets 2/6 and the third gets 3/6.
|
/// the second gets 2/6 and the third gets 3/6.
|
||||||
pub shares: HashMap<NodeId, f32>,
|
shares: HashMap<NodeId, f32>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Shares {
|
impl Shares {
|
||||||
|
pub fn insert(&mut self, id: NodeId, share: f32) {
|
||||||
|
self.shares.insert(id, share);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn replace_with(&mut self, a: NodeId, b: NodeId) {
|
pub fn replace_with(&mut self, a: NodeId, b: NodeId) {
|
||||||
if let Some(share) = self.shares.remove(&a) {
|
if let Some(share) = self.shares.remove(&a) {
|
||||||
self.shares.insert(b, share);
|
self.shares.insert(b, share);
|
||||||
@@ -48,21 +52,32 @@ impl Shares {
|
|||||||
|
|
||||||
pub fn split(&self, children: &[NodeId], available_width: f32) -> Vec<f32> {
|
pub fn split(&self, children: &[NodeId], available_width: f32) -> Vec<f32> {
|
||||||
let mut num_shares = 0.0;
|
let mut num_shares = 0.0;
|
||||||
for child in children {
|
for &child in children {
|
||||||
num_shares += self.shares.get(child).copied().unwrap_or(1.0);
|
num_shares += self[child];
|
||||||
}
|
}
|
||||||
if num_shares == 0.0 {
|
if num_shares == 0.0 {
|
||||||
num_shares = 1.0;
|
num_shares = 1.0;
|
||||||
}
|
}
|
||||||
children
|
children
|
||||||
.iter()
|
.iter()
|
||||||
.map(|child| {
|
.map(|&child| available_width * self[child] / num_shares)
|
||||||
available_width * self.shares.get(child).copied().unwrap_or(1.0) / num_shares
|
|
||||||
})
|
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::ops::Index<NodeId> for Shares {
|
||||||
|
type Output = f32;
|
||||||
|
fn index(&self, id: NodeId) -> &Self::Output {
|
||||||
|
self.shares.get(&id).unwrap_or(&1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::ops::IndexMut<NodeId> for Shares {
|
||||||
|
fn index_mut(&mut self, id: NodeId) -> &mut Self::Output {
|
||||||
|
self.shares.entry(id).or_insert(1.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)]
|
||||||
|
|||||||
Reference in New Issue
Block a user