Skip to content

Commit

Permalink
another attemp
Browse files Browse the repository at this point in the history
  • Loading branch information
edgarfgp committed Sep 2, 2023
1 parent 5453035 commit c2cd2ee
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 3 deletions.
69 changes: 69 additions & 0 deletions src/Fabulous.Avalonia/Attributes.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ namespace Fabulous.Avalonia

open System
open System.Collections
open System.Collections.Generic
open System.ComponentModel
open Avalonia
open Avalonia.Collections
open Avalonia.Input.GestureRecognizers
open Avalonia.Interactivity
open Fabulous
open Fabulous.ScalarAttributeDefinitions
Expand Down Expand Up @@ -238,6 +240,73 @@ module Attributes =

Attributes.defineWidgetCollection name applyDiff updateNode

let defineAvaloniaGestureRecognizerCollection<'itemType> name (getCollection: obj -> GestureRecognizerCollection) =
let applyDiff _ (diffs: WidgetCollectionItemChanges) (node: IViewNode) =
let targetColl = getCollection node.Target
let targetColl = List<GestureRecognizer>(targetColl)

for diff in diffs do
match diff with
| WidgetCollectionItemChange.Remove(index, widget) ->
let itemNode = node.TreeContext.GetViewNode(box targetColl[index])

// Trigger the unmounted event
Dispatcher.dispatchEventForAllChildren itemNode widget Lifecycle.Unmounted
itemNode.Disconnect()

// Remove the child from the UI tree
targetColl.RemoveAt(index)

| _ -> ()

for diff in diffs do
match diff with
| WidgetCollectionItemChange.Insert(index, widget) ->
let struct (itemNode, view) = Helpers.createViewForWidget node widget

// Insert the new child into the UI tree
targetColl.Insert(index, unbox view)

// Trigger the mounted event
Dispatcher.dispatchEventForAllChildren itemNode widget Lifecycle.Mounted

| WidgetCollectionItemChange.Update(index, widgetDiff) ->
let childNode = node.TreeContext.GetViewNode(box targetColl[index])

childNode.ApplyDiff(&widgetDiff)

| WidgetCollectionItemChange.Replace(index, oldWidget, newWidget) ->
let prevItemNode = node.TreeContext.GetViewNode(box targetColl[index])

let struct (nextItemNode, view) = Helpers.createViewForWidget node newWidget

// Trigger the unmounted event for the old child
Dispatcher.dispatchEventForAllChildren prevItemNode oldWidget Lifecycle.Unmounted
prevItemNode.Disconnect()

// Replace the existing child in the UI tree at the index with the new one
targetColl[index] <- unbox view

// Trigger the mounted event for the new child
Dispatcher.dispatchEventForAllChildren nextItemNode newWidget Lifecycle.Mounted

| _ -> ()

let updateNode _ (newValueOpt: ArraySlice<Widget> voption) (node: IViewNode) =
let targetColl = getCollection node.Target
// let targetColl = List<GestureRecognizer>(targetColl)
// targetColl.Clear()

match newValueOpt with
| ValueNone -> ()
| ValueSome widgets ->
for widget in ArraySlice.toSpan widgets do
let struct (_, view) = Helpers.createViewForWidget node widget

targetColl.Add(unbox view)

Attributes.defineWidgetCollection name applyDiff updateNode

/// Define an attribute storing a Widget for an AvaloniaProperty
let inline defineAvaloniaPropertyWidget (property: AvaloniaProperty<'T>) =
Attributes.definePropertyWidget property.Name (fun target -> (target :?> AvaloniaObject).GetValue(property)) (fun target value ->
Expand Down
4 changes: 4 additions & 0 deletions src/Fabulous.Avalonia/Fabulous.Avalonia.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
<Compile Include="Views\_Visual.fs" />
<Compile Include="Views\_Layoutable.fs" />
<Compile Include="Views\_Interactive.fs" />
<Compile Include="Views\_GestureRecognizer.fs" />
<Compile Include="Views\_InputElement.fs" />
<Compile Include="Views\_DragDrop.fs" />
<Compile Include="Views\_FlyoutBase.fs" />
Expand Down Expand Up @@ -213,6 +214,9 @@
<Compile Include="Views\Panels\DockPanel.fs" />
<Compile Include="Views\Panels\WrapPanel.fs" />
<Compile Include="Views\Panels\UniformGrid.fs" />
<Compile Include="Views\GestureRecognizers\PullGestureRecognizer.fs" />
<Compile Include="Views\GestureRecognizers\PinchGestureRecognizer.fs" />
<Compile Include="Views\GestureRecognizers\ScrollGestureRecognizer.fs" />
<Compile Include="Application.fs" />
<Compile Include="ThemeAware.fs" />
<Compile Include="Any.fs" />
Expand Down
18 changes: 15 additions & 3 deletions src/Fabulous.Avalonia/Views/_InputElement.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ namespace Fabulous.Avalonia
open System.Runtime.CompilerServices
open Avalonia.Collections
open Avalonia.Input
open Avalonia.Input.GestureRecognizers
open Avalonia.Input.TextInput
open Avalonia.Interactivity
open Fabulous
Expand Down Expand Up @@ -31,9 +32,7 @@ module InputElement =
Attributes.defineAvaloniaPropertyWithEquality InputElement.TabIndexProperty

let GestureRecognizers =
Attributes.defineAvaloniaListWidgetCollection "InputElement_GestureRecognizers" (fun target ->
let target = (target :?> InputElement)
AvaloniaList(target.GestureRecognizers))
Attributes.defineAvaloniaGestureRecognizerCollection "InputElement_GestureRecognizers" (fun target -> (target :?> InputElement).GestureRecognizers)

let GotFocus =
Attributes.defineEvent<GotFocusEventArgs> "InputElement_GotFocus" (fun target -> (target :?> InputElement).GotFocus)
Expand Down Expand Up @@ -239,3 +238,16 @@ type InputElementModifiers =
[<Extension>]
static member inline onDoubleTapped(this: WidgetBuilder<'msg, #IFabInputElement>, fn: RoutedEventArgs -> 'msg) =
this.AddScalar(InputElement.DoubleTapped.WithValue(fn))

/// <summary>Sets the GestureRecognizers property.</summary>
/// <param name="this">Current widget.</param>
[<Extension>]
static member inline gestureRecognizers<'msg, 'marker when 'marker :> IFabInputElement>(this: WidgetBuilder<'msg, 'marker>) =
AttributeCollectionBuilder<'msg, 'marker, IFabGestureRecognizer>(this, InputElement.GestureRecognizers)

/// <summary>Sets the GestureRecognizers property.</summary>
/// <param name="this">Current widget.</param>
/// <param name="value">Gesture recognizer.</param>
[<Extension>]
static member inline gestureRecognizer(this: WidgetBuilder<'msg, #IFabInputElement>, value: WidgetBuilder<'msg, #IFabGestureRecognizer>) =
AttributeCollectionBuilder<'msg, 'marker, IFabGestureRecognizer>(this, InputElement.GestureRecognizers) { value }

0 comments on commit c2cd2ee

Please sign in to comment.