use re_log_types::EntityPath;
use re_ui::{
CmdRow, CommandPalette, CommandPaletteProvider, FuzzyMatch, FuzzyQuery, MatchGroup, MatchedCmd,
SyntaxHighlighting as _, UICommand, UiExt as _,
};
use url::Url;
fn main() -> eframe::Result {
let mut state = State::default();
let set_uo = std::sync::Once::new();
let options = eframe::NativeOptions::default();
eframe::run_ui_native("My egui App", options, move |ui, _frame| {
set_uo.call_once(|| {
re_ui::apply_style_and_install_loaders(ui);
});
state.ui(ui);
})
}
#[expect(dead_code, reason = "This is an example")]
#[derive(Debug)]
enum Command {
#[expect(clippy::enum_variant_names, reason = "This is an example")]
UiCommand(UICommand),
SelectEntityPath(String),
OpenUrl(Url),
}
impl Command {
fn tooltip(&self) -> &'static str {
match self {
Self::UiCommand(command) => command.tooltip(),
Self::SelectEntityPath(_) => "Select and focus on this entity",
Self::OpenUrl(_) => {
"Open this URL in the viewer. If the contents are already loaded, this will select them."
}
}
}
fn formatted_kb_shortcut(&self, egui_ctx: &egui::Context) -> Option<String> {
match self {
Self::UiCommand(command) => command.formatted_kb_shortcut(egui_ctx),
Self::SelectEntityPath(_) | Self::OpenUrl(_) => None,
}
}
}
struct RecordingInfo {
entities: Vec<&'static str>,
}
struct CommandProvider {
rec: Option<RecordingInfo>,
}
impl CommandPaletteProvider<Command> for CommandProvider {
fn initial_hint_ui(&mut self, ui: &mut egui::Ui) {
if self.rec.is_some() {
ui.weak("Find a command, search for an entity, or enter an URL to open");
} else {
ui.weak("Find a command or enter an URL to open");
}
ui.add_space(4.0);
}
fn all_matching(&mut self, query: &FuzzyQuery) -> Vec<MatchGroup<Command>> {
use strum::IntoEnumIterator as _;
let ui_cmd_group = if query.raw_query().starts_with('/') {
vec![] } else {
UICommand::iter()
.filter_map(|command| {
let enabled = true;
let target_text = command.text();
let command = Command::UiCommand(command);
if query.is_empty() {
Some(MatchedCmd {
command,
fuzzy_match: FuzzyMatch::lowest(target_text.to_owned()),
enabled,
})
} else {
query
.try_match(target_text.to_owned())
.map(|fuzzy_match| MatchedCmd {
command,
fuzzy_match,
enabled,
})
}
})
.collect()
};
let entity_group = if query.is_empty() {
vec![] } else if let Some(rec) = &self.rec {
rec.entities
.iter()
.filter_map(|&entity_path| {
query
.try_match(entity_path.to_owned())
.map(|fuzzy_match| MatchedCmd {
command: Command::SelectEntityPath(entity_path.to_owned()),
fuzzy_match,
enabled: true,
})
})
.collect()
} else {
vec![] };
let url_group = if let Ok(url) = query.raw_query().trim().parse::<Url>() {
vec![MatchedCmd {
fuzzy_match: FuzzyMatch::highest(url.to_string()),
command: Command::OpenUrl(url),
enabled: true,
}]
} else {
vec![]
};
vec![ui_cmd_group, entity_group, url_group]
}
fn cmd_row(&self, ui: &egui::Ui, matched: &MatchedCmd<Command>, selected: bool) -> CmdRow {
let kb_shortcut = matched
.command
.formatted_kb_shortcut(ui.ctx())
.unwrap_or_default();
let text_color = if !matched.enabled {
ui.visuals().weak_text_color()
} else if selected {
ui.visuals().selection.stroke.color
} else {
ui.visuals().widgets.inactive.fg_stroke.color
};
let job = if let Command::SelectEntityPath(ent_path) = &matched.command {
let mut job = EntityPath::parse_forgiving(ent_path).syntax_highlighted(ui.style());
if selected {
for section in &mut job.sections {
section.format.color = text_color;
}
}
job
} else {
egui::text::LayoutJob::simple(
matched.fuzzy_match.target().to_owned(),
egui::TextStyle::Button.resolve(ui.style()),
text_color,
f32::INFINITY,
)
};
let job = if matched.enabled {
matched
.fuzzy_match
.highlight_matching_text(ui.style(), &job, selected)
} else {
job
};
CmdRow {
job,
kb_shortcut,
tooltip: Some(matched.command.tooltip().to_owned()),
}
}
}
struct State {
cmd_palette: CommandPalette,
has_recording: bool,
latest_command: Option<Command>,
}
impl Default for State {
fn default() -> Self {
Self {
cmd_palette: Default::default(),
has_recording: true,
latest_command: Default::default(),
}
}
}
impl State {
fn ui(&mut self, ui: &mut egui::Ui) {
egui::CentralPanel::default().show(ui, |ui| {
ui.heading("Press cmd-K");
ui.re_checkbox(&mut self.has_recording, "Pretend to have a recording");
});
let mut cmd_provider = CommandProvider {
rec: self.has_recording.then(|| RecordingInfo {
entities: vec![
"/camera/pinhole",
"/camera/rgb",
"/world",
"/world/car",
"/world/car/front_camera",
"/world/car/imu",
"/world/road",
],
}),
};
if let Some(command) = self.cmd_palette.show(ui.ctx(), &mut cmd_provider) {
self.on_command(ui, command);
}
if let Some(ui_cmd) = re_ui::UICommand::listen_for_kb_shortcut(ui) {
self.on_command(ui, Command::UiCommand(ui_cmd));
}
}
fn on_command(&mut self, ui: &egui::Ui, command: Command) {
match command {
Command::UiCommand(ui_cmd) => match ui_cmd {
UICommand::ToggleCommandPalette => self.cmd_palette.toggle(),
UICommand::ZoomIn => {
let mut zoom_factor = ui.zoom_factor();
zoom_factor += 0.1;
ui.set_zoom_factor(zoom_factor);
}
UICommand::ZoomOut => {
let mut zoom_factor = ui.zoom_factor();
zoom_factor -= 0.1;
ui.set_zoom_factor(zoom_factor);
}
UICommand::ZoomReset => {
ui.set_zoom_factor(1.0);
}
_ => {}
},
Command::SelectEntityPath(_) | Command::OpenUrl(_) => {
}
}
self.latest_command = Some(command);
}
}