Home > other >  How do I set or disable main menu keyboard shortcut programmatically in SwiftUI for a macOS app?
How do I set or disable main menu keyboard shortcut programmatically in SwiftUI for a macOS app?

Time:12-10

Say, I want to add the following main menu item to my macOS app - Next:

@main
struct MyApp: App {

    @ObservedObject var appState = DataViewModel.shared
    
    var body: some Scene {
        
        WindowGroup
        {
                ContentView()
        }
        .commands {
            CommandGroup(replacing: .pasteboard) {
                Button(action: {
                    appState.nextCurrentID()
                }) { Text("Next")}
                    .keyboardShortcut("V", modifiers: [.command, .option, .shift])
            }
        }
   }
}

But I want to do the following depending on two variables:

  • enable/disable that menu item's keyboard shortcut depending on appState.EnableShortcutKey

  • Set the shortcut key depending on appState.ShortcutKey

  • Set modifiers depending on appState.Modifiers

Where those state variables are declared as such:

@Published public var EnableShortcutKey : Bool = false
@Published public var ShortcutKey : String = "A"
@Published public var Modifiers : NSEvent.ModifierFlags = [.command, .shift]

How do I do that?

CodePudding user response:

Like this:

@main
struct SO_mac_TestsApp: App {
    
    @StateObject var menuOptions = MenuOptions()
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(menuOptions)
        }
        .commands {
            CommandGroup(replacing: .pasteboard) {
                Button(action: {
                    print("appState.nextCurrentID()")
                }) { Text("Next")}
                    .keyboardShortcut(menuOptions.shortcutKey, modifiers: menuOptions.modifiers)
                    .disabled(menuOptions.enableShortcutKey == false)
            }
        }
    }
}


class MenuOptions: ObservableObject {
    @Published public var enableShortcutKey : Bool = false
    @Published public var shortcutKey : KeyEquivalent = "A"
    @Published public var modifiers : EventModifiers = [.command, .shift]
}


truct ContentView: View {
    
    @EnvironmentObject var menuOptions: MenuOptions
    @State private var shortcut = ""
    
    var body: some View {
        Form {
            Toggle("Enable Shortcut", isOn: $menuOptions.enableShortcutKey)
            TextField("Shortcut", text: $shortcut)
                .onSubmit {
                    menuOptions.shortcutKey = KeyEquivalent(shortcut.first ?? "V")
                }
            Divider()
            Text("Modifiers:")
            Toggle("command:", isOn: Binding(
                        get: { menuOptions.modifiers.contains(.command) },
                        set: { new,_ in
                            if new { menuOptions.modifiers.insert(.command)
                            } else { menuOptions.modifiers.subtract(.command) }
                        }
                    ) )
            Toggle("option:", isOn: Binding(
                        get: { menuOptions.modifiers.contains(.option) },
                        set: { new,_ in
                            if new { menuOptions.modifiers.insert(.option)
                            } else { menuOptions.modifiers.subtract(.option) }
                        }
                    ) )
            Toggle("shift:", isOn: Binding(
                        get: { menuOptions.modifiers.contains(.shift) },
                        set: { new,_ in
                            if new { menuOptions.modifiers.insert(.shift)
                            } else { menuOptions.modifiers.subtract(.shift) }
                        }
                    ) )
            Toggle("control:", isOn: Binding(
                        get: { menuOptions.modifiers.contains(.control) },
                        set: { new,_ in
                            if new { menuOptions.modifiers.insert(.control)
                            } else { menuOptions.modifiers.subtract(.control) }
                        }
                    ) )

        }
        .padding()
        .onAppear {
            shortcut = String(menuOptions.shortcutKey.character)
        }
    }
}
  • Related