Skip to content

Commit fc7e5de

Browse files
committed
time panel context menu sharing
1 parent fc7f16d commit fc7e5de

File tree

2 files changed

+81
-27
lines changed

2 files changed

+81
-27
lines changed

crates/viewer/re_time_panel/src/time_control_ui.rs

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ impl TimeControlUi {
2525
ui.visuals_mut().widgets.hovered.expansion = 0.0;
2626
ui.visuals_mut().widgets.open.expansion = 0.0;
2727

28-
egui::ComboBox::from_id_salt("timeline")
28+
let response = egui::ComboBox::from_id_salt("timeline")
2929
.selected_text(time_control.timeline().name().as_str())
3030
.show_ui(ui, |ui| {
3131
for timeline in times_per_timeline.timelines() {
@@ -65,6 +65,25 @@ You can also define your own timelines, e.g. for sensor time or camera frame num
6565
true,
6666
);
6767
});
68+
});
69+
egui::Popup::menu(&response)
70+
.id(egui::Id::new("timeline select context menu"))
71+
.open_memory(if response.secondary_clicked() {
72+
Some(egui::SetOpenCommand::Bool(true))
73+
} else if response.clicked() {
74+
// Explicitly close the menu if the widget was clicked
75+
// Without this, the context menu would stay open if the user clicks the widget
76+
Some(egui::SetOpenCommand::Bool(false))
77+
} else {
78+
None
79+
})
80+
.at_pointer_fixed()
81+
.show(|ui| {
82+
if ui.button("Copy timeline name").clicked() {
83+
let timeline = format!("{}", time_control.timeline().name());
84+
re_log::info!("Copied timeline: {}", timeline);
85+
ui.ctx().copy_text(timeline);
86+
}
6887
})
6988
});
7089
}

crates/viewer/re_time_panel/src/time_panel.rs

Lines changed: 61 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ use re_ui::{ContextExt as _, DesignTokens, Help, UiExt as _, filter_widget, icon
2020
use re_ui::{IconText, filter_widget::format_matching_text};
2121
use re_viewer_context::{
2222
CollapseScope, HoverHighlight, Item, ItemCollection, ItemContext, RecordingConfig,
23-
SystemCommand, SystemCommandSender as _, TimeControl, TimeView, UiLayout, ViewerContext,
24-
VisitorControlFlow,
23+
SystemCommand, SystemCommandSender as _, TimeControl, TimeView, UiLayout, UrlContext,
24+
ViewerContext, VisitorControlFlow,
2525
};
2626
use re_viewport_blueprint::ViewportBlueprint;
2727

@@ -567,6 +567,7 @@ impl TimePanel {
567567
&self.time_ranges_ui,
568568
time_ctrl,
569569
ui,
570+
ctx,
570571
Some(&time_area_response),
571572
&time_area_painter,
572573
&timeline_rect,
@@ -1380,6 +1381,7 @@ impl TimePanel {
13801381
&time_ranges_ui,
13811382
time_ctrl,
13821383
ui,
1384+
ctx,
13831385
None,
13841386
&painter,
13851387
&time_range_rect,
@@ -1396,7 +1398,9 @@ impl TimePanel {
13961398
ui: &mut egui::Ui,
13971399
time_ctrl: &mut TimeControl,
13981400
) {
1399-
if let Some(time_int) = time_ctrl.time_int() {
1401+
if let Some(time_int) = time_ctrl.time_int()
1402+
&& let Some(time) = time_ctrl.time()
1403+
{
14001404
let time_type = time_ctrl.time_type();
14011405

14021406
let mut time_str = self
@@ -1418,11 +1422,11 @@ impl TimePanel {
14181422
}
14191423
self.time_edit_string = None;
14201424
}
1421-
response
1422-
.on_hover_text(format!("Timestamp: {}", time_int.as_i64()))
1423-
.context_menu(|ui| {
1424-
copy_time_properties_context_menu(ui, time_ctrl, None);
1425-
});
1425+
let response = response.on_hover_text(format!("Timestamp: {}", time_int.as_i64()));
1426+
1427+
response.context_menu(|ui| {
1428+
copy_time_properties_context_menu(ui, time);
1429+
});
14261430
}
14271431
}
14281432
}
@@ -1774,29 +1778,41 @@ fn interact_with_streams_rect(
17741778
}
17751779

17761780
/// Context menu that shows up when interacting with the streams rect.
1777-
fn copy_time_properties_context_menu(
1781+
fn copy_timeline_properties_context_menu(
17781782
ui: &mut egui::Ui,
1783+
ctx: &ViewerContext<'_>,
17791784
time_ctrl: &TimeControl,
1780-
hovered_time: Option<TimeReal>,
1785+
hovered_time: TimeReal,
17811786
) {
1782-
if let Some(time) = hovered_time {
1783-
if ui.button("Copy hovered timestamp").clicked() {
1784-
let time = format!("{}", time.floor().as_i64());
1785-
re_log::info!("Copied hovered timestamp: {}", time);
1786-
ui.ctx().copy_text(time);
1787-
}
1788-
} else if let Some(time) = time_ctrl.time_int()
1789-
&& ui.button("Copy current timestamp").clicked()
1787+
// TODO: Add shortcuts for these
1788+
if let Some(selected_time_range) = time_ctrl.active_loop_selection()
1789+
&& selected_time_range.contains(hovered_time)
17901790
{
1791-
let time = format!("{}", time.as_i64());
1792-
re_log::info!("Copied current timestamp: {}", time);
1791+
if ui.button("Copy link to trimmed range").clicked() {
1792+
ctx.command_sender()
1793+
.send_system(UrlContext::from_context(ctx).into_copy_cmd());
1794+
}
1795+
} else if ui.button("Copy link to timestamp").clicked() {
1796+
ctx.command_sender().send_system(
1797+
UrlContext::from_context(ctx)
1798+
.without_time_range()
1799+
.with_timestamp(time_ctrl.timeline(), hovered_time.into())
1800+
.into_copy_cmd(),
1801+
);
1802+
}
1803+
1804+
if ui.button("Copy timestamp").clicked() {
1805+
let time = format!("{}", hovered_time.floor().as_i64());
1806+
re_log::info!("Copied hovered timestamp: {}", time);
17931807
ui.ctx().copy_text(time);
17941808
}
1809+
}
17951810

1796-
if ui.button("Copy current timeline name").clicked() {
1797-
let timeline = format!("{}", time_ctrl.timeline().name());
1798-
re_log::info!("Copied current timeline: {}", timeline);
1799-
ui.ctx().copy_text(timeline);
1811+
fn copy_time_properties_context_menu(ui: &mut egui::Ui, time: TimeReal) {
1812+
if ui.button("Copy timestamp").clicked() {
1813+
let time = format!("{}", time.floor().as_i64());
1814+
re_log::info!("Copied hovered timestamp: {}", time);
1815+
ui.ctx().copy_text(time);
18001816
}
18011817
}
18021818

@@ -1805,6 +1821,7 @@ fn time_marker_ui(
18051821
time_ranges_ui: &TimeRangesUi,
18061822
time_ctrl: &mut TimeControl,
18071823
ui: &egui::Ui,
1824+
ctx: &ViewerContext<'_>,
18081825
time_area_response: Option<&egui::Response>,
18091826
time_area_painter: &egui::Painter,
18101827
timeline_rect: &Rect,
@@ -1918,8 +1935,26 @@ fn time_marker_ui(
19181935
}
19191936
}
19201937

1921-
time_area_response
1922-
.context_menu(|ui| copy_time_properties_context_menu(ui, time_ctrl, hovered_time));
1938+
let hovered_ctx_id = egui::Id::new("hovered timestamp context");
1939+
if let Some(hovered_time) = ui
1940+
.ctx()
1941+
.memory(|mem| mem.data.get_temp(hovered_ctx_id))
1942+
.or(hovered_time)
1943+
{
1944+
if egui::Popup::context_menu(&time_area_response)
1945+
.width(300.0)
1946+
.show(|ui| {
1947+
copy_timeline_properties_context_menu(ui, ctx, time_ctrl, hovered_time);
1948+
})
1949+
.is_some()
1950+
{
1951+
ui.ctx()
1952+
.memory_mut(|mem| mem.data.insert_temp(hovered_ctx_id, hovered_time));
1953+
} else {
1954+
ui.ctx()
1955+
.memory_mut(|mem| mem.data.remove::<TimeReal>(hovered_ctx_id));
1956+
}
1957+
}
19231958
}
19241959
}
19251960

0 commit comments

Comments
 (0)