// // MenuWrapper.swift // MacBackend // // Created by david-swift on 06.12.2024. // import AppKit /// Wrap a view to add a menu. public struct MenuWrapper: MacWidget { /// Whether the menu is visible. @Binding var isPresented: Bool /// The content. var content: Body /// The menu. var menu: Body /// Initialize a menu wrapper. /// - Parameters: /// - content: The view content. /// - isPresented: Whether the menu is visible. /// - menu: The menu. public init(@ViewBuilder content: () -> Body, isPresented: Binding, @ViewBuilder menu: () -> Body) { self._isPresented = isPresented self.content = content() self.menu = menu() } /// The view storage. /// - Parameters: /// - data: The widget data. /// - type: The type of the views. /// - Returns: The view storage. public func container( data: WidgetData, type: Data.Type ) -> ViewStorage where Data: ViewRenderData { let content = content.storage(data: data, type: type) let menuPointer = NSMenu() let menu = MenuCollection { self.menu }.getMenu(data: data, menu: menuPointer) let storage = ViewStorage(content.pointer, content: [.mainContent: [content], "menu": [menu]]) storage.fields["menu"] = menuPointer update(storage, data: data, updateProperties: true, type: type) return storage } /// Update the stored content. /// - Parameters: /// - storage: The storage to update. /// - data: The widget data. /// - updateProperties: Whether to update the properties. /// - type: The type of the views. public func update( _ storage: ViewStorage, data: WidgetData, updateProperties: Bool, type: Data.Type ) where Data: ViewRenderData { if let content = storage.content[.mainContent]?.first { self.content.updateStorage(content, data: data, updateProperties: updateProperties, type: type) } if let menu = storage.content["menu"]?.first { MenuCollection { self.menu } .updateStorage(menu, data: data, updateProperties: updateProperties, type: MenuContext.self) } if isPresented, let menu = storage.fields["menu"] as? NSMenu, let content = storage.content[.mainContent]?.first?.pointer as? NSView, let currentEvent = NSApp.currentEvent { NSMenu.popUpContextMenu(menu, with: currentEvent, for: content) isPresented = false } } }