@@ -18,6 +18,7 @@ use re_types::reflection::ComponentDescriptorExt as _;
18
18
use re_types_core:: ComponentDescriptor ;
19
19
use re_ui:: { ContextExt as _, DesignTokens , Help , UiExt as _, filter_widget, icons, list_item} ;
20
20
use re_ui:: { IconText , filter_widget:: format_matching_text} ;
21
+ use re_viewer_context:: open_url:: ViewerOpenUrl ;
21
22
use re_viewer_context:: {
22
23
CollapseScope , HoverHighlight , Item , ItemCollection , ItemContext , RecordingConfig ,
23
24
SystemCommand , SystemCommandSender as _, TimeControl , TimeView , UiLayout , ViewerContext ,
@@ -567,6 +568,7 @@ impl TimePanel {
567
568
& self . time_ranges_ui ,
568
569
time_ctrl,
569
570
ui,
571
+ ctx,
570
572
Some ( & time_area_response) ,
571
573
& time_area_painter,
572
574
& timeline_rect,
@@ -1388,6 +1390,7 @@ impl TimePanel {
1388
1390
& time_ranges_ui,
1389
1391
time_ctrl,
1390
1392
ui,
1393
+ ctx,
1391
1394
None ,
1392
1395
& painter,
1393
1396
& time_range_rect,
@@ -1404,7 +1407,9 @@ impl TimePanel {
1404
1407
ui : & mut egui:: Ui ,
1405
1408
time_ctrl : & mut TimeControl ,
1406
1409
) {
1407
- if let Some ( time_int) = time_ctrl. time_int ( ) {
1410
+ if let Some ( time_int) = time_ctrl. time_int ( )
1411
+ && let Some ( time) = time_ctrl. time ( )
1412
+ {
1408
1413
let time_type = time_ctrl. time_type ( ) ;
1409
1414
1410
1415
let mut time_str = self
@@ -1426,11 +1431,11 @@ impl TimePanel {
1426
1431
}
1427
1432
self . time_edit_string = None ;
1428
1433
}
1429
- response
1430
- . on_hover_text ( format ! ( "Timestamp: {}" , time_int . as_i64 ( ) ) )
1431
- . context_menu ( |ui| {
1432
- copy_time_properties_context_menu ( ui, time_ctrl , None ) ;
1433
- } ) ;
1434
+ let response = response . on_hover_text ( format ! ( "Timestamp: {}" , time_int . as_i64 ( ) ) ) ;
1435
+
1436
+ response . context_menu ( |ui| {
1437
+ copy_time_properties_context_menu ( ui, time ) ;
1438
+ } ) ;
1434
1439
}
1435
1440
}
1436
1441
}
@@ -1776,29 +1781,79 @@ fn interact_with_streams_rect(
1776
1781
}
1777
1782
1778
1783
/// Context menu that shows up when interacting with the streams rect.
1779
- fn copy_time_properties_context_menu (
1784
+ fn copy_timeline_properties_context_menu (
1780
1785
ui : & mut egui:: Ui ,
1786
+ ctx : & ViewerContext < ' _ > ,
1781
1787
time_ctrl : & TimeControl ,
1782
- hovered_time : Option < TimeReal > ,
1788
+ hovered_time : TimeReal ,
1783
1789
) {
1784
- if let Some ( time) = hovered_time {
1785
- if ui. button ( "Copy hovered timestamp" ) . clicked ( ) {
1786
- let time = format ! ( "{}" , time. floor( ) . as_i64( ) ) ;
1787
- re_log:: info!( "Copied hovered timestamp: {}" , time) ;
1788
- ui. ctx ( ) . copy_text ( time) ;
1789
- }
1790
- } else if let Some ( time) = time_ctrl. time_int ( )
1791
- && ui. button ( "Copy current timestamp" ) . clicked ( )
1790
+ let mut url = ViewerOpenUrl :: from_context ( ctx) ;
1791
+ if let Some ( selected_time_range) = time_ctrl. active_loop_selection ( )
1792
+ && selected_time_range. contains ( hovered_time)
1792
1793
{
1793
- let time = format ! ( "{}" , time. as_i64( ) ) ;
1794
- re_log:: info!( "Copied current timestamp: {}" , time) ;
1794
+ let has_time_range = url. as_mut ( ) . is_ok_and ( |url| url. fragment_mut ( ) . is_some ( ) ) ;
1795
+ let copy_command = url. and_then ( |url| url. copy_url_command ( ) ) ;
1796
+ if ui
1797
+ . add_enabled (
1798
+ copy_command. is_ok ( ) && has_time_range,
1799
+ egui:: Button :: new ( "Copy link to trimmed range" ) ,
1800
+ )
1801
+ . on_disabled_hover_text ( if copy_command. is_err ( ) {
1802
+ "Can't share links to the current recording"
1803
+ } else {
1804
+ "The current recording doesn't support time range links"
1805
+ } )
1806
+ . clicked ( )
1807
+ && let Ok ( copy_command) = copy_command
1808
+ {
1809
+ ctx. command_sender ( ) . send_system ( copy_command) ;
1810
+ }
1811
+ } else {
1812
+ let has_fragment = url. as_mut ( ) . is_ok_and ( |url| {
1813
+ if let Some ( fragment) = url. fragment_mut ( ) {
1814
+ fragment. when = Some ( (
1815
+ * time_ctrl. timeline ( ) . name ( ) ,
1816
+ re_log_types:: TimeCell {
1817
+ typ : time_ctrl. time_type ( ) ,
1818
+ value : hovered_time. floor ( ) . into ( ) ,
1819
+ } ,
1820
+ ) ) ;
1821
+ true
1822
+ } else {
1823
+ false
1824
+ }
1825
+ } ) ;
1826
+ let copy_command = url. and_then ( |url| url. copy_url_command ( ) ) ;
1827
+
1828
+ if ui
1829
+ . add_enabled (
1830
+ copy_command. is_ok ( ) && has_fragment,
1831
+ egui:: Button :: new ( "Copy link to timestamp" ) ,
1832
+ )
1833
+ . on_disabled_hover_text ( if copy_command. is_err ( ) {
1834
+ "Can't share links to the current recording"
1835
+ } else {
1836
+ "The current recording doesn't support time stamp links"
1837
+ } )
1838
+ . clicked ( )
1839
+ && let Ok ( copy_command) = copy_command
1840
+ {
1841
+ ctx. command_sender ( ) . send_system ( copy_command) ;
1842
+ }
1843
+ }
1844
+
1845
+ if ui. button ( "Copy timestamp" ) . clicked ( ) {
1846
+ let time = format ! ( "{}" , hovered_time. floor( ) . as_i64( ) ) ;
1847
+ re_log:: info!( "Copied hovered timestamp: {}" , time) ;
1795
1848
ui. ctx ( ) . copy_text ( time) ;
1796
1849
}
1850
+ }
1797
1851
1798
- if ui. button ( "Copy current timeline name" ) . clicked ( ) {
1799
- let timeline = format ! ( "{}" , time_ctrl. timeline( ) . name( ) ) ;
1800
- re_log:: info!( "Copied current timeline: {}" , timeline) ;
1801
- ui. ctx ( ) . copy_text ( timeline) ;
1852
+ fn copy_time_properties_context_menu ( ui : & mut egui:: Ui , time : TimeReal ) {
1853
+ if ui. button ( "Copy timestamp" ) . clicked ( ) {
1854
+ let time = format ! ( "{}" , time. floor( ) . as_i64( ) ) ;
1855
+ re_log:: info!( "Copied hovered timestamp: {}" , time) ;
1856
+ ui. ctx ( ) . copy_text ( time) ;
1802
1857
}
1803
1858
}
1804
1859
@@ -1807,6 +1862,7 @@ fn time_marker_ui(
1807
1862
time_ranges_ui : & TimeRangesUi ,
1808
1863
time_ctrl : & mut TimeControl ,
1809
1864
ui : & egui:: Ui ,
1865
+ ctx : & ViewerContext < ' _ > ,
1810
1866
time_area_response : Option < & egui:: Response > ,
1811
1867
time_area_painter : & egui:: Painter ,
1812
1868
timeline_rect : & Rect ,
@@ -1869,19 +1925,38 @@ fn time_marker_ui(
1869
1925
let is_pointer_in_timeline_rect =
1870
1926
ui. ui_contains_pointer ( ) && timeline_rect. contains ( pointer_pos) ;
1871
1927
1872
- // Show preview?
1873
- if !is_hovering_time_cursor
1928
+ let hovered_ctx_id = egui:: Id :: new ( "hovered timestamp context" ) ;
1929
+
1930
+ let on_timeline = !is_hovering_time_cursor
1874
1931
&& !time_area_double_clicked
1875
1932
&& is_pointer_in_time_area_rect
1876
1933
&& !is_anything_being_dragged
1877
- && !is_hovering_the_loop_selection
1934
+ && !is_hovering_the_loop_selection;
1935
+
1936
+ if on_timeline {
1937
+ ui. ctx ( ) . set_cursor_icon ( timeline_cursor_icon) ;
1938
+ }
1939
+
1940
+ // Show a preview bar at this position, if we have right-clicked
1941
+ // on the time panel we want to still draw the line at the
1942
+ // original position.
1943
+ let hovered_x_pos = if let Some ( hovered_time) =
1944
+ ui. ctx ( ) . memory ( |mem| mem. data . get_temp ( hovered_ctx_id) )
1945
+ && let Some ( x) = time_ranges_ui. x_from_time_f32 ( hovered_time)
1878
1946
{
1947
+ Some ( x)
1948
+ } else if on_timeline {
1949
+ Some ( pointer_pos. x )
1950
+ } else {
1951
+ None
1952
+ } ;
1953
+
1954
+ if let Some ( x) = hovered_x_pos {
1879
1955
time_area_painter. vline (
1880
- pointer_pos . x ,
1956
+ x,
1881
1957
timeline_rect. top ( ) ..=ui. max_rect ( ) . bottom ( ) ,
1882
1958
ui. visuals ( ) . widgets . noninteractive . fg_stroke ,
1883
1959
) ;
1884
- ui. ctx ( ) . set_cursor_icon ( timeline_cursor_icon) ; // preview!
1885
1960
}
1886
1961
1887
1962
// Click to move time here:
@@ -1920,8 +1995,25 @@ fn time_marker_ui(
1920
1995
}
1921
1996
}
1922
1997
1923
- time_area_response
1924
- . context_menu ( |ui| copy_time_properties_context_menu ( ui, time_ctrl, hovered_time) ) ;
1998
+ if let Some ( hovered_time) = ui
1999
+ . ctx ( )
2000
+ . memory ( |mem| mem. data . get_temp ( hovered_ctx_id) )
2001
+ . or ( hovered_time)
2002
+ {
2003
+ if egui:: Popup :: context_menu ( & time_area_response)
2004
+ . width ( 300.0 )
2005
+ . show ( |ui| {
2006
+ copy_timeline_properties_context_menu ( ui, ctx, time_ctrl, hovered_time) ;
2007
+ } )
2008
+ . is_some ( )
2009
+ {
2010
+ ui. ctx ( )
2011
+ . memory_mut ( |mem| mem. data . insert_temp ( hovered_ctx_id, hovered_time) ) ;
2012
+ } else {
2013
+ ui. ctx ( )
2014
+ . memory_mut ( |mem| mem. data . remove :: < TimeReal > ( hovered_ctx_id) ) ;
2015
+ }
2016
+ }
1925
2017
}
1926
2018
}
1927
2019
0 commit comments