Skip to content

Instantly share code, notes, and snippets.

@smolck
Created May 30, 2020 15:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save smolck/90dd6505f5a10bad174bace4dff0c27a to your computer and use it in GitHub Desktop.
Save smolck/90dd6505f5a10bad174bace4dff0c27a to your computer and use it in GitHub Desktop.
Attempt at using FsHotReloading with Avalonia.FuncUI
namespace Dotnet
module Counter =
open Avalonia.Controls
open Avalonia.FuncUI.DSL
open Avalonia.Layout
type Msg =
| Increment
| Decrement
| Reset
type State =
{ Count: int }
let init = { Count = 0 }
let update (msg: Msg) (state: State): State =
match msg with
| Increment -> { state with Count = state.Count + 1 }
| Decrement -> { state with Count = state.Count - 1 }
| Reset -> init
let view (state: State) (dispatch) =
(ViewRegistry.register
(DockPanel.create
[ DockPanel.children
[ Button.create
[ Button.dock Dock.Bottom
Button.onClick (fun _ -> dispatch Reset)
Button.content "reset" ]
Button.create
[ Button.dock Dock.Bottom
Button.onClick (fun _ -> dispatch Decrement)
Button.content "-" ]
Button.create
[ Button.dock Dock.Bottom
Button.onClick (fun _ -> dispatch Increment)
Button.content "+" ]
TextBlock.create
[ TextBlock.dock Dock.Top
TextBlock.fontSize 100.0
TextBlock.verticalAlignment VerticalAlignment.Center
TextBlock.horizontalAlignment HorizontalAlignment.Center
TextBlock.text (string state.Count) ] ] ])) ()
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<Compile Include="ViewRegistry.fs" />
<Compile Include="Counter.fs" />
<Compile Include="Program.fs" />
</ItemGroup>
<ItemGroup />
<ItemGroup>
<PackageReference Include="Avalonia.Desktop" Version="0.9.7" />
<PackageReference Include="JaggerJo.Avalonia.FuncUI" Version="0.4.0" />
<PackageReference Include="JaggerJo.Avalonia.FuncUI.DSL" Version="0.4.0" />
<PackageReference Include="JaggerJo.Avalonia.FuncUI.Elmish" Version="0.4.0" />
<!-- Need to git clone the FsHotReloading repo and provide path to its fsproj here -->
<ProjectReference Include="../FsHotReloading/FsHotReloading/FsHotReloading.fsproj" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Remove=".template.config\**" />
</ItemGroup>
</Project>
namespace Dotnet
open Elmish
open Avalonia
open Avalonia.Controls.ApplicationLifetimes
open Avalonia.Input
open Avalonia.FuncUI
open Avalonia.FuncUI.Elmish
open Avalonia.FuncUI.Components.Hosts
open FsHotReloading
type MainWindow() as this =
inherit HostWindow()
do
base.Title <- "dotnet"
base.Width <- 400.0
base.Height <- 400.0
//this.VisualRoot.VisualRoot.Renderer.DrawFps <- true
//this.VisualRoot.VisualRoot.Renderer.DrawDirtyRects <- true
let obs (state: Counter.State) =
let sub (dispatch: Counter.Msg -> unit) =
// When you modify the Counter.fs file, this will run
ViewRegistry.onChange.Subscribe(fun _ -> printfn "File Changed!")
|> ignore
Cmd.ofSub sub
Elmish.Program.mkSimple (fun () -> Counter.init) Counter.update Counter.view
|> Program.withSubscription obs
|> Program.withHost this
|> Program.run
type App() =
inherit Application()
override this.Initialize() =
this.Styles.Load "avares://Avalonia.Themes.Default/DefaultTheme.xaml"
this.Styles.Load "avares://Avalonia.Themes.Default/Accents/BaseDark.xaml"
override this.OnFrameworkInitializationCompleted() =
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktopLifetime -> desktopLifetime.MainWindow <- MainWindow()
| _ -> ()
module Program =
[<EntryPoint>]
let main (args: string []) =
HotReloading.enable [ ViewRegistry.registry.ops ]
AppBuilder.Configure<App>().UsePlatformDetect().UseSkia().StartWithClassicDesktopLifetime(args)
namespace Dotnet
open System.Runtime.CompilerServices
open FsHotReloading
type ViewId =
{ file: string
name: string }
module ViewRegistry =
let registry, onChange =
HotReloading.createSimpleRegistry "HotReloadableViews" (fun id -> id.file)
type ViewRegistry =
static member register(value: Avalonia.FuncUI.Types.IView, [<CallerMemberName>] ?name: string,
[<CallerFilePath>] ?file: string) =
let id =
{ file = file.Value
name = name.Value }
let getter =
fun () -> ViewRegistry.registry.tryGet id |> Option.get
ViewRegistry.registry.register id value getter
getter
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment