fsprojects / Avalonia.FuncUI

Develop cross-plattform GUI Applications using F# and Avalonia!
https://funcui.avaloniaui.net/
MIT License
955 stars 74 forks source link

App.axaml replacement #427

Open CoolCoderSuper opened 3 months ago

CoolCoderSuper commented 3 months ago

Currently you can't define styles or resources in app using the DSL which isn't that big of a deal since it is pretty easy to add manually. However it is more annoying when I want to have a TrayIcon.

<TrayIcon.Icons>
    <TrayIcons>
        <TrayIcon Icon="Assets/icon.ico">
            <TrayIcon.Menu>
                <NativeMenu>
                    <NativeMenuItem Header="Settings"/>
                    <NativeMenuItem Header="Start"/>
                    <NativeMenuItem Header="Stop"/>
                    <NativeMenuItem Header="Import"/>
                    <NativeMenuItem Header="Exit"/>
                </NativeMenu>
            </TrayIcon.Menu>
        </TrayIcon>
    </TrayIcons>
</TrayIcon.Icons>

It is pretty easy to use axaml when needed but I think it would be cool.

JaggerJo commented 3 months ago

Are there no bindings for TrayIcon yet?

If not we should add them. Are you willing to contribute the bindings?

CoolCoderSuper commented 3 months ago

I would be willing to try. We would also need to add bindings for NativeMenu as well. https://github.com/fsprojects/Avalonia.FuncUI/blob/master/docs/controls/nativemenu.md

I'm not sure how one would go about registering it on the window or application since the DSL creates IView which wouldn't work with NativeMenu.SetMenu or TrayIcon.SetIcon

CoolCoderSuper commented 3 months ago

If I understand correctly the Component type is a real Avalonia component that renders out the IViews. However neither NativeMenu or TrayIcon are actual Avalonia components.

JaggerJo commented 3 months ago

@CoolCoderSuper should still work as the base type is Avalonia Object.

IView is probably not the best name as all types inheriting from Avalonia Object are supported.

JaggerJo commented 3 months ago

I'm not sure how one would go about registering it on the window or application since the DSL creates IView which wouldn't work with NativeMenu.SetMenu or TrayIcon.SetIcon

If it works in XAML it should also work in the DSL without explicitly calling those methods.

CoolCoderSuper commented 3 months ago

OK that makes sense. The xaml compiler generates calls to those methods for it to work.

JaggerJo commented 3 months ago

Hah, ok. We could add 'register' calls that internally use init functions...

But thats kind of a workaround. If the XAML compiler does special things we.. also would have to.

CoolCoderSuper commented 3 months ago
    static void !XamlIlPopulate(IServiceProvider P_0, App P_1)
    {
        CompiledAvaloniaXaml.XamlIlContext.Context<App> context = new CompiledAvaloniaXaml.XamlIlContext.Context<App>(P_0, new object[1] { !AvaloniaResources.NamespaceInfo:/App.axaml.Singleton }, "avares://LantekQuoting/App.axaml");
        context.RootObject = P_1;
        context.IntermediateRoot = P_1;
        App app;
        App app2 = (app = P_1);
        context.PushParent(app);
        app.RequestedThemeVariant = ThemeVariant.Dark;
        app.Styles.Add(new FluentTheme(context));
        TrayIcons trayIcons;
        TrayIcons trayIcons2 = (trayIcons = new TrayIcons());
        context.PushParent(trayIcons);
        TrayIcon trayIcon;
        TrayIcon item = (trayIcon = new TrayIcon());
        context.PushParent(trayIcon);
        trayIcon.Icon = (WindowIcon)new IconTypeConverter().ConvertFrom(context, CultureInfo.InvariantCulture, "Assets/icon.ico");
        trayIcon.Clicked += context.RootObject.settings_OnClick;
        trayIcon.ToolTipText = "Lantek Quoting";
        NativeMenu nativeMenu = new NativeMenu();
        IList<NativeMenuItemBase> items = nativeMenu.Items;
        NativeMenuItem nativeMenuItem = new NativeMenuItem();
        nativeMenuItem.Header = "Settings";
        nativeMenuItem.Click += context.RootObject.settings_OnClick;
        items.Add(nativeMenuItem);
        IList<NativeMenuItemBase> items2 = nativeMenu.Items;
        NativeMenuItem nativeMenuItem2 = new NativeMenuItem();
        nativeMenuItem2.Header = "Start";
        nativeMenuItem2.Click += context.RootObject.start_OnClick;
        items2.Add(nativeMenuItem2);
        IList<NativeMenuItemBase> items3 = nativeMenu.Items;
        NativeMenuItem nativeMenuItem3 = new NativeMenuItem();
        nativeMenuItem3.Header = "Stop";
        nativeMenuItem3.Click += context.RootObject.stop_OnClick;
        items3.Add(nativeMenuItem3);
        IList<NativeMenuItemBase> items4 = nativeMenu.Items;
        NativeMenuItem nativeMenuItem4 = new NativeMenuItem();
        nativeMenuItem4.Header = "Import";
        nativeMenuItem4.Click += context.RootObject.import_OnClick;
        items4.Add(nativeMenuItem4);
        IList<NativeMenuItemBase> items5 = nativeMenu.Items;
        NativeMenuItem nativeMenuItem5 = new NativeMenuItem();
        nativeMenuItem5.Header = "Exit";
        nativeMenuItem5.Click += context.RootObject.exit_OnClick;
        items5.Add(nativeMenuItem5);
        trayIcon.Menu = nativeMenu;
        context.PopParent();
        trayIcons.Add(item);
        context.PopParent();
        TrayIcon.SetIcons(app, trayIcons2);
        context.PopParent();
        if (app2 is StyledElement styled)
        {
            NameScope.SetNameScope(styled, context.AvaloniaNameScope);
        }
        context.AvaloniaNameScope.Complete();
    }

This is the compiled result of the supplied xaml if it is at all helpful.

JaggerJo commented 2 months ago

@CoolCoderSuper did you try writing bindings for TrayIcon, ... ?

CoolCoderSuper commented 2 months ago

I did try and this now works:

    let menu = NativeMenu.create [
        NativeMenu.items [
            NativeMenuItem.create [
                NativeMenuItem.header "File"
                NativeMenuItem.isChecked true
                NativeMenuItem.isEnabled false
            ]
        ]
    ]

But I'm not sure what the next steps to register it on the window are I will fork and push my changes to GitHub later today.

CoolCoderSuper commented 2 months ago

https://github.com/CoolCoderSuper/Avalonia.FuncUI/tree/native_menu Here are my changes