@@ -25,6 +25,11 @@ struct EditorJumpBarView: View {
2525
2626 static let height = 28.0
2727
28+ @State private var textWidth : CGFloat = 0
29+ @State private var containerWidth : CGFloat = 0
30+ @State private var isTruncated : Bool = false
31+ @State private var crumbWidth : CGFloat ? = nil
32+
2833 init (
2934 file: CEWorkspaceFile ? ,
3035 shouldShowTabBar: Bool ,
@@ -50,24 +55,59 @@ struct EditorJumpBarView: View {
5055 }
5156
5257 var body : some View {
53- ScrollView ( . horizontal, showsIndicators: false ) {
54- HStack ( spacing: 0 ) {
55- if file == nil {
56- Text ( " No Selection " )
57- . font ( . system( size: 11 , weight: . regular) )
58- . foregroundColor (
59- activeState != . inactive
60- ? isActiveEditor ? . primary : . secondary
61- : Color ( nsColor: . tertiaryLabelColor)
62- )
63- } else {
64- ForEach ( fileItems, id: \. self) { fileItem in
65- EditorJumpBarComponent (
66- fileItem: fileItem,
67- tappedOpenFile: tappedOpenFile,
68- isLastItem: fileItems. last == fileItem
69- )
58+ GeometryReader { containerProxy in
59+ ScrollView ( . horizontal, showsIndicators: false ) {
60+ HStack ( spacing: 0 ) {
61+ if file == nil {
62+ Text ( " No Selection " )
63+ . font ( . system( size: 11 , weight: . regular) )
64+ . foregroundColor (
65+ activeState != . inactive
66+ ? isActiveEditor ? . primary : . secondary
67+ : Color ( nsColor: . tertiaryLabelColor)
68+ )
69+ } else {
70+ ForEach ( fileItems, id: \. self) { fileItem in
71+ EditorJumpBarComponent (
72+ fileItem: fileItem,
73+ tappedOpenFile: tappedOpenFile,
74+ isLastItem: fileItems. last == fileItem,
75+ isTruncated: $crumbWidth
76+ )
77+ }
78+
79+ }
80+ }
81+ . background (
82+ GeometryReader { proxy in
83+ Color . clear
84+ . onAppear {
85+ if crumbWidth == nil {
86+ textWidth = proxy. size. width
87+ }
88+ }
89+ . onChange ( of: proxy. size. width) { newValue in
90+ if crumbWidth == nil {
91+ textWidth = newValue
92+ }
93+ }
7094 }
95+ )
96+ }
97+ . onAppear {
98+ containerWidth = containerProxy. size. width
99+ }
100+ . onChange ( of: containerProxy. size. width) { newValue in
101+ containerWidth = newValue
102+ }
103+ . onChange ( of: textWidth) { _ in
104+ withAnimation ( . easeInOut( duration: 0.2 ) ) {
105+ resize ( )
106+ }
107+ }
108+ . onChange ( of: containerWidth) { _ in
109+ withAnimation ( . easeInOut( duration: 0.2 ) ) {
110+ resize ( )
71111 }
72112 }
73113 }
@@ -86,4 +126,22 @@ struct EditorJumpBarView: View {
86126 . opacity ( activeState == . inactive ? 0.8 : 1.0 )
87127 . grayscale ( isActiveEditor ? 0.0 : 1.0 )
88128 }
129+
130+ private func resize( ) {
131+ let minWidth : CGFloat = 20
132+ let snapThreshold : CGFloat = 30
133+ let maxWidth : CGFloat = textWidth / CGFloat( fileItems. count)
134+ let exponent : CGFloat = 5.0
135+
136+ if textWidth >= containerWidth {
137+ let scale = max ( 0 , min ( 1 , containerWidth / textWidth) )
138+ var width = floor ( ( minWidth + ( maxWidth - minWidth) * pow( scale, exponent) ) )
139+ if width < snapThreshold {
140+ width = minWidth
141+ }
142+ crumbWidth = width
143+ } else {
144+ crumbWidth = nil
145+ }
146+ }
89147}
0 commit comments