@@ -22,7 +22,7 @@ use crate::{
2222 Action , InternalEvent , NeedsUpdate , Queue , StackablePopupOpen ,
2323 } ,
2424 setup_popups,
25- strings:: { self , order} ,
25+ strings:: { self , ellipsis_trim_start , order} ,
2626 tabs:: { FilesTab , Revlog , StashList , Stashing , Status } ,
2727 ui:: style:: { SharedTheme , Theme } ,
2828 AsyncAppNotification , AsyncNotification ,
@@ -41,11 +41,14 @@ use std::{
4141} ;
4242use tui:: {
4343 backend:: Backend ,
44- layout:: { Constraint , Direction , Layout , Margin , Rect } ,
44+ layout:: {
45+ Alignment , Constraint , Direction , Layout , Margin , Rect ,
46+ } ,
4547 text:: { Span , Spans } ,
46- widgets:: { Block , Borders , Tabs } ,
48+ widgets:: { Block , Borders , Paragraph , Tabs } ,
4749 Frame ,
4850} ;
51+ use unicode_width:: UnicodeWidthStr ;
4952
5053#[ derive( Clone ) ]
5154pub enum QuitState {
@@ -94,6 +97,7 @@ pub struct App {
9497 input : Input ,
9598 popup_stack : PopupStack ,
9699 options : SharedOptions ,
100+ repo_path_text : String ,
97101
98102 // "Flags"
99103 requires_redraw : Cell < bool > ,
@@ -114,6 +118,9 @@ impl App {
114118 ) -> Result < Self > {
115119 log:: trace!( "open repo at: {:?}" , & repo) ;
116120
121+ let repo_path_text =
122+ repo_work_dir ( & repo. borrow ( ) ) . unwrap_or_default ( ) ;
123+
117124 let queue = Queue :: new ( ) ;
118125 let theme = Rc :: new ( theme) ;
119126 let key_config = Rc :: new ( key_config) ;
@@ -311,6 +318,7 @@ impl App {
311318 requires_redraw : Cell :: new ( false ) ,
312319 file_to_open : None ,
313320 repo,
321+ repo_path_text,
314322 popup_stack : PopupStack :: default ( ) ,
315323 } ;
316324
@@ -339,7 +347,7 @@ impl App {
339347
340348 self . cmdbar . borrow ( ) . draw ( f, chunks_main[ 2 ] ) ;
341349
342- self . draw_tabs ( f, chunks_main[ 0 ] ) ;
350+ self . draw_top_bar ( f, chunks_main[ 0 ] ) ;
343351
344352 //TODO: component property + a macro `fullscreen_popup_open!`
345353 // to make this scale better?
@@ -1104,23 +1112,47 @@ impl App {
11041112 }
11051113
11061114 //TODO: make this dynamic
1107- fn draw_tabs < B : Backend > ( & self , f : & mut Frame < B > , r : Rect ) {
1115+ fn draw_top_bar < B : Backend > ( & self , f : & mut Frame < B > , r : Rect ) {
1116+ const DIVIDER_PAD_SPACES : usize = 2 ;
1117+ const SIDE_PADS : usize = 2 ;
1118+ const MARGIN_LEFT_AND_RIGHT : usize = 2 ;
1119+
11081120 let r = r. inner ( & Margin {
11091121 vertical : 0 ,
11101122 horizontal : 1 ,
11111123 } ) ;
11121124
1113- let tabs = [
1125+ let tab_labels = [
11141126 Span :: raw ( strings:: tab_status ( & self . key_config ) ) ,
11151127 Span :: raw ( strings:: tab_log ( & self . key_config ) ) ,
11161128 Span :: raw ( strings:: tab_files ( & self . key_config ) ) ,
11171129 Span :: raw ( strings:: tab_stashing ( & self . key_config ) ) ,
11181130 Span :: raw ( strings:: tab_stashes ( & self . key_config ) ) ,
1119- ]
1120- . iter ( )
1121- . cloned ( )
1122- . map ( Spans :: from)
1123- . collect ( ) ;
1131+ ] ;
1132+ let divider = strings:: tab_divider ( & self . key_config ) ;
1133+
1134+ // heuristic, since tui doesn't provide a way to know
1135+ // how much space is needed to draw a `Tabs`
1136+ let tabs_len: usize =
1137+ tab_labels. iter ( ) . map ( Span :: width) . sum :: < usize > ( )
1138+ + tab_labels. len ( ) . saturating_sub ( 1 )
1139+ * ( divider. width ( ) + DIVIDER_PAD_SPACES )
1140+ + SIDE_PADS + MARGIN_LEFT_AND_RIGHT ;
1141+
1142+ let left_right = Layout :: default ( )
1143+ . direction ( Direction :: Horizontal )
1144+ . constraints ( vec ! [
1145+ Constraint :: Length (
1146+ u16 :: try_from( tabs_len) . unwrap_or( r. width) ,
1147+ ) ,
1148+ Constraint :: Min ( 0 ) ,
1149+ ] )
1150+ . split ( r) ;
1151+
1152+ let table_area = r; // use entire area to allow drawing the horizontal separator line
1153+ let text_area = left_right[ 1 ] ;
1154+
1155+ let tabs = tab_labels. into_iter ( ) . map ( Spans :: from) . collect ( ) ;
11241156
11251157 f. render_widget (
11261158 Tabs :: new ( tabs)
@@ -1131,9 +1163,21 @@ impl App {
11311163 )
11321164 . style ( self . theme . tab ( false ) )
11331165 . highlight_style ( self . theme . tab ( true ) )
1134- . divider ( strings :: tab_divider ( & self . key_config ) )
1166+ . divider ( divider )
11351167 . select ( self . tab ) ,
1136- r,
1168+ table_area,
1169+ ) ;
1170+
1171+ f. render_widget (
1172+ Paragraph :: new ( Spans :: from ( vec ! [ Span :: styled(
1173+ ellipsis_trim_start(
1174+ & self . repo_path_text,
1175+ text_area. width as usize ,
1176+ ) ,
1177+ self . theme. title( true ) ,
1178+ ) ] ) )
1179+ . alignment ( Alignment :: Right ) ,
1180+ text_area,
11371181 ) ;
11381182 }
11391183}
0 commit comments