mirror of
https://github.com/emilk/egui.git
synced 2026-08-31 22:00:03 -04:00
Add support for selection and target container highlight
This commit is contained in:
@@ -33,6 +33,9 @@ enum Item {
|
|||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
enum Command {
|
enum Command {
|
||||||
|
/// Set the selected item
|
||||||
|
SetSelectedItem(Option<ItemId>),
|
||||||
|
|
||||||
/// Move the currently dragged item to the given container and position.
|
/// Move the currently dragged item to the given container and position.
|
||||||
MoveItem {
|
MoveItem {
|
||||||
moved_item_id: ItemId,
|
moved_item_id: ItemId,
|
||||||
@@ -51,6 +54,9 @@ pub struct HierarchicalDragAndDrop {
|
|||||||
/// Id of the root item (not displayed in the UI)
|
/// Id of the root item (not displayed in the UI)
|
||||||
root_id: ItemId,
|
root_id: ItemId,
|
||||||
|
|
||||||
|
/// Selected item, if any
|
||||||
|
selected_item: Option<ItemId>,
|
||||||
|
|
||||||
/// If a drag is ongoing, this is the id of the destination container (if any was identified)
|
/// If a drag is ongoing, this is the id of the destination container (if any was identified)
|
||||||
///
|
///
|
||||||
/// This is used to highlight the target container.
|
/// This is used to highlight the target container.
|
||||||
@@ -73,6 +79,7 @@ impl Default for HierarchicalDragAndDrop {
|
|||||||
let mut res = Self {
|
let mut res = Self {
|
||||||
items: std::iter::once((root_id, root_item)).collect(),
|
items: std::iter::once((root_id, root_item)).collect(),
|
||||||
root_id,
|
root_id,
|
||||||
|
selected_item: None,
|
||||||
target_container: None,
|
target_container: None,
|
||||||
command_receiver,
|
command_receiver,
|
||||||
command_sender,
|
command_sender,
|
||||||
@@ -235,12 +242,25 @@ impl HierarchicalDragAndDrop {
|
|||||||
self.container_children_ui(ui, top_level_items);
|
self.container_children_ui(ui, top_level_items);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// deselect by clicking in the empty space
|
||||||
|
if ui
|
||||||
|
.interact(
|
||||||
|
ui.available_rect_before_wrap(),
|
||||||
|
"empty_space".into(),
|
||||||
|
egui::Sense::click(),
|
||||||
|
)
|
||||||
|
.clicked()
|
||||||
|
{
|
||||||
|
self.send_command(Command::SetSelectedItem(None));
|
||||||
|
}
|
||||||
|
|
||||||
// always reset the target container
|
// always reset the target container
|
||||||
self.target_container = None;
|
self.target_container = None;
|
||||||
|
|
||||||
while let Ok(command) = self.command_receiver.try_recv() {
|
while let Ok(command) = self.command_receiver.try_recv() {
|
||||||
//println!("Received command: {command:?}");
|
println!("Received command: {command:?}");
|
||||||
match command {
|
match command {
|
||||||
|
Command::SetSelectedItem(item_id) => self.selected_item = item_id,
|
||||||
Command::MoveItem {
|
Command::MoveItem {
|
||||||
moved_item_id,
|
moved_item_id,
|
||||||
target_container_id,
|
target_container_id,
|
||||||
@@ -264,13 +284,25 @@ impl HierarchicalDragAndDrop {
|
|||||||
ui.add(
|
ui.add(
|
||||||
egui::Label::new(format!("Container {item_id:?}"))
|
egui::Label::new(format!("Container {item_id:?}"))
|
||||||
.selectable(false)
|
.selectable(false)
|
||||||
.sense(egui::Sense::drag()),
|
.sense(egui::Sense::click_and_drag()),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.body(|ui| {
|
.body(|ui| {
|
||||||
self.container_children_ui(ui, children);
|
self.container_children_ui(ui, children);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if head_response.inner.clicked() {
|
||||||
|
self.send_command(Command::SetSelectedItem(Some(item_id)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.target_container == Some(item_id) {
|
||||||
|
ui.painter().rect_stroke(
|
||||||
|
head_response.inner.rect,
|
||||||
|
2.0,
|
||||||
|
(1.0, ui.visuals().selection.bg_fill),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
self.handle_drag_and_drop_interaction(
|
self.handle_drag_and_drop_interaction(
|
||||||
ui,
|
ui,
|
||||||
item_id,
|
item_id,
|
||||||
@@ -282,6 +314,13 @@ impl HierarchicalDragAndDrop {
|
|||||||
|
|
||||||
fn container_children_ui(&self, ui: &mut egui::Ui, children: &Vec<ItemId>) {
|
fn container_children_ui(&self, ui: &mut egui::Ui, children: &Vec<ItemId>) {
|
||||||
for child_id in children {
|
for child_id in children {
|
||||||
|
// check if the item is selected
|
||||||
|
ui.visuals_mut().override_text_color = if Some(*child_id) == self.selected_item {
|
||||||
|
Some(ui.visuals().selection.bg_fill)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
};
|
||||||
|
|
||||||
match self.items.get(child_id) {
|
match self.items.get(child_id) {
|
||||||
Some(Item::Container(children)) => {
|
Some(Item::Container(children)) => {
|
||||||
self.container_ui(ui, *child_id, children);
|
self.container_ui(ui, *child_id, children);
|
||||||
@@ -298,9 +337,13 @@ impl HierarchicalDragAndDrop {
|
|||||||
let response = ui.add(
|
let response = ui.add(
|
||||||
egui::Label::new(label)
|
egui::Label::new(label)
|
||||||
.selectable(false)
|
.selectable(false)
|
||||||
.sense(egui::Sense::drag()),
|
.sense(egui::Sense::click_and_drag()),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if response.clicked() {
|
||||||
|
self.send_command(Command::SetSelectedItem(Some(item_id)));
|
||||||
|
}
|
||||||
|
|
||||||
self.handle_drag_and_drop_interaction(ui, item_id, false, &response, None);
|
self.handle_drag_and_drop_interaction(ui, item_id, false, &response, None);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -318,6 +361,9 @@ impl HierarchicalDragAndDrop {
|
|||||||
|
|
||||||
if response.drag_started() {
|
if response.drag_started() {
|
||||||
egui::DragAndDrop::set_payload(ui.ctx(), item_id);
|
egui::DragAndDrop::set_payload(ui.ctx(), item_id);
|
||||||
|
|
||||||
|
// force selection to the dragged item
|
||||||
|
self.send_command(Command::SetSelectedItem(Some(item_id)));
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|||||||
Reference in New Issue
Block a user