From 848786f994980ed8d49d23991b1a84a5e50ab295 Mon Sep 17 00:00:00 2001 From: Ben Frankel Date: Mon, 19 Aug 2024 19:19:22 -0700 Subject: [PATCH] impl `From` for stuff --- src/context.rs | 16 +++---- src/lib.rs | 113 +++++++++++++++++++++++++++++++++-------------- src/placement.rs | 74 +++++++++++++++---------------- 3 files changed, 123 insertions(+), 80 deletions(-) diff --git a/src/context.rs b/src/context.rs index 8a603f3..2aaf490 100644 --- a/src/context.rs +++ b/src/context.rs @@ -19,7 +19,7 @@ use bevy_ui::{Interaction, UiStack}; use bevy_window::{PrimaryWindow, Window, WindowRef}; use tiny_bail::prelude::*; -use crate::{PrimaryTooltip, Tooltip, TooltipEntity, TooltipSet}; +use crate::{PrimaryTooltip, Tooltip, TooltipContent, TooltipSet}; pub(super) fn plugin(app: &mut App) { app.register_type::(); @@ -65,7 +65,7 @@ impl Default for TooltipContext { target: Entity::PLACEHOLDER, timer: 0, cursor_pos: Vec2::ZERO, - tooltip: Tooltip::custom(Entity::PLACEHOLDER), + tooltip: Tooltip::new(Entity::PLACEHOLDER), } } } @@ -84,9 +84,9 @@ fn update_tooltip_context( ) { let old_active = matches!(ctx.state, TooltipState::Active); let old_target = ctx.target; - let old_entity = match ctx.tooltip.entity { - TooltipEntity::Primary(_) => primary.container, - TooltipEntity::Custom(id) => id, + let old_entity = match ctx.tooltip.content { + TooltipContent::Primary(_) => primary.container, + TooltipContent::Custom(id) => id, }; // TODO: Reconsider whether this is the right way to detect cursor movement. @@ -234,14 +234,14 @@ fn show_tooltip( mut text_query: Query<&mut Text>, mut visibility_query: Query<&mut Visibility>, ) { - let entity = match &mut ctx.tooltip.entity { - TooltipEntity::Primary(ref mut text) => { + let entity = match &mut ctx.tooltip.content { + TooltipContent::Primary(ref mut text) => { if let Ok(mut primary_text) = text_query.get_mut(primary.text) { *primary_text = std::mem::take(text); } primary.container } - TooltipEntity::Custom(id) => *id, + TooltipContent::Custom(id) => *id, }; *r!(visibility_query.get_mut(entity)) = Visibility::Visible; } diff --git a/src/lib.rs b/src/lib.rs index 7a14354..fdaee68 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -29,7 +29,7 @@ //! To customize tooltip behavior, see [`Tooltip`]. //! //! To set a custom primary tooltip, see [`TooltipPlugin`] and [`PrimaryTooltip`]. -//! For fully custom per-entity tooltips, use [`TooltipEntity::Custom`]. +//! For fully custom per-entity tooltips, use [`TooltipContent::Custom`]. mod context; mod placement; @@ -43,8 +43,8 @@ mod placement; /// ``` pub mod prelude { pub use super::{ - PrimaryTooltip, Tooltip, TooltipActivation, TooltipEntity, TooltipPlacement, TooltipPlugin, - TooltipSet, TooltipTransfer, + PrimaryTooltip, Tooltip, TooltipActivation, TooltipContent, TooltipPlacement, + TooltipPlugin, TooltipSet, TooltipTransfer, }; } @@ -196,67 +196,61 @@ pub struct Tooltip { /// How the position of the tooltip entity should be determined. pub placement: TooltipPlacement, /// The entity to display as the tooltip. - pub entity: TooltipEntity, + pub content: TooltipContent, } impl Tooltip { - /// Use the provided tooltip entity and default behavior. - fn new(entity: TooltipEntity) -> Self { + /// Construct a new `Tooltip` with default behavior. + pub fn new(content: impl Into) -> Self { Self { activation: TooltipActivation::IDLE, transfer: TooltipTransfer::NONE, placement: TooltipPlacement::CURSOR, - entity, + content: content.into(), } } - /// Use a custom tooltip entity and default behavior. - pub fn custom(entity: Entity) -> Self { - Self::new(TooltipEntity::Custom(entity)) - } - - /// Use the primary tooltip entity with a single [`TextSection`] and default behavior. + /// Construct a new `Tooltip` from a single [`TextSection`] and default behavior. pub fn from_section(value: impl Into, style: TextStyle) -> Self { - Self::new(TooltipEntity::Primary(Text::from_section(value, style))) + Self::new(TooltipContent::Primary(Text::from_section(value, style))) } - /// Use the primary tooltip entity with a list of [`TextSection`]s and default behavior. + /// Construct a new `Tooltip` from a list of [`TextSection`]s and default behavior. pub fn from_sections(sections: impl IntoIterator) -> Self { - Self::new(TooltipEntity::Primary(Text::from_sections(sections))) + Self::new(TooltipContent::Primary(Text::from_sections(sections))) } - /// Use the primary tooltip entity with a given [`Text`] and default behavior. + /// Construct a new `Tooltip` from a given [`Text`] and default behavior. pub fn from_text(text: impl Into) -> Self { - Self::new(TooltipEntity::Primary(text.into())) + Self::new(TooltipContent::Primary(text.into())) } - /// Set the [`JustifyText`]. + /// Set [`JustifyText`]. /// - /// NOTE: This does nothing with a custom tooltip. + /// NOTE: This does nothing for custom tooltips. pub fn with_justify_text(mut self, justify_text: JustifyText) -> Self { - match &mut self.entity { - TooltipEntity::Primary(text) => text.justify = justify_text, - // TODO: Warn? - _ => (), + // TODO: Warn otherwise? + if let TooltipContent::Primary(text) = &mut self.content { + text.justify = justify_text; } self } - /// Set a custom [`TooltipActivation`]. - pub fn with_activation(mut self, activation: TooltipActivation) -> Self { - self.activation = activation; + /// Set [`TooltipActivation`]. + pub fn with_activation(mut self, activation: impl Into) -> Self { + self.activation = activation.into(); self } - /// Set a custom [`TooltipTransfer`]. - pub fn with_transfer(mut self, transfer: TooltipTransfer) -> Self { - self.transfer = transfer; + /// Set [`TooltipTransfer`]. + pub fn with_transfer(mut self, transfer: impl Into) -> Self { + self.transfer = transfer.into(); self } - /// Set a custom [`TooltipPlacement`]. - pub fn with_placement(mut self, placement: TooltipPlacement) -> Self { - self.placement = placement; + /// Set [`TooltipPlacement`]. + pub fn with_placement(mut self, placement: impl Into) -> Self { + self.placement = placement.into(); self } } @@ -327,6 +321,16 @@ impl TooltipActivation { }; } +impl From for TooltipActivation { + fn from(value: u16) -> Self { + Self { + delay: value, + reset_delay_on_cursor_move: false, + dismiss_radius: f32::INFINITY, + } + } +} + impl Default for TooltipActivation { fn default() -> Self { Self::IMMEDIATE @@ -369,6 +373,17 @@ impl TooltipTransfer { }; } +impl From for TooltipTransfer { + fn from(value: u16) -> Self { + Self { + group: Some(0), + layer: 0, + timeout: value, + from_active: true, + } + } +} + impl Default for TooltipTransfer { fn default() -> Self { Self::NONE @@ -378,13 +393,43 @@ impl Default for TooltipTransfer { /// The tooltip entity and content to be displayed. #[derive(Clone, Debug)] #[cfg_attr(feature = "bevy_reflect", derive(bevy_reflect::Reflect))] -pub enum TooltipEntity { +pub enum TooltipContent { /// Use the primary tooltip entity with custom [`Text`]. Primary(Text), /// Use a fully custom entity as the tooltip. Custom(Entity), } +impl From<&str> for TooltipContent { + fn from(value: &str) -> Self { + Self::Primary(Text::from_section(value.to_string(), TextStyle::default())) + } +} + +impl From for TooltipContent { + fn from(value: String) -> Self { + Self::Primary(Text::from_section(value, TextStyle::default())) + } +} + +impl From for TooltipContent { + fn from(value: TextSection) -> Self { + Self::Primary(Text::from_section(value.value, value.style)) + } +} + +impl From for TooltipContent { + fn from(value: Text) -> Self { + Self::Primary(value) + } +} + +impl From for TooltipContent { + fn from(value: Entity) -> Self { + Self::Custom(value) + } +} + /// A [`SystemSet`] for tooltip systems. #[derive(SystemSet, Copy, Clone, Eq, PartialEq, Hash, Debug)] pub enum TooltipSet { diff --git a/src/placement.rs b/src/placement.rs index 8640eca..a44f2f6 100644 --- a/src/placement.rs +++ b/src/placement.rs @@ -15,7 +15,7 @@ use tiny_bail::prelude::*; use crate::{ context::{TooltipContext, TooltipState}, - PrimaryTooltip, TooltipEntity, TooltipSet, + PrimaryTooltip, TooltipContent, TooltipSet, }; pub(super) fn plugin(app: &mut App) { @@ -58,42 +58,40 @@ impl TooltipPlacement { offset_y: Val::Px(16.0), clamp_padding: UiRect::ZERO, }; +} - /// Show tooltip to the left of target. - pub const LEFT: Self = Self { - tooltip_anchor: Anchor::CenterRight, - target_anchor: Some(Anchor::CenterLeft), - offset_x: Val::ZERO, - offset_y: Val::ZERO, - clamp_padding: UiRect::ZERO, - }; - - /// Show tooltip to the right of target. - pub const RIGHT: Self = Self { - tooltip_anchor: Anchor::CenterLeft, - target_anchor: Some(Anchor::CenterRight), - offset_x: Val::ZERO, - offset_y: Val::ZERO, - clamp_padding: UiRect::ZERO, - }; - - /// Show tooltip above target. - pub const TOP: Self = Self { - tooltip_anchor: Anchor::BottomCenter, - target_anchor: Some(Anchor::TopCenter), - offset_x: Val::ZERO, - offset_y: Val::ZERO, - clamp_padding: UiRect::ZERO, - }; +impl From for TooltipPlacement { + fn from(value: Anchor) -> Self { + Self { + tooltip_anchor: match value { + Anchor::Center | Anchor::Custom(_) => Anchor::Center, + Anchor::BottomLeft => Anchor::TopRight, + Anchor::BottomCenter => Anchor::TopCenter, + Anchor::BottomRight => Anchor::TopLeft, + Anchor::CenterLeft => Anchor::CenterRight, + Anchor::CenterRight => Anchor::CenterLeft, + Anchor::TopLeft => Anchor::BottomRight, + Anchor::TopCenter => Anchor::BottomCenter, + Anchor::TopRight => Anchor::BottomLeft, + }, + target_anchor: Some(value), + offset_x: Val::ZERO, + offset_y: Val::ZERO, + clamp_padding: UiRect::ZERO, + } + } +} - /// Show tooltip below target. - pub const BOTTOM: Self = Self { - tooltip_anchor: Anchor::TopCenter, - target_anchor: Some(Anchor::BottomCenter), - offset_x: Val::ZERO, - offset_y: Val::ZERO, - clamp_padding: UiRect::ZERO, - }; +impl From for TooltipPlacement { + fn from(value: Vec2) -> Self { + Self { + tooltip_anchor: Anchor::TopLeft, + target_anchor: None, + offset_x: Val::Px(value.x), + offset_y: Val::Px(value.y), + clamp_padding: UiRect::ZERO, + } + } } impl Default for TooltipPlacement { @@ -116,9 +114,9 @@ fn place_tooltip( ) { rq!(matches!(ctx.state, TooltipState::Active)); let (target_gt, target_node) = rq!(target_query.get(ctx.target)); - let entity = match &ctx.tooltip.entity { - TooltipEntity::Primary(_) => primary.container, - &TooltipEntity::Custom(id) => id, + let entity = match &ctx.tooltip.content { + TooltipContent::Primary(_) => primary.container, + &TooltipContent::Custom(id) => id, }; let (mut style, mut transform, gt, node) = or_return!(tooltip_query.get_mut(entity));