Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- namespace FSharpSandbox.iOS
- open System
- open System.Drawing
- open MonoTouch.UIKit
- open MonoTouch.Foundation
- open Microsoft.FSharp.Quotations
- type EventHandler<'Model> =
- | Sync of ('Model -> 'Model)
- | Async of ('Model -> Async<'Model>)
- | Seq of EventHandler<'Model> seq
- type IController<'Event, 'Model> =
- abstract member InitModel : unit -> 'Model
- abstract member Handle : ('Event -> EventHandler<'Model>)
- [<Preserve (AllMembers = true)>]
- type TestModel = { FirstName: string; LastName: string; ClickCount: int; ClickEnabled: bool }
- module TestModelModule =
- let fullName model = model.FirstName + " " + model.LastName
- let enableClick model = { model with ClickEnabled = true }
- let disableClick model = { model with ClickEnabled = false }
- let click model = { model with ClickCount = model.ClickCount + 1 }
- let clickAsync model = async {
- do! Async.Sleep 1000
- return click model |> enableClick }
- type TestModelEvent =
- | Clicked
- type TestController () =
- interface IController<TestModelEvent, TestModel> with
- member this.InitModel () = { FirstName = ""; LastName = ""; ClickCount = 0; ClickEnabled = true }
- member this.Handle = function
- //| Clicked -> Sync TestModelModule.click
- | Clicked -> seq {
- yield Sync TestModelModule.disableClick
- yield Async TestModelModule.clickAsync } |> Seq
- [<Register ("FSharpSandbox_iOSViewController")>]
- [<Preserve (AllMembers = true)>]
- type FSharpSandbox_iOSViewController () =
- inherit UIViewController ()
- let controller = TestController () :> IController<TestModelEvent, TestModel>
- let mutable model = controller.InitModel ()
- let mutable prevModel = model
- let click (args: EventArgs) = Clicked
- let uiButtonEnabledBinding (button: UIButton) f = fun x -> button.Enabled <- f x
- let uiButtonTitleBinding (button: UIButton) f = fun x -> button.SetTitle (f x)
- // Release any cached data, images, etc that aren't in use.
- override this.DidReceiveMemoryWarning () =
- base.DidReceiveMemoryWarning ()
- // Perform any additional setup after loading the view, typically from a nib.
- override this.ViewDidLoad () =
- base.ViewDidLoad ()
- this.View.BackgroundColor <- UIColor.White
- let btn = UIButton.FromType UIButtonType.System
- let txtv = new UITextView (RectangleF (16.f, 16.f, 64.f, 32.f))
- btn.Frame <- RectangleF (96.f, 96.f, 196.f, 32.f)
- btn.SetTitle ("Click", UIControlState.Normal)
- this.View.AddSubview btn
- this.View.AddSubview txtv
- let btnEnabledBinding = uiButtonEnabledBinding btn (fun x -> x.ClickEnabled)
- let btnTitleBinding = uiButtonTitleBinding btn (fun x -> sprintf "Clicked %i times!" x.ClickCount, UIControlState.Normal)
- let getPropertyValues model =
- let typ = model.GetType()
- typ.GetProperties()
- |> Array.map (fun x -> (x.Name, x.GetValue model))
- let check prevModel model =
- let prevValues = getPropertyValues prevModel
- let values = getPropertyValues model
- prevValues
- |> Array.iter2 (fun (name, value1) (_, value2) ->
- if value1 <> value2 && name = "ClickCount" then btnTitleBinding model
- if value1 <> value2 && name = "ClickEnabled" then btnEnabledBinding model
- ) values
- let rec eventHandler = function
- | Sync eh ->
- prevModel <- model
- model <- eh model
- check prevModel model
- | Async eh ->
- prevModel <- model
- Async.StartWithContinuations (
- computation = eh model,
- continuation = (fun x ->
- model <- x
- check prevModel x),
- exceptionContinuation = ignore,
- cancellationContinuation = ignore)
- | Seq xs -> xs |> Seq.iter eventHandler
- let handle x = controller.Handle x |> eventHandler
- btn.TouchUpInside
- |> Observable.map click
- |> Observable.subscribe handle
- |> ignore
- // Return true for supported orientations
- override this.ShouldAutorotateToInterfaceOrientation (orientation) =
- orientation <> UIInterfaceOrientation.PortraitUpsideDown
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement