diff --git a/crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs b/crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs index af82733e7d63..959720efd79b 100644 --- a/crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs +++ b/crates/store/re_types/definitions/rerun/blueprint/components/map_provider.fbs @@ -13,17 +13,11 @@ enum MapProvider: ubyte ( OpenStreetMap (default), /// Mapbox Streets is a minimalistic map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxStreets, /// Mapbox Dark is a dark-themed map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxDark, /// Mapbox Satellite is a satellite map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxSatellite, } diff --git a/crates/store/re_types/src/blueprint/components/map_provider.rs b/crates/store/re_types/src/blueprint/components/map_provider.rs index 65962e353be7..ad8101a200ff 100644 --- a/crates/store/re_types/src/blueprint/components/map_provider.rs +++ b/crates/store/re_types/src/blueprint/components/map_provider.rs @@ -28,18 +28,12 @@ pub enum MapProvider { OpenStreetMap = 1, /// Mapbox Streets is a minimalistic map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxStreets = 2, /// Mapbox Dark is a dark-themed map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxDark = 3, /// Mapbox Satellite is a satellite map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxSatellite = 4, } @@ -58,15 +52,9 @@ impl ::re_types_core::reflection::Enum for MapProvider { fn docstring_md(self) -> &'static str { match self { Self::OpenStreetMap => "`OpenStreetMap` is the default map provider.", - Self::MapboxStreets => { - "Mapbox Streets is a minimalistic map designed by Mapbox.\n\n**Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable." - } - Self::MapboxDark => { - "Mapbox Dark is a dark-themed map designed by Mapbox.\n\n**Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable." - } - Self::MapboxSatellite => { - "Mapbox Satellite is a satellite map designed by Mapbox.\n\n**Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable." - } + Self::MapboxStreets => "Mapbox Streets is a minimalistic map designed by Mapbox.", + Self::MapboxDark => "Mapbox Dark is a dark-themed map designed by Mapbox.", + Self::MapboxSatellite => "Mapbox Satellite is a satellite map designed by Mapbox.", } } } diff --git a/crates/viewer/re_component_ui/src/datatype_uis/enum_combobox.rs b/crates/viewer/re_component_ui/src/datatype_uis/enum_combobox.rs index e0e634512ec7..94d12164cd16 100644 --- a/crates/viewer/re_component_ui/src/datatype_uis/enum_combobox.rs +++ b/crates/viewer/re_component_ui/src/datatype_uis/enum_combobox.rs @@ -3,16 +3,70 @@ use re_viewer_context::{MaybeMutRef, ViewerContext}; use crate::response_utils::response_with_changes_of_inner; +/// Is a particular variant of an enum available for selection? If not, why? +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum VariantAvailable { + /// The variant is available + Yes, + + /// The variant is not available. + No { + /// The reason why the variant is not available, markdown formatted. + reason_markdown: String, + }, +} + +/// Trait for a type that can provide information about whether a particular variant of an enum is +/// available for selection. +pub trait VariantAvailableProvider { + fn is_variant_enabled(ctx: &ViewerContext<'_>, variant: EnumT) -> VariantAvailable; +} + +/// A variant available provider that makes all variants available. +struct AllEnumVariantAvailable { + _phantom: std::marker::PhantomData, +} + +impl VariantAvailableProvider + for AllEnumVariantAvailable +{ + fn is_variant_enabled(_ctx: &ViewerContext<'_>, _variant: EnumT) -> VariantAvailable { + VariantAvailable::Yes + } +} + +/// Edit or view an enum value using a combobox. All variants are available. pub fn edit_view_enum( - _ctx: &ViewerContext<'_>, + ctx: &ViewerContext<'_>, + ui: &mut egui::Ui, + current_value: &mut MaybeMutRef<'_, EnumT>, +) -> egui::Response { + edit_view_enum_with_variant_available::>( + ctx, + ui, + current_value, + ) +} + +/// Edit or view an enum value using a combobox. The availability of each variant is determined by +/// the provided `VariantAvailableProvider` type. +pub fn edit_view_enum_with_variant_available< + EnumT: re_types_core::reflection::Enum + re_types_core::Component, + VariantAvailT: VariantAvailableProvider, +>( + ctx: &ViewerContext<'_>, ui: &mut egui::Ui, current_value: &mut MaybeMutRef<'_, EnumT>, ) -> egui::Response { let id_salt = EnumT::name().full_name(); - edit_view_enum_impl(ui, id_salt, current_value) + edit_view_enum_impl::<_, VariantAvailT>(ctx, ui, id_salt, current_value) } -fn edit_view_enum_impl( +fn edit_view_enum_impl< + EnumT: re_types_core::reflection::Enum, + VariantAvailT: VariantAvailableProvider, +>( + ctx: &ViewerContext<'_>, ui: &mut egui::Ui, id_salt: &str, current_value: &mut MaybeMutRef<'_, EnumT>, @@ -32,9 +86,19 @@ fn edit_view_enum_impl( return ui.label(""); }; - let mut response = variant_ui(ui, current_value, first); + let mut response = crate::datatype_uis::enum_combobox::variant_ui( + ui, + current_value, + first, + VariantAvailT::is_variant_enabled(ctx, first), + ); for variant in iter { - response |= variant_ui(ui, current_value, variant); + response |= variant_ui( + ui, + current_value, + variant, + VariantAvailT::is_variant_enabled(ctx, variant), + ); } response }); @@ -53,9 +117,24 @@ fn variant_ui( ui: &mut egui::Ui, current_value: &mut EnumT, variant: EnumT, + variant_available: VariantAvailable, ) -> egui::Response { - ui.selectable_value(current_value, variant, variant.to_string()) - .on_hover_ui(|ui| { - ui.markdown_ui(variant.docstring_md()); - }) + match variant_available { + VariantAvailable::Yes => ui + .selectable_value(current_value, variant, variant.to_string()) + .on_hover_ui(|ui| { + ui.markdown_ui(variant.docstring_md()); + }), + VariantAvailable::No { + reason_markdown: reason, + } => { + ui.add_enabled_ui(false, |ui| { + ui.selectable_value(current_value, variant, variant.to_string()) + .on_disabled_hover_ui(|ui| { + ui.markdown_ui(&format!("{}\n\n{}", variant.docstring_md(), reason)); + }) + }) + .inner + } + } } diff --git a/crates/viewer/re_component_ui/src/datatype_uis/mod.rs b/crates/viewer/re_component_ui/src/datatype_uis/mod.rs index ea58de5b26c8..7f6a0da34b82 100644 --- a/crates/viewer/re_component_ui/src/datatype_uis/mod.rs +++ b/crates/viewer/re_component_ui/src/datatype_uis/mod.rs @@ -7,7 +7,10 @@ mod vec; mod view_id; pub use bool_toggle::edit_bool; -pub use enum_combobox::edit_view_enum; +pub use enum_combobox::{ + edit_view_enum, edit_view_enum_with_variant_available, VariantAvailable, + VariantAvailableProvider, +}; pub use float_drag::{ edit_f32_min_to_max_float, edit_f32_zero_to_max, edit_f32_zero_to_one, edit_f64_float_raw_with_speed_impl, diff --git a/crates/viewer/re_component_ui/src/lib.rs b/crates/viewer/re_component_ui/src/lib.rs index 45bc3dae9458..5c2404cd7a7c 100644 --- a/crates/viewer/re_component_ui/src/lib.rs +++ b/crates/viewer/re_component_ui/src/lib.rs @@ -9,6 +9,7 @@ mod entity_path; mod fallback_ui; mod image_format; mod line_strip; +mod map_provider; mod marker_shape; mod pinhole; mod radius; @@ -24,7 +25,7 @@ mod zoom_level; use datatype_uis::{ display_name_ui, display_text_ui, edit_bool, edit_f32_min_to_max_float, edit_f32_zero_to_max, edit_f32_zero_to_one, edit_multiline_string, edit_or_view_vec3d, edit_singleline_string, - edit_view_enum, edit_view_range1d, view_view_id, + edit_view_enum, edit_view_enum_with_variant_available, edit_view_range1d, view_view_id, }; use re_types::{ @@ -94,7 +95,12 @@ pub fn create_component_ui_registry() -> re_viewer_context::ComponentUiRegistry registry.add_singleline_edit_or_view::(edit_view_enum); registry.add_singleline_edit_or_view::(edit_view_enum); registry.add_singleline_edit_or_view::(edit_view_enum); - registry.add_singleline_edit_or_view::(edit_view_enum); + registry.add_singleline_edit_or_view::( + edit_view_enum_with_variant_available::< + MapProvider, + crate::map_provider::MapProviderVariantAvailable, + >, + ); registry.add_singleline_edit_or_view::(edit_view_enum); registry.add_singleline_edit_or_view::(edit_view_enum); diff --git a/crates/viewer/re_component_ui/src/map_provider.rs b/crates/viewer/re_component_ui/src/map_provider.rs new file mode 100644 index 000000000000..b44c0b990b22 --- /dev/null +++ b/crates/viewer/re_component_ui/src/map_provider.rs @@ -0,0 +1,32 @@ +use re_types::blueprint::components::MapProvider; +use re_viewer_context::ViewerContext; + +use crate::datatype_uis::{VariantAvailable, VariantAvailableProvider}; + +pub struct MapProviderVariantAvailable; + +impl VariantAvailableProvider for MapProviderVariantAvailable { + fn is_variant_enabled(ctx: &ViewerContext<'_>, variant: MapProvider) -> VariantAvailable { + let map_box_available = if ctx + .app_options + .mapbox_access_token() + .is_some_and(|token| !token.is_empty()) + { + VariantAvailable::Yes + } else { + VariantAvailable::No { + reason_markdown: "A Mapbox access token is not available. You can set it in the \ + settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable." + .to_owned(), + } + }; + + match variant { + MapProvider::OpenStreetMap => VariantAvailable::Yes, + + MapProvider::MapboxStreets | MapProvider::MapboxDark | MapProvider::MapboxSatellite => { + map_box_available + } + } + } +} diff --git a/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp b/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp index 450519b812d8..1dd03dbd68e7 100644 --- a/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp +++ b/rerun_cpp/src/rerun/blueprint/components/map_provider.hpp @@ -27,18 +27,12 @@ namespace rerun::blueprint::components { OpenStreetMap = 1, /// Mapbox Streets is a minimalistic map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxStreets = 2, /// Mapbox Dark is a dark-themed map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxDark = 3, /// Mapbox Satellite is a satellite map designed by Mapbox. - /// - /// **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. MapboxSatellite = 4, }; } // namespace rerun::blueprint::components diff --git a/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py b/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py index 3a77f4990089..eb52209dd421 100644 --- a/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py +++ b/rerun_py/rerun_sdk/rerun/blueprint/components/map_provider.py @@ -28,25 +28,13 @@ class MapProvider(Enum): """`OpenStreetMap` is the default map provider.""" MapboxStreets = 2 - """ - Mapbox Streets is a minimalistic map designed by Mapbox. - - **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. - """ + """Mapbox Streets is a minimalistic map designed by Mapbox.""" MapboxDark = 3 - """ - Mapbox Dark is a dark-themed map designed by Mapbox. - - **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. - """ + """Mapbox Dark is a dark-themed map designed by Mapbox.""" MapboxSatellite = 4 - """ - Mapbox Satellite is a satellite map designed by Mapbox. - - **Note**: Requires a Mapbox access token in the settings or using the `RERUN_MAPBOX_ACCESS_TOKEN` environment variable. - """ + """Mapbox Satellite is a satellite map designed by Mapbox.""" @classmethod def auto(cls, val: str | int | MapProvider) -> MapProvider: