@@ -24,78 +24,86 @@ struct BreadcrumbsComponent: View {
2424 @State
2525 var position : NSPoint ?
2626
27+ @State
28+ var selection : WorkspaceClient . FileItem
29+
2730 init (
2831 fileItem: WorkspaceClient . FileItem ,
2932 tappedOpenFile: @escaping ( WorkspaceClient . FileItem ) -> Void
3033 ) {
3134 self . fileItem = fileItem
35+ self . _selection = . init( wrappedValue: fileItem)
3236 self . tappedOpenFile = tappedOpenFile
3337 }
3438
35- private var image : String {
36- fileItem. parent == nil ? " square.dashed.inset.filled " : fileItem. systemImage
39+ var siblings : [ WorkspaceClient . FileItem ] {
40+ if let siblings = fileItem. parent? . children? . sortItems ( foldersOnTop: true ) , !siblings. isEmpty {
41+ return siblings
42+ } else {
43+ return [ fileItem]
44+ }
3745 }
3846
39- /// If current `fileItem` has no parent, it's the workspace root directory
40- /// else if current `fileItem` has no children, it's the opened file
41- /// else it's a folder
42- private var color : Color {
43- fileItem. parent == nil
44- ? . accentColor
45- : (
46- fileItem. isFolder
47- ? Color ( hex: colorScheme == . dark ? " #61b6df " : " #27b9ff " )
48- : fileItem. iconColor
49- )
47+ var body : some View {
48+ NSPopUpButtonView ( selection: $selection) {
49+ let button = NSPopUpButton ( )
50+ button. menu = BreadcrumsMenu ( fileItems: siblings, tappedOpenFile: tappedOpenFile)
51+ button. font = . systemFont( ofSize: NSFont . systemFontSize ( for: . small) )
52+ button. isBordered = false
53+ ( button. cell as? NSPopUpButtonCell ) ? . arrowPosition = . noArrow
54+ return button
55+ }
56+ . padding ( . leading, - 5 )
5057 }
5158
52- var body : some View {
53- HStack ( alignment: . center, spacing: 5 ) {
54- Image ( systemName: image)
55- . resizable ( )
56- . aspectRatio ( contentMode: . fit)
57- . frame ( width: 12 )
58- . foregroundStyle (
59- prefs. preferences. general. fileIconStyle == . color
60- ? color
61- : . secondary
62- )
63- . opacity ( activeState != . inactive ? 1.0 : 0.4 )
64- Text ( fileItem. fileName)
65- . foregroundStyle ( . primary)
66- . font ( . system( size: 11 ) )
67- . opacity ( activeState != . inactive ? 1.0 : 0.2 )
59+ struct NSPopUpButtonView < ItemType> : NSViewRepresentable where ItemType: Equatable {
60+ @Binding var selection : ItemType
61+ var popupCreator : ( ) -> NSPopUpButton
62+
63+ typealias NSViewType = NSPopUpButton
64+
65+ func makeNSView( context: NSViewRepresentableContext < NSPopUpButtonView > ) -> NSPopUpButton {
66+ let newPopupButton = popupCreator ( )
67+ setPopUpFromSelection ( newPopupButton, selection: selection)
68+ return newPopupButton
6869 }
69- /// Get location in window
70- . background ( GeometryReader { ( proxy : GeometryProxy ) -> Color in
71- if position != NSPoint (
72- x : proxy . frame ( in : . global ) . minX ,
73- y : proxy . frame ( in : . global ) . midY
74- ) {
75- DispatchQueue . main . async {
76- position = NSPoint (
77- x : proxy . frame ( in : . global ) . minX ,
78- y : proxy . frame ( in : . global ) . midY
79- )
80- }
70+
71+ func updateNSView ( _ nsView : NSPopUpButton , context : NSViewRepresentableContext < NSPopUpButtonView > ) {
72+ setPopUpFromSelection ( nsView , selection : selection )
73+ }
74+
75+ func setPopUpFromSelection ( _ button : NSPopUpButton , selection : ItemType ) {
76+ let itemsList = button . itemArray
77+ let matchedMenuItem = itemsList . filter {
78+ ( $0 . representedObject as? ItemType ) == selection
79+ } . first
80+ if matchedMenuItem != nil {
81+ button . select ( matchedMenuItem )
8182 }
82- return Color . clear
83- } )
84- . onTapGesture {
85- if let siblings = fileItem. parent? . children? . sortItems ( foldersOnTop: true ) , !siblings. isEmpty {
86- let menu = BreadcrumsMenu (
87- fileItems: siblings
88- ) { item in
89- tappedOpenFile ( item)
90- }
91- if let position = position,
92- let windowHeight = NSApp . keyWindow? . contentView? . frame. height {
93- let pos = NSPoint ( x: position. x, y: windowHeight - 72 ) // 72 = offset from top to breadcrumbs bar
94- menu. popUp (
95- positioning: menu. item ( withTitle: fileItem. fileName) ,
96- at: pos,
97- in: NSApp . keyWindow? . contentView
98- )
83+ }
84+
85+ func makeCoordinator( ) -> Coordinator {
86+ return Coordinator ( self )
87+ }
88+
89+ class Coordinator : NSObject {
90+ var parent : NSPopUpButtonView !
91+
92+ init ( _ parent: NSPopUpButtonView ) {
93+ super. init ( )
94+ self . parent = parent
95+ NotificationCenter . default. addObserver (
96+ self ,
97+ selector: #selector( dropdownItemSelected) ,
98+ name: NSMenu . didSendActionNotification,
99+ object: nil
100+ )
101+ }
102+
103+ @objc func dropdownItemSelected( _ notification: NSNotification ) {
104+ let menuItem = ( notification. userInfo ? [ " MenuItem " ] ) ! as? NSMenuItem
105+ if let selection = menuItem? . representedObject as? ItemType {
106+ parent. selection = selection
99107 }
100108 }
101109 }
0 commit comments