use bevy::prelude::*;
use bevy_color::palettes::css::{BLUE, GREEN, ORANGE, ORANGE_RED, WHITE, YELLOW_GREEN};
use bevy_nested_tooltips::prelude::*;
use bevy_platform::collections::HashMap;
use bevy_ui::RelativeCursorPosition;
use bevy_window::WindowMode;
#[derive(Component)]
struct LockMessage;
#[derive(Component)]
struct ConfigActivationText;
fn main() -> AppExit {
App::new()
.add_plugins((
DefaultPlugins.set(WindowPlugin {
primary_window: Some(Window {
mode: WindowMode::BorderlessFullscreen(MonitorSelection::Current),
..Default::default()
}),
..Default::default()
}),
NestedTooltipPlugin,
))
.add_systems(Startup, spawn_scene)
.add_systems(Update, update_settings)
.add_observer(style_tooltip)
.add_observer(query_style)
.add_observer(add_highlight)
.add_observer(remove_highlight)
.add_observer(display_locking)
.add_observer(display_unlocking)
.run()
}
fn spawn_scene(mut commands: Commands) {
commands.spawn(Camera2d);
edge_panels(&mut commands);
let interaction_screen = Node {
left: Val::Percent(30.),
top: Val::Percent(30.),
width: Val::Vw(45.),
height: Val::Vh(45.),
display: Display::Grid,
grid_template_rows: vec![GridTrack::fr(1.), GridTrack::fr(5.)],
position_type: PositionType::Absolute,
..Default::default()
};
let background_colour = BackgroundColor(Oklcha::lch(0.7, 0.1, 229.).into());
commands.spawn((
interaction_screen,
background_colour,
children![
(
Node {
display: Display::Flex,
justify_content: JustifyContent::Center,
width: Val::Percent(100.),
..Default::default()
},
children![(
Text::new("Bevy nested tooltips!"),
TextFont {
font_size: FontSize::Px(50.),
..Default::default()
}
)]
),
(
Node {
width: Val::Percent(100.),
..Default::default()
},
BackgroundColor(YELLOW_GREEN.into()),
Text::new("I am a "),
RelativeCursorPosition::default(),
children![
(
TextSpan::new("ToolTip"),
TooltipTermLink::new("tooltip"),
TextColor(BLUE.into())
),
TextSpan::new(" press middle mouse over it! "),
(
TextSpan::new("top"),
TooltipHighlightLink("top".into()),
TextColor(GREEN.into())
),
TextSpan::new(" "),
(
TextSpan::new("bottom"),
TooltipHighlightLink("bottom".into()),
TextColor(GREEN.into())
),
]
),
(
Node {
width: Val::Percent(100.),
..Default::default()
},
BackgroundColor(YELLOW_GREEN.into()),
Text::new("Press 'a' to change me between hover and middle mouse "),
children![(
TextSpan::new("I am currently on hover"),
ConfigActivationText
)]
)
],
));
let mut tooltip_map = TooltipMap {
map: HashMap::new(),
};
tooltip_map.insert(
"tooltip".into(),
TooltipsData::new(
"ToolTip",
vec![
TooltipsContent::String("A way to give users infomation can be ".into()),
TooltipsContent::Term("recursive".into()),
TooltipsContent::String(" ".into()),
TooltipsContent::Highlight("left".into()),
TooltipsContent::String(" ".into()),
TooltipsContent::Highlight("right".into()),
TooltipsContent::String(" Press middle mouse button to lock me. ".into()),
],
),
);
tooltip_map.insert(
"recursive".into(),
TooltipsData::new(
"Recursive",
vec![
TooltipsContent::String("Tooltips can be ".into()),
TooltipsContent::Term("recursive".into()),
TooltipsContent::String(
" You can highlight specific ui panels with such as the ".into(),
),
TooltipsContent::Highlight("sides".into()),
TooltipsContent::String(" Press middle mouse button to lock me. ".into()),
],
),
);
commands.insert_resource(tooltip_map);
}
fn edge_panels(commands: &mut Commands) {
let left_node = Node {
position_type: PositionType::Absolute,
left: percent(0),
top: percent(10),
bottom: auto(),
width: percent(5),
height: percent(80),
..Default::default()
};
commands.spawn((
left_node,
BackgroundColor(BLUE.into()),
TooltipHighlight(vec!["left".into(), "sides".into()]),
));
let right_node = Node {
position_type: PositionType::Absolute,
right: percent(0),
top: percent(10),
width: percent(5),
height: percent(80),
..Default::default()
};
commands.spawn((
right_node,
BackgroundColor(BLUE.into()),
TooltipHighlight(vec!["right".into(), "sides".into()]),
));
let top_node = Node {
position_type: PositionType::Absolute,
right: percent(10),
top: percent(0),
width: percent(80),
height: percent(10),
..Default::default()
};
commands.spawn((
top_node,
BackgroundColor(BLUE.into()),
TooltipHighlight(vec!["top".into()]),
));
let bottom_node = Node {
position_type: PositionType::Absolute,
right: percent(10),
bottom: percent(0),
width: percent(80),
height: percent(10),
..Default::default()
};
commands.spawn((
bottom_node,
BackgroundColor(BLUE.into()),
TooltipHighlight(vec!["bottom".into()]),
));
}
fn style_tooltip(tooltip: On<Add, Tooltip>, mut commands: Commands) {
commands
.get_entity(tooltip.entity)
.unwrap()
.insert((BackgroundColor(ORANGE.into()), BorderColor::all(WHITE)));
}
fn query_style(
new_tooltip: On<TooltipSpawned>,
tooltip_info: TooltipEntitiesParam,
mut commands: Commands,
) {
let tooltip_info = tooltip_info
.tooltip_child_entities(new_tooltip.entity)
.unwrap();
commands
.get_entity(tooltip_info.title_node)
.unwrap()
.insert(Node {
display: Display::Flex,
justify_content: JustifyContent::Center,
width: Val::Percent(100.),
..Default::default()
});
commands
.get_entity(tooltip_info.title_text)
.unwrap()
.insert(TextFont {
font_size: FontSize::Px(40.),
..Default::default()
});
for highlight_entity in tooltip_info.highlight_texts {
commands
.get_entity(highlight_entity)
.unwrap()
.insert(TextColor(GREEN.into()));
}
for term_entity in tooltip_info.term_texts {
commands
.get_entity(term_entity)
.unwrap()
.insert(TextColor(BLUE.into()));
}
}
fn add_highlight(side: On<Add, TooltipHighlighting>, mut commands: Commands) {
commands
.get_entity(side.entity)
.unwrap()
.insert(BackgroundColor(GREEN.into()));
}
fn remove_highlight(side: On<Remove, TooltipHighlighting>, mut commands: Commands) {
commands
.get_entity(side.entity)
.unwrap()
.insert(BackgroundColor(BLUE.into()));
}
fn display_locking(lock: On<Add, TooltipLocked>, mut commands: Commands) {
let id = commands
.spawn((
Text::new("I have been locked"),
TextFont::from_font_size(10.),
LockMessage,
))
.id();
commands
.get_entity(lock.entity)
.unwrap()
.insert(BackgroundColor(ORANGE_RED.into()))
.add_child(id);
}
fn display_unlocking(
lock: On<Remove, TooltipLocked>,
message_lock_query: Query<(Entity, &ChildOf), With<LockMessage>>,
mut commands: Commands,
) {
commands
.get_entity(lock.entity)
.unwrap()
.insert(BackgroundColor(ORANGE.into()));
if let Some((entity, _)) = message_lock_query
.iter()
.find(|item| item.1.0 == lock.entity)
{
commands.get_entity(entity).unwrap().despawn();
}
}
fn update_settings(
keycode: Res<ButtonInput<KeyCode>>,
mut activation_text_query: Query<&mut TextSpan, With<ConfigActivationText>>,
mut config: ResMut<TooltipConfiguration>,
) {
let activation = config.activation_method.clone();
if keycode.just_pressed(KeyCode::KeyA) {
for mut text in &mut activation_text_query {
match activation {
ActivationMethod::MiddleMouse => {
text.0 = "I am currently on hover".to_string();
config.activation_method = ActivationMethod::default();
}
ActivationMethod::Hover { .. } => {
config.activation_method = ActivationMethod::MiddleMouse;
text.0 = "I am currently on middle mouse".to_string()
}
}
}
}
}