Replies: 1 comment · 10 replies
-
There's a drag-and-drop example on egui.rs. Here's the source: https://github.com/emilk/egui/blob/master/crates/egui_demo_lib/src/demo/drag_and_drop.rs |
Beta Was this translation helpful? Give feedback.
All reactions
-
Hi, thank for you for the response. I have a couple of questions,
To simplify, I basically have a Sorry, but I have not used a |
Beta Was this translation helpful? Give feedback.
All reactions
-
No worries, it's my first time using it as well.
egui is storing the payload internally:
As a recap:
|
Beta Was this translation helpful? Give feedback.
All reactions
-
So
Hmm.. so should I call impl eframe::App for App {
fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
if !self.initialized {
self.preferences_dialog
.get_mut_audio_preferences()
.init_backend(&self.serializer, &mut self.app_config);
if self.theme_config.should_enable_theming(&self.serializer) {
ctx.set_style(self.set_style(ctx, false));
}
}
self.initialized = true;
// Process keybinds
self.process_key_press(ctx);
// Render custom header bar if enabled
if !self
.app_config
.get_use_system_window_header(&self.serializer)
&& !self.is_window_fullscreen
{
egui::TopBottomPanel::top("header_bar")
.show_separator_line(true)
.show_animated(ctx, true, |ui| {
self.header_bar_widgets(ui);
});
}
// Render about dialog
self.about_dialog.render(ctx);
// Render preferences dialog
self.preferences_dialog.render(ctx);
// Render file picker dialog
self.file_picker_dialog.render(ctx);
// Render side panel
self.side_panel.render(ctx); // <-------
// Render waveform viewer
self.waveform_viewer.render(ctx);
egui::CentralPanel::default().show(ctx, |ui| {
// Render control bar
self.render_control_bar(ui);
// Render sample viewer
self.sample_viewer.render(ui); // <-------
});
} instead of their respective
Do I call impl SampleViewer {
pub fn new() -> Self {
Self {
id: egui::Id::new("sample_viewer"),
number_of_samples: 0,
// clickable: true,
scroll_to_row: None,
selection: Default::default(),
is_row_selected: false,
}
}
pub fn render(&mut self, ui: &mut egui::Ui, dnd: &mut Dnd) {
let text_height = egui::TextStyle::Body
.resolve(ui.style())
.size
.max(ui.spacing().interact_size.y);
// let mut dnd = Dnd::default();
// let mut source_col_row = None;
// let mut drop_col = None;
// let file_tree_id = dnd.get_drag_id().unwrap_or("file_tree_".into());
// let payload_type = dnd.get_payload_type();
// let is_payload_valid = dnd.is_payload_valid(payload_type);
// let mut samples = Vec::default();
// if is_payload_valid {
// log::debug!("Paylad type valid, getting the payload");
// samples = dnd.get_payload();
// }
// self.number_of_samples = samples.len();
// let frame = egui::Frame::default();
// Dnd::drop_target(ui, true, |ui| {
let (response, payload) = ui
.dnd_drop_zone::<crate::sample_hive::gui::utils::samples::Sample, ()>(frame, |ui| {
let mut table = TableBuilder::new(ui)
.sense(egui::Sense::click())
.striped(true)
.cell_layout(egui::Layout::left_to_right(egui::Align::Center))
.column(Column::auto())
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::initial(100.0).range(40.0..=300.0).resizable(true))
.column(Column::remainder())
.min_scrolled_height(0.0);
if let Some(row_index) = self.scroll_to_row.take() {
table = table.scroll_to_row(row_index, Some(egui::Align::Center));
}
table
.header(20.0, |mut header| {
header.col(|ui| {
ui.strong("⭐");
});
header.col(|ui| {
ui.strong("Filename");
});
header.col(|ui| {
ui.strong("Sample Pack");
});
header.col(|ui| {
ui.strong("Type");
});
header.col(|ui| {
ui.strong("Channels");
});
header.col(|ui| {
ui.strong("BPM");
});
header.col(|ui| {
ui.strong("Length");
});
header.col(|ui| {
ui.strong("Sample Rate");
});
header.col(|ui| {
ui.strong("Bitrate");
});
header.col(|ui| {
ui.strong("Path");
});
})
.body(|body| {
body.rows(text_height, self.number_of_samples, |mut row| {
row.set_selected(self.selection.contains(&row.index()));
// samples.clone().into_iter().for_each(|sample| {
row.col(|ui| {
// if sample.get_favorite() {
// ui.selectable_value(&mut self.is_row_selected, true, "⭐");
// } else {
// ui.selectable_value(&mut self.is_row_selected, true, "✴");
// }
});
row.col(|ui| {
// ui.label(sample.get_filename().unwrap());
});
row.col(|ui| {
// ui.label(sample.get_sample_pack().unwrap());
});
row.col(|ui| {
// ui.label(sample.get_sample_type().unwrap());
});
row.col(|ui| {
// ui.label(sample.get_channels().unwrap().to_string());
});
row.col(|ui| {
// ui.label(sample.get_bpm().unwrap().to_string());
});
row.col(|ui| {
// ui.label(sample.get_length().unwrap());
});
row.col(|ui| {
// ui.label(sample.get_sample_rate().unwrap().to_string());
});
row.col(|ui| {
// ui.label(sample.get_bitrate().unwrap().to_string());
});
row.col(|ui| {
// ui.label(sample.get_path().unwrap());
});
// });
// ui.memory_mut(|mem| {
// mem.set_dragged_id(egui::Id::new((
// "sample_",
// row.col_index(),
// row.index(),
// )))
// });
self.toggle_row_selection(row.index(), &row.response());
// if ui.memory(|mem| mem.is_being_dragged(file_tree_id)) {
// source_col_row = Some((row.index(), row.col_index()));
// }
})
});
// });
// });
// .response;
// let response = response.context_menu(|ui| {
// if ui.button("New Item").clicked() {
// self.columns[col_idx].push("New Item".to_owned());
// ui.close_menu();
// }
// });
// let is_being_dragged = ui.memory(|mem| mem.is_anything_being_dragged());
// if is_being_dragged && is_payload_valid && response.hovered() {
// drop_col = Some(samples[0].get_filename());
// }
// if let Some((source_col, source_row)) = source_col_row {
// if let Some(drop_col) = drop_col {
// if ui.input(|i| i.pointer.any_released()) {
// // do the drop:
// let item = &samples[source_col]; //.remove(source_row);
// samples.push(item.clone());
// }
// }
// }
if let Some(hovered_payload) = response
.response
.dnd_hover_payload::<crate::sample_hive::gui::utils::samples::Sample>(
) {
// draw a yellow rect around drop zone when a source is hovering over it
let highlight_rect = response.response.rect.expand(4.0);
ui.painter().rect(
highlight_rect,
0.0,
egui::Color32::TRANSPARENT,
egui::Stroke::new(2.0, egui::Color32::from_hex("#fc0").unwrap()),
);
// debug print so you can see what's going on
// `loc` is a `Location` representing the location of the item being hovered over
println!("{:?} hovers over {:?}", hovered_payload, frame.clone()); // Not sure what would `loc.clone()` here in my case.
}
} This Actually when wrapped by This is what it looks like when wrapped with And this is what it looks like when its not wrapped with |
Beta Was this translation helpful? Give feedback.
All reactions
-
That's what it's called in API documentation. I was using Location as a reference to the example code. I think you're making this way harder than it has to be:
As far as the table is concerned, that seems like a separate issue. I would recommend reading the source code for
Why would you expect it to do anything if there are no calls to No one can help you unless you show your work. Did you try hovering over the table header? The missing vertical lines from your table should be a dead giveaway that the table has been resized. Try adding some fake, static records to the table for troubleshooting. |
Beta Was this translation helpful? Give feedback.
All reactions
-
I have shared my impl BrowserSection {
fn new() -> Self {
Self {
path: PathBuf::from("/"),
samples: Vec::new(),
}
}
fn render(&mut self, ui: &mut egui::Ui, dnd: &mut Dnd) {
self.directory_browser(ui, &self.path.clone(), dnd);
}
fn directory_browser(&mut self, ui: &mut egui::Ui, path: &std::path::Path, dnd: &mut Dnd) {
if let Ok(entries) = std::fs::read_dir(path) {
entries.filter_map(|entry| entry.ok()).for_each(|entry| {
let mut samples_clone = self.samples.clone();
let path = entry.path();
let file_tree_id = egui::Id::new("file_tree_")
.with(entry.file_name().to_string_lossy())
.with(entry.path().to_string_lossy());
// let mut dnd = Dnd::default();
// let source_col: Option<(usize, usize)> = None;
// let drop_col: Option<usize> = None;
// let mut samples: Vec<Sample> = Vec::new();
// let mut samples_clone = samples.clone();
// let file_tree_id = ui.memory(|mem| mem.dragged_id().unwrap());
// Dnd::drag_source(ui, file_tree_id, |ui| {
ui.dnd_drag_source(file_tree_id, samples_clone.clone(), |ui| {
if path.is_dir() {
egui::collapsing_header::CollapsingState::load_with_default_open(
ui.ctx(),
file_tree_id,
false,
)
.show_header(ui, |ui| {
let directory = ui.selectable_label(
false,
format!("📁 {}", entry.file_name().to_string_lossy()),
);
// samples_clone.push(Sample::new(
// false,
// format!("{}", entry.file_name().to_string_lossy()),
// format!("{}", entry.file_name().to_string_lossy()),
// format!("{}", entry.file_name().to_string_lossy()),
// 2,
// 132,
// "00:32".to_string(),
// 44100,
// 51243,
// format!("{}", entry.path().to_string_lossy()),
// ));
// if directory.hovered() {
// ui.ctx().set_cursor_icon(egui::CursorIcon::Grab);
// }
// let dir_sense = directory.interact(egui::Sense::click_and_drag());
// if dir_sense.dragged() {
// log::debug!("Directory is being dragged..");
// ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing);
// }
// if dir_sense.drag_started() {
// dnd.set_drag_id(file_tree_id);
// dnd.set_payload_type(Payload::SampleDir);
// dnd.set_payload(samples);
// }
})
.body(|ui| {
// let header = egui::CollapsingHeader::new(format!(
// "📁 {}",
// entry.file_name().to_string_lossy()
// ))
// .default_open(false)
// .show(ui, |ui| {});
self.directory_browser(ui, &path, dnd);
});
} else {
let file = ui.selectable_label(
false,
format!("📄 {}", &entry.file_name().to_string_lossy()),
);
// samples_clone.push(Sample::new(
// false,
// format!("{}", entry.file_name().to_string_lossy()),
// format!("{}", entry.file_name().to_string_lossy()),
// format!("{}", entry.file_name().to_string_lossy()),
// 2,
// 132,
// "00:32".to_string(),
// 44100,
// 51243,
// format!("{}", entry.path().to_string_lossy()),
// ));
// if file.hovered() {
// ui.ctx().set_cursor_icon(egui::CursorIcon::Grab);
// }
// let file_sense = file.interact(egui::Sense::click_and_drag());
// if file_sense.dragged() {
// log::debug!("File is being dragged..");
// ui.ctx().set_cursor_icon(egui::CursorIcon::Grabbing);
// }
// if file_sense.drag_started() {
// dnd.set_drag_id(file_tree_id);
// dnd.set_payload_type(Payload::SampleFile);
// dnd.set_payload(samples);
// }
}
});
// if let Some((source_col, source_row)) = source_col {
// if let Some(drop_col) = drop_col {
// if ui.input(|i| i.pointer.any_released()) {
// // do the drop:
// let item = samples_clone[source_col].remove(source_row);
// samples_clone[drop_col].push(item);
// }
// }
// }
});
}
}
} I left all the commented code I have as well from when I was creating my own
There is no option for min height or something in
This code where I asked if I should call |
Beta Was this translation helpful? Give feedback.
-
I'm trying to implement drag and drop by looking at the example form the repository but can't understand how would it work for my use case.
I basically have a side panel which shows a file tree of all the files and directories on the system using
CollapsibleState
s andSelectableLabel
s. I want to be able to drag "files/directories" to another widget, which is aTable
, filling up every column with the individual file's metadata one file per row..Here is what I tried so far,
This is form
side_panel.rs
This is from
sample_viewer.rs
(the table widget)I created my own
drag_and_drop.rs
file which has the functions from the example plus a little extra,here is the
drag_and_drop.rs
I'm passing
dnd
as an argument to both thedirectory_browser
andsample_viewer
which I pass in theupdate()
inapp.rs
,Sample
is just astruct
,with a bunch of
get
andset
methods for getting and/or setting individual fields..Am I even on the right track?
ATM it just shows correct cursors and animations nothing else,
https://github.com/emilk/egui/assets/53279454/18cd84a2-99d3-4438-ba11-6f7331d71a4c
This project is a re-write of my older project https://gitlab.com/samplehive/sample-hive
Here's a peek of what I basically want,
https://github.com/emilk/egui/assets/53279454/8859c35b-d539-4f82-abe1-69ac48739e6f
Beta Was this translation helpful? Give feedback.
All reactions