mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 22:00:03 -04:00
Improve dragging around tab labels
This commit is contained in:
@@ -122,7 +122,7 @@ impl Linear {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_zones(ui.ctx(), nodes, &self.children, self.dir, |rect, i| {
|
linear_drop_zones(ui.ctx(), nodes, &self.children, self.dir, |rect, i| {
|
||||||
drop_context.suggest_rect(
|
drop_context.suggest_rect(
|
||||||
InsertionPoint::new(parent_id, LayoutInsertion::Horizontal(i)),
|
InsertionPoint::new(parent_id, LayoutInsertion::Horizontal(i)),
|
||||||
rect,
|
rect,
|
||||||
@@ -185,7 +185,7 @@ impl Linear {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
drop_zones(ui.ctx(), nodes, &self.children, self.dir, |rect, i| {
|
linear_drop_zones(ui.ctx(), nodes, &self.children, self.dir, |rect, i| {
|
||||||
drop_context.suggest_rect(
|
drop_context.suggest_rect(
|
||||||
InsertionPoint::new(parent_id, LayoutInsertion::Vertical(i)),
|
InsertionPoint::new(parent_id, LayoutInsertion::Vertical(i)),
|
||||||
rect,
|
rect,
|
||||||
@@ -315,25 +315,18 @@ fn shrink_shares<Leaf>(
|
|||||||
total_shares_lost
|
total_shares_lost
|
||||||
}
|
}
|
||||||
|
|
||||||
fn drop_zones<Leaf>(
|
fn linear_drop_zones<Leaf>(
|
||||||
egui_ctx: &egui::Context,
|
egui_ctx: &egui::Context,
|
||||||
nodes: &Nodes<Leaf>,
|
nodes: &Nodes<Leaf>,
|
||||||
children: &[NodeId],
|
children: &[NodeId],
|
||||||
dir: LinearDir,
|
dir: LinearDir,
|
||||||
mut add_drop_drect: impl FnMut(Rect, usize),
|
add_drop_drect: impl FnMut(Rect, usize),
|
||||||
) {
|
) {
|
||||||
let preview_thickness = 12.0;
|
let preview_thickness = 12.0;
|
||||||
|
let dragged_index = children
|
||||||
|
.iter()
|
||||||
|
.position(|&child| is_being_dragged(egui_ctx, child));
|
||||||
|
|
||||||
let before_rect = |rect: Rect| match dir {
|
|
||||||
LinearDir::Horizontal => Rect::from_min_max(
|
|
||||||
rect.left_top(),
|
|
||||||
rect.left_bottom() + vec2(preview_thickness, 0.0),
|
|
||||||
),
|
|
||||||
LinearDir::Vertical => Rect::from_min_max(
|
|
||||||
rect.left_top(),
|
|
||||||
rect.right_top() + vec2(0.0, preview_thickness),
|
|
||||||
),
|
|
||||||
};
|
|
||||||
let afer_rect = |rect: Rect| match dir {
|
let afer_rect = |rect: Rect| match dir {
|
||||||
LinearDir::Horizontal => Rect::from_min_max(
|
LinearDir::Horizontal => Rect::from_min_max(
|
||||||
rect.right_top() - vec2(preview_thickness, 0.0),
|
rect.right_top() - vec2(preview_thickness, 0.0),
|
||||||
@@ -344,6 +337,37 @@ fn drop_zones<Leaf>(
|
|||||||
rect.right_bottom(),
|
rect.right_bottom(),
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
drop_zones(
|
||||||
|
preview_thickness,
|
||||||
|
children,
|
||||||
|
dragged_index,
|
||||||
|
dir,
|
||||||
|
|node_id| nodes.rect(node_id),
|
||||||
|
add_drop_drect,
|
||||||
|
afer_rect,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drop_zones(
|
||||||
|
preview_thickness: f32,
|
||||||
|
children: &[NodeId],
|
||||||
|
dragged_index: Option<usize>,
|
||||||
|
dir: LinearDir,
|
||||||
|
get_rect: impl Fn(NodeId) -> Rect,
|
||||||
|
mut add_drop_drect: impl FnMut(Rect, usize),
|
||||||
|
afer_rect: impl Fn(Rect) -> Rect,
|
||||||
|
) {
|
||||||
|
let before_rect = |rect: Rect| match dir {
|
||||||
|
LinearDir::Horizontal => Rect::from_min_max(
|
||||||
|
rect.left_top(),
|
||||||
|
rect.left_bottom() + vec2(preview_thickness, 0.0),
|
||||||
|
),
|
||||||
|
LinearDir::Vertical => Rect::from_min_max(
|
||||||
|
rect.left_top(),
|
||||||
|
rect.right_top() + vec2(0.0, preview_thickness),
|
||||||
|
),
|
||||||
|
};
|
||||||
let between_rects = |a: Rect, b: Rect| match dir {
|
let between_rects = |a: Rect, b: Rect| match dir {
|
||||||
LinearDir::Horizontal => Rect::from_center_size(
|
LinearDir::Horizontal => Rect::from_center_size(
|
||||||
a.right_center().lerp(b.left_center(), 0.5),
|
a.right_center().lerp(b.left_center(), 0.5),
|
||||||
@@ -355,15 +379,11 @@ fn drop_zones<Leaf>(
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
let dragged_index = children
|
|
||||||
.iter()
|
|
||||||
.position(|&child| is_being_dragged(egui_ctx, child));
|
|
||||||
|
|
||||||
let mut prev_rect: Option<Rect> = None;
|
let mut prev_rect: Option<Rect> = None;
|
||||||
let mut insertion_index = 0; // skips over drag-source, if any, beacuse it will be removed before its re-inserted
|
let mut insertion_index = 0; // skips over drag-source, if any, beacuse it will be removed before its re-inserted
|
||||||
|
|
||||||
for (i, &child) in children.iter().enumerate() {
|
for (i, &child) in children.iter().enumerate() {
|
||||||
let rect = nodes.rect(child);
|
let rect = get_rect(child);
|
||||||
|
|
||||||
if Some(i) == dragged_index {
|
if Some(i) == dragged_index {
|
||||||
// Suggest hole as a drop-target:
|
// Suggest hole as a drop-target:
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use egui::{vec2, Rect};
|
use egui::{vec2, Rect};
|
||||||
|
|
||||||
use crate::dock::{
|
use crate::dock::{
|
||||||
@@ -54,8 +56,8 @@ impl Tabs {
|
|||||||
|
|
||||||
// Show tab bar:
|
// Show tab bar:
|
||||||
tab_bar_ui.horizontal(|ui| {
|
tab_bar_ui.horizontal(|ui| {
|
||||||
let mut prev_tab_rect: Option<Rect> = None;
|
let mut button_rects = HashMap::new();
|
||||||
let mut insertion_index = 0; // skips over drag-source, if any, beacuse it will be removed then re-inserted
|
let mut dragged_index = None;
|
||||||
|
|
||||||
for (i, &child_id) in self.children.iter().enumerate() {
|
for (i, &child_id) in self.children.iter().enumerate() {
|
||||||
let is_being_dragged = is_being_dragged(ui.ctx(), child_id);
|
let is_being_dragged = is_being_dragged(ui.ctx(), child_id);
|
||||||
@@ -76,38 +78,37 @@ impl Tabs {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let rect = response.rect;
|
button_rects.insert(child_id, response.rect);
|
||||||
|
if is_being_dragged {
|
||||||
{
|
dragged_index = Some(i);
|
||||||
// suggest dropping before this tab:
|
|
||||||
let before_point = if let Some(prev_tab_rect) = prev_tab_rect {
|
|
||||||
// between
|
|
||||||
prev_tab_rect.right_center().lerp(rect.left_center(), 0.5)
|
|
||||||
} else {
|
|
||||||
// before first
|
|
||||||
rect.left_center()
|
|
||||||
};
|
|
||||||
|
|
||||||
drop_context.suggest_rect(
|
|
||||||
InsertionPoint::new(node_id, LayoutInsertion::Tabs(insertion_index)),
|
|
||||||
Rect::from_center_size(before_point, vec2(4.0, rect.height())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if i + 1 == self.children.len() {
|
|
||||||
// suggest dropping after last tab:
|
|
||||||
drop_context.suggest_rect(
|
|
||||||
InsertionPoint::new(node_id, LayoutInsertion::Tabs(insertion_index + 1)),
|
|
||||||
Rect::from_center_size(rect.right_center(), vec2(4.0, rect.height())),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
prev_tab_rect = Some(rect);
|
|
||||||
|
|
||||||
if !is_being_dragged {
|
|
||||||
insertion_index += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let preview_thickness = 6.0;
|
||||||
|
let afer_rect = |rect: Rect| {
|
||||||
|
let dragged_size = if let Some(dragged_index) = dragged_index {
|
||||||
|
// We actually know the size of this thing
|
||||||
|
button_rects[&self.children[dragged_index]].size()
|
||||||
|
} else {
|
||||||
|
rect.size() // guess that the size is the same as the last button
|
||||||
|
};
|
||||||
|
Rect::from_min_size(
|
||||||
|
rect.right_top() + vec2(ui.spacing().item_spacing.x, 0.0),
|
||||||
|
dragged_size,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
super::linear::drop_zones(
|
||||||
|
preview_thickness,
|
||||||
|
&self.children,
|
||||||
|
dragged_index,
|
||||||
|
super::LinearDir::Horizontal,
|
||||||
|
|node_id| button_rects[&node_id],
|
||||||
|
|rect, i| {
|
||||||
|
drop_context
|
||||||
|
.suggest_rect(InsertionPoint::new(node_id, LayoutInsertion::Tabs(i)), rect);
|
||||||
|
},
|
||||||
|
afer_rect,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
// When dragged, don't show it (it is "being held")
|
// When dragged, don't show it (it is "being held")
|
||||||
|
|||||||
Reference in New Issue
Block a user