Skip to content

Commit

Permalink
Displaying Label
Browse files Browse the repository at this point in the history
  • Loading branch information
TimLariviere committed Jul 1, 2022
1 parent b47388f commit e75371a
Show file tree
Hide file tree
Showing 12 changed files with 388 additions and 115 deletions.
6 changes: 5 additions & 1 deletion samples/Maui/CounterApp/App.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,11 @@ module App =
| Nope -> model

let view model =
Application()
Application() {
Window(
Label(model.Text)
)
}

let program =
Program.stateful init update view
4 changes: 2 additions & 2 deletions src/Fabulous.Maui/AppHostBuilderExtensions.fs
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@ open System
[<Extension>]
type AppHostBuilderExtensions =
[<Extension>]
static member UseFabulousApp<'model, 'msg, 'marker when 'marker :> Fabulous.Maui.IApplication>(this: MauiAppBuilder, program: Program<unit, 'model, 'msg, 'marker>): MauiAppBuilder =
static member UseFabulousApp<'model, 'msg, 'marker when 'marker :> IApplication>(this: MauiAppBuilder, program: Program<unit, 'model, 'msg, 'marker>): MauiAppBuilder =
this.Services.TryAddSingleton<IApplication>(fun (_serviceProvider: IServiceProvider) ->
Program.startApplication program
)
AppHostBuilderExtensions.SetupDefaults()
this

[<Extension>]
static member UseFabulousApp<'arg, 'model, 'msg, 'marker when 'marker :> Fabulous.Maui.IApplication>(this: MauiAppBuilder, program: Program<'arg, 'model, 'msg, 'marker>, arg: 'arg): MauiAppBuilder =
static member UseFabulousApp<'arg, 'model, 'msg, 'marker when 'marker :> IApplication>(this: MauiAppBuilder, program: Program<'arg, 'model, 'msg, 'marker>, arg: 'arg): MauiAppBuilder =
this.Services.TryAddSingleton<IApplication>(fun (_serviceProvider: IServiceProvider) ->
Program.startApplicationWithArgs arg program
)
Expand Down
4 changes: 3 additions & 1 deletion src/Fabulous.Maui/Fabulous.Maui.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
<ItemGroup>
<Compile Include="ViewNode.fs" />
<Compile Include="Widgets.fs" />
<Compile Include="Views\Element.fs" />
<Compile Include="Views\Window.fs" />
<Compile Include="Views\Application.fs" />
<Compile Include="Views\StackLayout.fs" />
<Compile Include="Views\Label.fs" />
<Compile Include="Program.fs" />
<Compile Include="AppHostBuilderExtensions.fs" />
</ItemGroup>
Expand Down
5 changes: 3 additions & 2 deletions src/Fabulous.Maui/Program.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
open System.Diagnostics
open Fabulous
open Fabulous.Maui
open Microsoft.Maui

module ViewHelpers =
let canReuseView (prev: Widget) (curr: Widget) =
Expand Down Expand Up @@ -67,11 +68,11 @@ module Program =
(fun msg model -> let m, c = update msg model in m, mapCmds c)
view

let startApplicationWithArgs (arg: 'arg) (program: Program<'arg, 'model, 'msg, #IApplication>) : Microsoft.Maui.IApplication =
let startApplicationWithArgs (arg: 'arg) (program: Program<'arg, 'model, 'msg, #IApplication>) : IApplication =
let runner = Runners.create program
runner.Start(arg)
let adapter = ViewAdapters.create ViewNode.get runner
adapter.CreateView() |> unbox

let startApplication (program: Program<unit, 'model, 'msg, 'marker>) : Microsoft.Maui.IApplication =
let startApplication (program: Program<unit, 'model, 'msg, 'marker>) : IApplication =
startApplicationWithArgs () program
8 changes: 7 additions & 1 deletion src/Fabulous.Maui/ViewNode.fs
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
namespace Fabulous.Maui

open System.Collections.Generic
open Fabulous
open Microsoft.Maui

type Node() =
type Node(handler: IElementHandler) =
let scalarAttributes = Dictionary<int<scalarAttributeKey>, obj>()
member val Handler = handler with get, set
member val ViewNode: IViewNode = Unchecked.defaultof<IViewNode> with get, set
member val Parent: IElement = null with get, set
member this.GetScalarValue<'T>(key: int<scalarAttributeKey>) = scalarAttributes[key] :?> 'T

module ViewNode =
let get (target: obj) = (target :?> Node).ViewNode
Expand Down
49 changes: 40 additions & 9 deletions src/Fabulous.Maui/Views/Application.fs
Original file line number Diff line number Diff line change
@@ -1,30 +1,61 @@
namespace Fabulous.Maui

open System.Collections.Generic
open System.Runtime.CompilerServices
open Fabulous
open Fabulous.StackAllocatedCollections
open Fabulous.StackAllocatedCollections.StackList
open Microsoft.Maui

type FabulousApplication() =
inherit Node()
inherit Node(Microsoft.Maui.Handlers.ApplicationHandler())

interface Microsoft.Maui.IApplication with
let _windows = List<IWindow>()
member this.Windows = _windows

interface IApplication with
member this.CloseWindow(window) = failwith "todo"
member this.CreateWindow(activationState) = failwith "todo"
member this.CreateWindow(activationState) = _windows[0]
member this.OpenWindow(window) = failwith "todo"
member this.ThemeChanged() = failwith "todo"
member this.Handler = failwith "todo"
member this.Parent = failwith "todo"
member this.Windows = failwith "todo"
member this.Handler with set value = failwith "todo"
member this.Handler
with get () = this.Handler
and set value = this.Handler <- value
member this.Parent = this.Parent
member this.Windows = _windows :> IReadOnlyList<_>

module Application =
let WidgetKey = Widgets.register<FabulousApplication>()

let Windows =
Attributes.defineListWidgetCollection
"Application_Windows"
ViewNode.get
(fun target -> (target :?> FabulousApplication).Windows)

[<AutoOpen>]
module ApplicationBuilders =
type Fabulous.Maui.View with
static member inline Application<'msg>() =
WidgetBuilder<'msg, IApplication>(
CollectionBuilder<'msg, IApplication, IWindow>(
Application.WidgetKey,
AttributesBundle(StackList.empty(), ValueNone, ValueNone)
Application.Windows
)

[<Extension>]
type ApplicationCollectionExtensions =
[<Extension>]
static member inline Yield<'msg, 'itemType when 'itemType :> IWindow>
(
_: CollectionBuilder<'msg, IApplication, IWindow>,
x: WidgetBuilder<'msg, 'itemType>
) =
{ Widgets = MutStackArray1.One(x.Compile()) } : Content<'msg>

[<Extension>]
static member inline Yield<'msg, 'itemType when 'itemType :> IWindow>
(
_: CollectionBuilder<'msg, IApplication, IWindow>,
x: WidgetBuilder<'msg, Memo.Memoized<'itemType>>
) =
{ Widgets = MutStackArray1.One(x.Compile()) } : Content<'msg>
96 changes: 0 additions & 96 deletions src/Fabulous.Maui/Views/Element.fs

This file was deleted.

122 changes: 122 additions & 0 deletions src/Fabulous.Maui/Views/Label.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
namespace Fabulous.Maui

open System.Runtime.CompilerServices
open Microsoft.Maui
open Microsoft.Maui.Graphics
open Microsoft.Maui.Handlers
open Fabulous

type FabulousLabel() =
inherit Node(LabelHandler())

let mutable _frame = Rect.Zero
let mutable _desiredSize = Size.Zero

member val Text = "" with get, set
member val TextColor = Colors.Black with get, set

interface ILabel with
member this.Arrange(bounds) =
_frame <- Microsoft.Maui.Layouts.LayoutExtensions.ComputeFrame(this, bounds)
let viewHandler = this.Handler :?> IViewHandler
if viewHandler <> null then viewHandler.PlatformArrange(_frame)
_frame.Size

member this.Focus() = failwith "todo"
member this.InvalidateArrange() = failwith "todo"
member this.InvalidateMeasure() = failwith "todo"
member this.Measure(widthConstraint, heightConstraint) =
_desiredSize <- Microsoft.Maui.Layouts.LayoutExtensions.ComputeDesiredSize(this, widthConstraint, heightConstraint)
_desiredSize

member this.Unfocus() = failwith "todo"
member this.AnchorX = 0.5
member this.AnchorY = 0.5
member this.AutomationId = null
member this.Background = SolidPaint(Colors.White)
member this.CharacterSpacing = 1.
member this.Clip = null
member this.DesiredSize = failwith "todo"
member this.FlowDirection = FlowDirection.MatchParent
member this.Font = Microsoft.Maui.Font.Default
member this.Frame = _frame
member this.Height = -1
member this.HorizontalLayoutAlignment = failwith "todo"
member this.HorizontalTextAlignment = TextAlignment.Start
member this.InputTransparent = true
member this.IsEnabled = failwith "todo"
member this.IsFocused = failwith "todo"
member this.LineHeight = 1.
member this.Margin = failwith "todo"
member this.MaximumHeight = failwith "todo"
member this.MaximumWidth = failwith "todo"
member this.MinimumHeight = failwith "todo"
member this.MinimumWidth = failwith "todo"
member this.Opacity = 1.
member this.Padding = Thickness()
member this.Parent = this.Parent
member this.Rotation = 0.
member this.RotationX = 0.
member this.RotationY = 0.
member this.Scale = 1.
member this.ScaleX = 1.
member this.ScaleY = 1.
member this.Semantics = null
member this.Shadow = null
member this.Text = this.Text
member this.TextColor = this.TextColor
member this.TextDecorations = TextDecorations.None
member this.TranslationX = 0.
member this.TranslationY = 0.
member this.VerticalLayoutAlignment = failwith "todo"
member this.VerticalTextAlignment = failwith "todo"
member this.Visibility = Visibility.Visible
member this.Width = -1
member this.ZIndex = failwith "todo"
member this.Frame with set value = failwith "todo"
member this.IsFocused with set value = failwith "todo"

member this.Handler
with get () : IElementHandler = this.Handler
and set value = this.Handler <- value

member this.Handler
with get () = this.Handler :?> IViewHandler
and set (value: IViewHandler) = this.Handler <- value

module FabulousLabel =
let WidgetKey = Widgets.register<FabulousLabel>()

let Text =
Attributes.defineSimpleScalarWithEquality<string>
"Text"
(fun _ newValue node ->
let target = node.Target :?> FabulousLabel
match newValue with
| ValueNone -> target.Text <- ""
| ValueSome value -> target.Text <- value
let res = (target :> ILabel).Handler
res.UpdateValue("Text"))

let TextColor =
Attributes.defineSimpleScalarWithEquality<Color>
"TextColor"
(fun _ newValue node ->
let target = node.Target :?> FabulousLabel
match newValue with
| ValueNone -> target.TextColor <- null
| ValueSome value -> target.TextColor <- value
let res = (target :> ILabel).Handler
res.UpdateValue("TextColor"))

[<AutoOpen>]
module LabelBuilders =
type Fabulous.Maui.View with
static member inline Label<'msg>(text: string) =
WidgetBuilder<'msg, ILabel>(FabulousLabel.WidgetKey, FabulousLabel.Text.WithValue(text))

[<Extension>]
type LabelModifiers =
[<Extension>]
static member inline textColor(this: WidgetBuilder<'msg, #ILabel>, value: Color) =
this.AddScalar(FabulousLabel.TextColor.WithValue(value))
Loading

0 comments on commit e75371a

Please sign in to comment.