78 lines
2.6 KiB
Swift
78 lines
2.6 KiB
Swift
//
|
|
// 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<Bool>, @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>(
|
|
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<Data>(
|
|
_ 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
|
|
}
|
|
}
|
|
|
|
}
|