#[derive(Clone, Debug, PartialEq, Eq)]
pub enum ClipAction {
Copy,
Cut,
Paste(String),
}
pub fn poll(ctx: &egui::Context) -> Vec<ClipAction> {
ctx.input(|i| {
i.events
.iter()
.filter_map(|e| match e {
egui::Event::Copy => Some(ClipAction::Copy),
egui::Event::Cut => Some(ClipAction::Cut),
egui::Event::Paste(s) => Some(ClipAction::Paste(s.clone())),
_ => None,
})
.collect()
})
}
pub fn put(ctx: &egui::Context, text: impl Into<String>) {
ctx.copy_text(text.into());
}
pub fn rows_to_tsv<S: AsRef<str>>(header: &[S], rows: impl IntoIterator<Item = Vec<String>>) -> String {
let mut out = String::new();
if !header.is_empty() {
out.push_str(&header.iter().map(|c| c.as_ref()).collect::<Vec<_>>().join("\t"));
}
for row in rows {
if !out.is_empty() {
out.push('\n');
}
out.push_str(&row.join("\t"));
}
out
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn rows_to_tsv_joins_header_and_rows() {
let tsv = rows_to_tsv(
&["name", "ver"],
vec![vec!["knut".to_string(), "0.1".to_string()], vec!["korp".to_string(), "0.2".to_string()]],
);
assert_eq!(tsv, "name\tver\nknut\t0.1\nkorp\t0.2");
}
#[test]
fn rows_to_tsv_no_header() {
let tsv = rows_to_tsv::<&str>(&[], vec![vec!["a".to_string(), "b".to_string()]]);
assert_eq!(tsv, "a\tb");
}
#[test]
fn poll_decodes_events_in_order() {
let ctx = egui::Context::default();
let input = egui::RawInput {
events: vec![
egui::Event::Copy,
egui::Event::Paste("hello".to_string()),
egui::Event::Cut,
],
..Default::default()
};
let mut got = Vec::new();
let _ = ctx.run(input, |ctx| {
got = poll(ctx);
});
assert_eq!(got, vec![ClipAction::Copy, ClipAction::Paste("hello".to_string()), ClipAction::Cut]);
}
}