Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add missing properties to Shell related controls #447

Merged
merged 1 commit into from
Jun 12, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
135 changes: 129 additions & 6 deletions src/Fabulous.Core/ViewConverters.fs
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ type ViewElementCell() =
modelOpt <- None
| None -> ()

type ItemViewElementCell() =
type ContentViewElement() =
inherit ContentView()

let mutable listElementOpt : IItemListElement option = None
Expand Down Expand Up @@ -179,10 +179,10 @@ type CustomListView() =
inherit ListView(ItemTemplate=DataTemplate(typeof<ViewElementCell>))

type CustomCollectionListView() =
inherit CollectionView(ItemTemplate=DataTemplate(typeof<ItemViewElementCell>))
inherit CollectionView(ItemTemplate=DataTemplate(typeof<ContentViewElement>))

type CustomCarouselView() =
inherit CarouselView(ItemTemplate=DataTemplate(typeof<ItemViewElementCell>))
inherit CarouselView(ItemTemplate=DataTemplate(typeof<ContentViewElement>))

/// A custom control for the ListViewGrouped view element
type CustomGroupListView() =
Expand All @@ -200,6 +200,18 @@ type CustomContentPage() as self =
base.OnSizeAllocated(width, height)
sizeAllocated.Trigger(width, height)

/// A custom SearchHandler which exposes the overridable methods OnQueryChanged, OnQueryConfirmed and OnItemSelected as events
type CustomSearchHandler() =
TimLariviere marked this conversation as resolved.
Show resolved Hide resolved
inherit SearchHandler(ItemTemplate=DataTemplate(typeof<ContentViewElement>))

member val QueryChanged = ignore with get, set
member val QueryConfirmed = ignore with get, set
member val ItemSelected: obj -> unit = ignore with get, set

override this.OnQueryChanged(oldValue, newValue) = this.QueryChanged (oldValue, newValue)
override this.OnQueryConfirmed() = this.QueryConfirmed ()
override this.OnItemSelected(item) = this.ItemSelected item

[<AutoOpen>]
module Converters =
open System.Collections.ObjectModel
Expand Down Expand Up @@ -452,6 +464,12 @@ module Converters =
oc
updateCollectionGeneric (ValueOption.map seqToArray prevCollOpt) (ValueOption.map seqToArray collOpt) targetColl ListElementData (fun _ _ _ -> ()) canReuseChild (fun _ curr target -> target.Key <- curr)

/// Update the items in a SearchHandler control, given previous and current view elements
let updateSearchHandlerItems (prevCollOpt: seq<'T> voption) (collOpt: seq<'T> voption) (target: Xamarin.Forms.SearchHandler) =
TimLariviere marked this conversation as resolved.
Show resolved Hide resolved
let targetColl = List<ItemListElementData>()
updateCollectionGeneric (ValueOption.map seqToArray prevCollOpt) (ValueOption.map seqToArray collOpt) targetColl ItemListElementData (fun _ _ _ -> ()) canReuseChild (fun _ curr target -> target.Key <- curr)
target.ItemsSource <- targetColl

/// Update the items in a CollectionView control, given previous and current view elements
let internal updateCollectionViewItems (prevCollOpt: seq<'T> voption) (collOpt: seq<'T> voption) (target: Xamarin.Forms.CollectionView) =
let targetColl =
Expand Down Expand Up @@ -771,7 +789,17 @@ module Converters =
| :? ShellItem as shellItem -> shellItem
| child -> failwithf "%s is not compatible with the type ShellItem" (child.GetType().Name)

updateCollectionGeneric prevCollOpt collOpt target.Items create (fun _ _ _ -> ()) (fun _ _ -> true) updateChild
let update prevViewElement (currViewElement: ViewElement) (target: ShellItem) =
let realTarget =
match currViewElement.TargetType with
| t when t = typeof<ShellContent> -> target.Items.[0].Items.[0] :> Element
| t when t = typeof<TemplatedPage> -> target.Items.[0].Items.[0] :> Element
| t when t = typeof<ShellSection> -> target.Items.[0] :> Element
| t when t = typeof<MenuItem> -> target.GetType().GetProperty("MenuItem").GetValue(target) :?> Element // MenuShellItem is marked as internal
| _ -> target :> Element
updateChild prevViewElement currViewElement realTarget

updateCollectionGeneric prevCollOpt collOpt target.Items create (fun _ _ _ -> ()) (fun _ _ -> true) update

/// Update the menu items of a ShellContent, given previous and current view elements
let internal updateMenuItemsShellContent (prevCollOpt: ViewElement array voption) (collOpt: ViewElement array voption) (target: Xamarin.Forms.ShellContent) =
Expand All @@ -789,7 +817,15 @@ module Converters =
| :? ShellSection as shellSection -> shellSection
| child -> failwithf "%s is not compatible with the type ShellSection" (child.GetType().Name)

updateCollectionGeneric prevCollOpt collOpt target.Items create (fun _ _ _ -> ()) (fun _ _ -> true) updateChild
let update prevViewElement (currViewElement: ViewElement) (target: ShellSection) =
let realTarget =
match currViewElement.TargetType with
| t when t = typeof<ShellContent> -> target.Items.[0] :> BaseShellItem
| t when t = typeof<TemplatedPage> -> target.Items.[0] :> BaseShellItem
| _ -> target :> BaseShellItem
updateChild prevViewElement currViewElement realTarget

updateCollectionGeneric prevCollOpt collOpt target.Items create (fun _ _ _ -> ()) (fun _ _ -> true) update

/// Update the items of a ShellSection, given previous and current view elements
let internal updateShellSectionItems (prevCollOpt: ViewElement array voption) (collOpt: ViewElement array voption) (target: Xamarin.Forms.ShellSection) =
Expand All @@ -815,7 +851,7 @@ module Converters =
| _, ValueSome newVal -> target.SetValue(Xamarin.Forms.SearchHandler.SelectedItemProperty, newVal)

/// Update the IsCheckedProperty of a BaseShellItem, given previous and current IsChecked
let internal updateIsCecked prevValue currValue (target: Xamarin.Forms.BaseShellItem) =
let internal updateIsChecked prevValue currValue (target: Xamarin.Forms.BaseShellItem) =
match prevValue, currValue with
| ValueNone, ValueNone -> ()
| ValueSome prevVal, ValueSome newVal when prevVal = newVal -> ()
Expand Down Expand Up @@ -917,3 +953,90 @@ module Converters =
let items = (sender :?> Xamarin.Forms.ListView).ItemsSource :?> System.Collections.Generic.IList<ListGroupData>
tryFindGroupedListViewItemIndex items item
| _ -> None

let internal updateShellSearchHandler prevValueOpt (currValueOpt: ViewElement voption) target =
match prevValueOpt, currValueOpt with
| ValueNone, ValueNone -> ()
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueSome prevValue, ValueSome currValue ->
let searchHandler = Shell.GetSearchHandler(target)
currValue.UpdateIncremental(prevValue, searchHandler)
| ValueNone, ValueSome currValue -> Shell.SetSearchHandler(target, currValue.Create() :?> Xamarin.Forms.SearchHandler)
| ValueSome _, ValueNone -> Shell.SetSearchHandler(target, null)

let internal updateShellBackgroundColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetBackgroundColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetBackgroundColor(target, Color.Default)

let internal updateShellForegroundColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetForegroundColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetForegroundColor(target, Color.Default)

let internal updateShellTitleColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetTitleColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetTitleColor(target, Color.Default)

let internal updateShellDisabledColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetDisabledColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetDisabledColor(target, Color.Default)

let internal updateShellUnselectedColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetUnselectedColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetUnselectedColor(target, Color.Default)

let internal updateShellTabBarBackgroundColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetTabBarBackgroundColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetTabBarBackgroundColor(target, Color.Default)

let internal updateShellTabBarForegroundColor prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetTabBarForegroundColor(target, currValue)
| ValueSome _, ValueNone -> Shell.SetTabBarForegroundColor(target, Color.Default)

let internal updateShellBackButtonBehavior prevValueOpt (currValueOpt: ViewElement voption) target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetBackButtonBehavior(target, currValue.Create() :?> BackButtonBehavior)
| ValueSome _, ValueNone -> Shell.SetBackButtonBehavior(target, null)

let internal updateShellTitleView prevValueOpt (currValueOpt: ViewElement voption) target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetTitleView(target, currValue.Create() :?> View)
| ValueSome _, ValueNone -> Shell.SetTitleView(target, null)

let internal updateShellFlyoutBehavior prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetFlyoutBehavior(target, currValue)
| ValueSome _, ValueNone -> Shell.SetFlyoutBehavior(target, FlyoutBehavior.Flyout)

let internal updateShellTabBarIsVisible prevValueOpt currValueOpt target =
match prevValueOpt, currValueOpt with
| ValueSome prevValue, ValueSome currValue when prevValue = currValue -> ()
| ValueNone, ValueNone -> ()
| _, ValueSome currValue -> Shell.SetTabBarIsVisible(target, currValue)
| ValueSome _, ValueNone -> Shell.SetTabBarIsVisible(target, true)
5 changes: 4 additions & 1 deletion tools/Generator/CodeGenerator.fs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ module CodeGenerator =
match m with
| "ElementCreated" ->
w.printfn " let ElementCreatedAttribKey : AttributeKey<(obj -> unit)> = AttributeKey<(obj -> unit)>(\"ElementCreated\")"
| "SearchHandlerItemSelected" -> // AttributeKey<_> incorrectly generalizes obj to 'a
w.printfn " let SearchHandlerItemSelectedAttribKey : AttributeKey<(obj -> unit)> = AttributeKey<(obj -> unit)>(\"SearchHandlerItemSelected\")"
| _ ->
w.printfn " let %sAttribKey : AttributeKey<_> = AttributeKey<_>(\"%s\")" m m
w.printfn ""
Expand Down Expand Up @@ -164,7 +166,8 @@ module CodeGenerator =
match m.BoundType with

// Check if the type of the member is in the model, if so issue recursive calls to "Create" and "UpdateIncremental"
| Some boundType when (tryFindType data.KnownTypes boundType.FullName).IsSome && not hasApply ->
// ModelType = "ViewElement" is also accepted because some properties (like FlyoutHeader) are typed object by default (thus disabling control reuse in the generator)
| Some boundType when ((tryFindType data.KnownTypes boundType.FullName).IsSome || m.ModelType = "ViewElement") && not hasApply ->
w.printfn " match prev%sOpt, curr%sOpt with" m.UniqueName m.UniqueName
w.printfn " // For structured objects, dependsOn on reference equality"
w.printfn " | ValueSome prevValue, ValueSome newValue when identical prevValue newValue -> ()"
Expand Down
5 changes: 4 additions & 1 deletion tools/Generator/Resolvers.fs
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,10 @@ module Resolvers =

let getModelType (this : MemberBinding, bindings : Bindings, memberResolutions, hierarchy : seq<TypeReference * TypeDefinition>) =
match this.ModelType with
| NotNullOrWhitespace s -> s
| NotNullOrWhitespace s ->
match (bindings.Types |> Seq.tryFind (fun x -> x.Name = s)) with
| None -> s
| Some _ -> "ViewElement"
| _ ->
match tryGetBoundType memberResolutions this with
| None -> failwithf "no type for %s" this.Name
Expand Down
Loading