Skip to content

Instantly share code, notes, and snippets.

@bent-rasmussen
Created November 25, 2023 09:57
Show Gist options
  • Save bent-rasmussen/b6bede7662fd520007e978a81985fdbb to your computer and use it in GitHub Desktop.
Save bent-rasmussen/b6bede7662fd520007e978a81985fdbb to your computer and use it in GitHub Desktop.
Vide todo-list sample in a LINQPad script (F#, Avalonia)
<Query Kind="FSharpProgram">
<NuGetReference>Avalonia</NuGetReference>
<NuGetReference>Avalonia.Desktop</NuGetReference>
<NuGetReference>Avalonia.Themes.Fluent</NuGetReference>
<NuGetReference>Vide.UI.Avalonia</NuGetReference>
<Namespace>Avalonia</Namespace>
<Namespace>Vide</Namespace>
<Namespace>Vide.UI.Avalonia</Namespace>
</Query>
// Source: https://github.com/vide-collabo/Vide/blob/main/Vide.UI/Vide.UI.Avalonia/src/DevApp/
module UseCases_TodoList =
open System
open Vide
open Vide.UI.Avalonia
open type Vide.UI.Avalonia.Controls
open type Vide.UI.Avalonia.AvaloniaControlsDefaults
type TodoList = { items: TodoItem list }
and TodoItem = { name: string; mutable isDone: bool; key: int }
let view = vide {
let! todoList = ofMutable {
{
items = [
{ name = "Write Vide docu"; isDone = false; key = 0 }
{ name = "Cook new ramen broth"; isDone = false; key = 1 }
{ name = "Stuff that's already done"; isDone = true; key = 2 }
{ name = "Auto-gen Vide Avalonia API"; isDone = false; key = 3 }
{ name = "Wrap this list in ScrollViewer"; isDone = false; key = 4 }
]
}
}
let setItems items = todoList.Value <- { todoList.Value with items = items }
DockPanel.Margin(4) {
H1
.HorizontalAlignment(HA.Center)
.DockPanel().Dock(Dock.Top)
.Text("My TODO List")
DockPanel
.Margin(4)
.DockPanel().Dock(Dock.Bottom) {
let! itemName = ofMutable { "" }
Button
.DockPanel().Dock(Dock.Right)
.Margin(0)
.IsEnabled(String.IsNullOrWhiteSpace(itemName.Value) |> not)
.onInit(fun x -> x.node.IsDefault <- true)
.Click(fun _ ->
let nextId =
match todoList.Value.items |> List.map (fun x -> x.key) |> List.sortDescending with
| [] -> 0
| x::_ -> x + 1
let newItem = { name = itemName.Value; isDone = false; key = nextId }
do setItems (newItem :: todoList.Value.items)
do itemName.Reset()) {
"Add Item"
}
TextBox.BindText(itemName)
}
VStack.Margin(4) {
for item in todoList.Value.items do
DockPanel {
Button
.IsEnabled(item.isDone)
.DockPanel().Dock(Dock.Right)
.Click(fun _ -> setItems (todoList.Value.items |> List.except [item]))
{ "Remove" }
CheckBox
.BindIsChecked(item.isDone, fun value -> item.isDone <- value)
TextBlock
.VerticalAlignment(VA.Center)
.TextTrimming(TextTrimming.CharacterEllipsis)
.Text(item.name)
}
}
}
}
open Avalonia
open Avalonia.Controls.ApplicationLifetimes
open Avalonia.Controls
open Avalonia.Themes.Fluent
open Vide
open Vide.UI.Avalonia
module FormFactor =
let mobile = 390.0, 644.0
let desktop = 1200.0, 700.0
type App() =
inherit Application()
//let demo = UseCases.GettingStarted.counter, FormFactor.desktop
let demo = UseCases_TodoList.view, FormFactor.mobile
//let demo = UseCases.EvalDebugger.view, FormFactor.mobile
override this.Initialize() =
this.Styles.Add(FluentTheme())
this.RequestedThemeVariant <- Styling.ThemeVariant.Dark
override this.OnFrameworkInitializationCompleted() =
match this.ApplicationLifetime with
| :? IClassicDesktopStyleApplicationLifetime as desktopLifetime ->
desktopLifetime.MainWindow <-
let host = ContentControl()
let window = Window(
Background = Media.Brushes.DarkSlateBlue,
Content = host,
Width = fst (snd demo),
Height = snd (snd demo),
WindowStartupLocation = WindowStartupLocation.CenterOwner
)
let app = VideApp.ForHost(host).CreateAndStart(fst demo)
window
| _ -> failwith "Unexpected ApplicationLifetime"
AppBuilder
.Configure<App>()
.UsePlatformDetect()
.UseSkia()
.StartWithClassicDesktopLifetime([||])
|> ignore
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment