Skip to content

Commit

Permalink
Add Help and Discord to command palette (#4752)
Browse files Browse the repository at this point in the history
### What
You can now open the help web site and visit the Rerun Discord from the
command pallette.

* Closes #4436

### Checklist
* [x] I have read and agree to [Contributor
Guide](https://github.com/rerun-io/rerun/blob/main/CONTRIBUTING.md) and
the [Code of
Conduct](https://github.com/rerun-io/rerun/blob/main/CODE_OF_CONDUCT.md)
* [x] I've included a screenshot or gif (if applicable)
* [x] I have tested the web demo (if applicable):
* Using newly built examples:
[app.rerun.io](https://app.rerun.io/pr/4752/index.html)
* Using examples from latest `main` build:
[app.rerun.io](https://app.rerun.io/pr/4752/index.html?manifest_url=https://app.rerun.io/version/main/examples_manifest.json)
* Using full set of examples from `nightly` build:
[app.rerun.io](https://app.rerun.io/pr/4752/index.html?manifest_url=https://app.rerun.io/version/nightly/examples_manifest.json)
* [x] The PR title and labels are set such as to maximize their
usefulness for the next release's CHANGELOG

- [PR Build Summary](https://build.rerun.io/pr/4752)
- [Docs
preview](https://rerun.io/preview/348636dd01a5a97f5efe7992720243d309f44948/docs)
<!--DOCS-PREVIEW-->
- [Examples
preview](https://rerun.io/preview/348636dd01a5a97f5efe7992720243d309f44948/examples)
<!--EXAMPLES-PREVIEW-->
- [Recent benchmark results](https://build.rerun.io/graphs/crates.html)
- [Wasm size tracking](https://build.rerun.io/graphs/sizes.html)

---------

Co-authored-by: Andreas Reich <andreas@rerun.io>
  • Loading branch information
emilk and Wumpf authored Jan 9, 2024
1 parent 0e41edc commit cff545f
Show file tree
Hide file tree
Showing 5 changed files with 138 additions and 119 deletions.
4 changes: 1 addition & 3 deletions crates/re_types/src/tensor_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,9 +551,7 @@ impl DecodedTensor {
jpeg_bytes: &::re_types_core::ArrowBuffer<u8>,
[expected_height, expected_width, expected_channels]: [u64; 3],
) -> Result<DecodedTensor, TensorImageLoadError> {
re_tracing::profile_function!();

re_log::debug!("Decoding {expected_width}x{expected_height} JPEG");
re_tracing::profile_function!(format!("{expected_width}x{expected_height}"));

use zune_core::colorspace::ColorSpace;
use zune_core::options::DecoderOptions;
Expand Down
153 changes: 95 additions & 58 deletions crates/re_ui/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ pub enum UICommand {
#[cfg(not(target_arch = "wasm32"))]
Quit,

OpenWebHelp,
OpenRerunDiscord,

ResetViewer,

#[cfg(not(target_arch = "wasm32"))]
Expand Down Expand Up @@ -78,95 +81,98 @@ impl UICommand {
pub fn text_and_tooltip(self) -> (&'static str, &'static str) {
match self {
#[cfg(not(target_arch = "wasm32"))]
UICommand::Save => ("Save…", "Save all data to a Rerun data file (.rrd)"),
Self::Save => ("Save…", "Save all data to a Rerun data file (.rrd)"),

#[cfg(not(target_arch = "wasm32"))]
UICommand::SaveSelection => (
Self::SaveSelection => (
"Save loop selection…",
"Save data for the current loop selection to a Rerun data file (.rrd)",
),

UICommand::Open => ("Open…", "Open any supported files (.rrd, images, meshes, …)"),
Self::Open => ("Open…", "Open any supported files (.rrd, images, meshes, …)"),

UICommand::CloseCurrentRecording => (
Self::CloseCurrentRecording => (
"Close current Recording",
"Close the current Recording (unsaved data will be lost)",
),

#[cfg(not(target_arch = "wasm32"))]
UICommand::Quit => ("Quit", "Close the Rerun Viewer"),
Self::Quit => ("Quit", "Close the Rerun Viewer"),

Self::OpenWebHelp => ("Help", "Visit the help page on our website, with troubleshooting tips and more"),
Self::OpenRerunDiscord => ("Rerun Discord", "Visit the Rerun Discord server, where you can ask questions and get help"),

UICommand::ResetViewer => (
Self::ResetViewer => (
"Reset Viewer",
"Reset the Viewer to how it looked the first time you ran it",
),

#[cfg(not(target_arch = "wasm32"))]
UICommand::OpenProfiler => (
Self::OpenProfiler => (
"Open profiler",
"Starts a profiler, showing what makes the viewer run slow",
),

UICommand::ToggleMemoryPanel => (
Self::ToggleMemoryPanel => (
"Toggle Memory Panel",
"View and track current RAM usage inside Rerun Viewer",
),
UICommand::ToggleBlueprintPanel => ("Toggle Blueprint Panel", "Toggle the left panel"),
UICommand::ToggleSelectionPanel => ("Toggle Selection Panel", "Toggle the right panel"),
UICommand::ToggleTimePanel => ("Toggle Time Panel", "Toggle the bottom panel"),
Self::ToggleBlueprintPanel => ("Toggle Blueprint Panel", "Toggle the left panel"),
Self::ToggleSelectionPanel => ("Toggle Selection Panel", "Toggle the right panel"),
Self::ToggleTimePanel => ("Toggle Time Panel", "Toggle the bottom panel"),

#[cfg(debug_assertions)]
UICommand::ToggleStylePanel => (
Self::ToggleStylePanel => (
"Toggle Style Panel",
"View and change global egui style settings",
),

#[cfg(not(target_arch = "wasm32"))]
UICommand::ToggleFullscreen => (
Self::ToggleFullscreen => (
"Toggle fullscreen",
"Toggle between windowed and fullscreen viewer",
),
#[cfg(not(target_arch = "wasm32"))]
UICommand::ZoomIn => ("Zoom In", "Increases the UI zoom level"),
Self::ZoomIn => ("Zoom In", "Increases the UI zoom level"),
#[cfg(not(target_arch = "wasm32"))]
UICommand::ZoomOut => ("Zoom Out", "Decreases the UI zoom level"),
Self::ZoomOut => ("Zoom Out", "Decreases the UI zoom level"),
#[cfg(not(target_arch = "wasm32"))]
UICommand::ZoomReset => (
Self::ZoomReset => (
"Reset Zoom",
"Resets the UI zoom level to the operating system's default value",
),

UICommand::SelectionPrevious => ("Previous selection", "Go to previous selection"),
UICommand::SelectionNext => ("Next selection", "Go to next selection"),
UICommand::ToggleCommandPalette => ("Command Palette…", "Toggle the Command Palette"),
Self::SelectionPrevious => ("Previous selection", "Go to previous selection"),
Self::SelectionNext => ("Next selection", "Go to next selection"),
Self::ToggleCommandPalette => ("Command Palette…", "Toggle the Command Palette"),

UICommand::PlaybackTogglePlayPause => {
Self::PlaybackTogglePlayPause => {
("Toggle play/pause", "Either play or pause the time")
}
UICommand::PlaybackFollow => ("Follow", "Follow on from end of timeline"),
UICommand::PlaybackStepBack => (
Self::PlaybackFollow => ("Follow", "Follow on from end of timeline"),
Self::PlaybackStepBack => (
"Step time back",
"Move the time marker back to the previous point in time with any data",
),
UICommand::PlaybackStepForward => (
Self::PlaybackStepForward => (
"Step time forward",
"Move the time marker to the next point in time with any data",
),
UICommand::PlaybackRestart => ("Restart", "Restart from beginning of timeline"),
Self::PlaybackRestart => ("Restart", "Restart from beginning of timeline"),

#[cfg(not(target_arch = "wasm32"))]
UICommand::ScreenshotWholeApp => (
Self::ScreenshotWholeApp => (
"Screenshot",
"Copy screenshot of the whole app to clipboard",
),
#[cfg(not(target_arch = "wasm32"))]
UICommand::PrintDatastore => (
Self::PrintDatastore => (
"Print datastore",
"Prints the entire data store to the console. WARNING: this may be A LOT of text.",
),

#[cfg(target_arch = "wasm32")]
UICommand::CopyDirectLink => (
Self::CopyDirectLink => (
"Copy direct link",
"Copy a link to the viewer with the URL parameter set to the current .rrd data source."
)
Expand Down Expand Up @@ -194,58 +200,73 @@ impl UICommand {

match self {
#[cfg(not(target_arch = "wasm32"))]
UICommand::Save => Some(cmd(Key::S)),
Self::Save => Some(cmd(Key::S)),
#[cfg(not(target_arch = "wasm32"))]
UICommand::SaveSelection => Some(cmd_alt(Key::S)),
UICommand::Open => Some(cmd(Key::O)),
UICommand::CloseCurrentRecording => None,
Self::SaveSelection => Some(cmd_alt(Key::S)),
Self::Open => Some(cmd(Key::O)),
Self::CloseCurrentRecording => None,

#[cfg(all(not(target_arch = "wasm32"), target_os = "windows"))]
UICommand::Quit => Some(KeyboardShortcut::new(Modifiers::ALT, Key::F4)),
Self::Quit => Some(KeyboardShortcut::new(Modifiers::ALT, Key::F4)),

Self::OpenWebHelp => None,
Self::OpenRerunDiscord => None,

#[cfg(all(not(target_arch = "wasm32"), not(target_os = "windows")))]
UICommand::Quit => Some(cmd(Key::Q)),
Self::Quit => Some(cmd(Key::Q)),

UICommand::ResetViewer => Some(ctrl_shift(Key::R)),
Self::ResetViewer => Some(ctrl_shift(Key::R)),
#[cfg(not(target_arch = "wasm32"))]
UICommand::OpenProfiler => Some(ctrl_shift(Key::P)),
UICommand::ToggleMemoryPanel => Some(ctrl_shift(Key::M)),
UICommand::ToggleBlueprintPanel => Some(ctrl_shift(Key::B)),
UICommand::ToggleSelectionPanel => Some(ctrl_shift(Key::S)),
UICommand::ToggleTimePanel => Some(ctrl_shift(Key::T)),
Self::OpenProfiler => Some(ctrl_shift(Key::P)),
Self::ToggleMemoryPanel => Some(ctrl_shift(Key::M)),
Self::ToggleBlueprintPanel => Some(ctrl_shift(Key::B)),
Self::ToggleSelectionPanel => Some(ctrl_shift(Key::S)),
Self::ToggleTimePanel => Some(ctrl_shift(Key::T)),

#[cfg(debug_assertions)]
UICommand::ToggleStylePanel => Some(ctrl_shift(Key::U)),
Self::ToggleStylePanel => Some(ctrl_shift(Key::U)),

#[cfg(not(target_arch = "wasm32"))]
UICommand::ToggleFullscreen => Some(key(Key::F11)),
Self::ToggleFullscreen => Some(key(Key::F11)),
#[cfg(not(target_arch = "wasm32"))]
UICommand::ZoomIn => Some(egui::gui_zoom::kb_shortcuts::ZOOM_IN),
Self::ZoomIn => Some(egui::gui_zoom::kb_shortcuts::ZOOM_IN),
#[cfg(not(target_arch = "wasm32"))]
UICommand::ZoomOut => Some(egui::gui_zoom::kb_shortcuts::ZOOM_OUT),
Self::ZoomOut => Some(egui::gui_zoom::kb_shortcuts::ZOOM_OUT),
#[cfg(not(target_arch = "wasm32"))]
UICommand::ZoomReset => Some(egui::gui_zoom::kb_shortcuts::ZOOM_RESET),
Self::ZoomReset => Some(egui::gui_zoom::kb_shortcuts::ZOOM_RESET),

UICommand::SelectionPrevious => Some(ctrl_shift(Key::ArrowLeft)),
UICommand::SelectionNext => Some(ctrl_shift(Key::ArrowRight)),
UICommand::ToggleCommandPalette => Some(cmd(Key::P)),
Self::SelectionPrevious => Some(ctrl_shift(Key::ArrowLeft)),
Self::SelectionNext => Some(ctrl_shift(Key::ArrowRight)),
Self::ToggleCommandPalette => Some(cmd(Key::P)),

UICommand::PlaybackTogglePlayPause => Some(key(Key::Space)),
UICommand::PlaybackFollow => Some(cmd(Key::ArrowRight)),
UICommand::PlaybackStepBack => Some(key(Key::ArrowLeft)),
UICommand::PlaybackStepForward => Some(key(Key::ArrowRight)),
UICommand::PlaybackRestart => Some(cmd(Key::ArrowLeft)),
Self::PlaybackTogglePlayPause => Some(key(Key::Space)),
Self::PlaybackFollow => Some(cmd(Key::ArrowRight)),
Self::PlaybackStepBack => Some(key(Key::ArrowLeft)),
Self::PlaybackStepForward => Some(key(Key::ArrowRight)),
Self::PlaybackRestart => Some(cmd(Key::ArrowLeft)),

#[cfg(not(target_arch = "wasm32"))]
UICommand::ScreenshotWholeApp => None,
Self::ScreenshotWholeApp => None,
#[cfg(not(target_arch = "wasm32"))]
UICommand::PrintDatastore => None,
Self::PrintDatastore => None,

#[cfg(target_arch = "wasm32")]
UICommand::CopyDirectLink => None,
Self::CopyDirectLink => None,
}
}

pub fn icon(self) -> Option<&'static crate::Icon> {
match self {
Self::OpenWebHelp => Some(&crate::icons::EXTERNAL_LINK),
Self::OpenRerunDiscord => Some(&crate::icons::DISCORD),
_ => None,
}
}

pub fn is_link(self) -> bool {
matches!(self, Self::OpenWebHelp | Self::OpenRerunDiscord)
}

#[must_use = "Returns the Command that was triggered by some keyboard shortcut"]
pub fn listen_for_kb_shortcut(egui_ctx: &egui::Context) -> Option<UICommand> {
use strum::IntoEnumIterator as _;
Expand All @@ -256,7 +277,7 @@ impl UICommand {
}

egui_ctx.input_mut(|input| {
for command in UICommand::iter() {
for command in Self::iter() {
if let Some(kb_shortcut) = command.kb_shortcut() {
if input.consume_shortcut(&kb_shortcut) {
return Some(command);
Expand All @@ -276,19 +297,35 @@ impl UICommand {
command_sender: &impl UICommandSender,
) -> egui::Response {
let button = self.menu_button(ui.ctx());
let response = ui.add(button).on_hover_text(self.tooltip());
let mut response = ui.add(button).on_hover_text(self.tooltip());

if self.is_link() {
response = response.on_hover_cursor(egui::CursorIcon::PointingHand);
}

if response.clicked() {
command_sender.send_ui(self);
ui.close_menu();
}

response
}

pub fn menu_button(self, egui_ctx: &egui::Context) -> egui::Button<'static> {
let mut button = egui::Button::new(self.text());
let mut button = if let Some(icon) = self.icon() {
egui::Button::image_and_text(
icon.as_image()
.fit_to_exact_size(crate::ReUi::small_icon_size()),
self.text(),
)
} else {
egui::Button::new(self.text())
};

if let Some(shortcut) = self.kb_shortcut() {
button = button.shortcut_text(egui_ctx.format_shortcut(&shortcut));
}

button
}

Expand Down
18 changes: 14 additions & 4 deletions crates/re_ui/src/command_palette.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,21 @@ impl CommandPalette {
let max_height = 320.0.at_most(screen_rect.height());

egui::Window::new("Command Palette")
.title_bar(false)
.fixed_pos(screen_rect.center() - 0.5 * max_height * egui::Vec2::Y)
.fixed_size([width, max_height])
.pivot(egui::Align2::CENTER_TOP)
.fixed_pos(screen_rect.center() - 0.5 * max_height * egui::Vec2::Y)
.show(egui_ctx, |ui| self.window_content_ui(ui))?
.resizable(false)
.scroll2(false)
.title_bar(false)
.show(egui_ctx, |ui| {
// We need an extra egui frame here because we set clip_rect_margin to zero.
egui::Frame {
inner_margin: 2.0.into(),
..Default::default()
}
.show(ui, |ui| self.window_content_ui(ui))
.inner
})?
.inner?
}

Expand Down Expand Up @@ -199,7 +209,7 @@ fn commands_that_match(query: &str) -> Vec<FuzzyMatch> {
})
})
.collect();
matches.sort_by_key(|m| -m.score);
matches.sort_by_key(|m| -m.score); // highest score first
matches
}
}
Expand Down
Loading

0 comments on commit cff545f

Please sign in to comment.