Tracking Apple Pencil angles and pressure with Xamarin

Rumor has it that Apple will support the Apple Pencil in the forthcoming iPad. If so, more developers will want to use the new features of UITouch — force, angle, and elevation — supported by the incredibly-precise stylus.

Basically, it’s trivial:

— Force is UITouch.Force;
— Angle is UITouch.GetAzimuthAngle(UIView); and
— Angle above horizontal is UITouch.AltitudeAngle

(The UIView objects are there, I think, to make it easier to create a custom angular transform that is more natural to the task at hand — i.e., an artist could “rotate” the page slightly to accommodate the angle with which they like to work. I think.)

Anyhow, here’s some code:


namespace UITouch0

open System
open UIKit
open Foundation
open System.Drawing
open CoreGraphics

type ContentView(color : UIColor) as this = 
   inherit UIView()
   do this.BackgroundColor <- color

   let MaxRadius = 200.0
   let MaxStrokeWidth = nfloat 10.0

   //Mutable!
   member val Circle : (CGPoint * nfloat * nfloat * nfloat ) option = None with get, set

   member this.DrawTouch (touch : UITouch) = 
      let radius = (1.0 - (float touch.AltitudeAngle) / (Math.PI / 2.0)) * MaxRadius |> nfloat
      this.Circle <- Some (touch.LocationInView(this), radius, touch.GetAzimuthAngle(this), touch.Force)
      this.SetNeedsDisplay()


   override this.Draw rect = 

      match this.Circle with
      | Some (location, radius, angle, force) ->
         let rectUL = new CGPoint(location.X - radius, location.Y - radius)
         let rectSize = new CGSize(radius * (nfloat 2.0), radius * (nfloat 2.0))
         use g = UIGraphics.GetCurrentContext()
         let strokeWidth = force * MaxStrokeWidth
         g.SetLineWidth(strokeWidth)
         let hue = angle / nfloat (Math.PI * 2.0)
         let color = UIColor.FromHSB(hue, nfloat 1.0, nfloat 1.0) 
         g.SetStrokeColor(color.CGColor)
         g.AddEllipseInRect <| new CGRect(rectUL, rectSize)
         g.MoveTo (location.X, location.Y)
         let endX = location.X + nfloat (cos(float angle)) * radius
         let endY = location.Y + nfloat (sin(float angle)) * radius
         g.AddLineToPoint (endX, endY)
         g.StrokePath()
      | None -> ignore() 

type SimpleController() = 
   inherit UIViewController()
   override this.ViewDidLoad() = 
      this.View <- new ContentView(UIColor.Blue)

   override this.TouchesBegan(touches, evt) =
     let cv = this.View :?> ContentView
       
     touches |> Seq.map (fun o -> o :?> UITouch) |> Seq.iter cv.DrawTouch

   override this.TouchesMoved(touches, evt) = 
      let cv = this.View :?> ContentView
      touches |> Seq.map (fun o -> o :?> UITouch) |> Seq.iter cv.DrawTouch
   


[<Register("AppDelegate")>]
type AppDelegate() = 
   inherit UIApplicationDelegate()
   let window = new UIWindow(UIScreen.MainScreen.Bounds)

   override this.FinishedLaunching(app, options) = 
      let viewController = new SimpleController()
      viewController.Title <- "F# Rocks"
      let navController = new UINavigationController(viewController)
      window.RootViewController <- navController
      window.MakeKeyAndVisible()
      true

   
module Main = 
   [<EntryPoint>]
   let main args = 
      UIApplication.Main(args, null, "AppDelegate")
      0

And it looks like this:

TideMonkey: Development Diary 0

I am publicly committing to developing “TideMonkey,” a tide-prediction application that will run on (at least) iOS and watchOS.

TideMonkey will be based on Xtide, an excellent piece of software developed by David Flater. At the moment, my hope is that it will be a very loose port, or what Flater refers to as a “non-port” that reuses the harmonics files of Xtide but is otherwise only loosely based on the source code. On the other hand, I know virtually nothing about the domain, so it is likely that I will have to hew pretty closely to Xtide’s algorithms, at least initially. Ideally I would like to be able to plugin different algorithms and compare their results with the canonical Xtide. Neural nets are a particular interest of mine and one would think that a harmonic series would be the type of thing that one could successfully train (if this ever happens, it won’t be for months and months and months).

I am battling the urge to dive right into coding. Instead, I know that I will be happy by investing in:

  • automation, and
  • testing, and
  • continuous integration

All of which argues for me to begin my journey by getting Xtide, which is written in C++, up and running in a CI server. For no particular reason (but it’s free for personal use) I’ve chosen to use TeamCity for my CI server.


Hmm…

There are several Xtide ports on Github to iOS or Android. The first one I tried was last updated in 2013 and doesn’t run on iOS 9 (it looks like a simple permissions issue, but it doesn’t run “straight from the cloud” and I don’t know if I want to deal with a port rather than just go with the original “straight from the horse’s mouth” Xtide source.

At the moment, I think I’ll work all inside the single “TideMonkey” Github repo. I’ll have to check license restrictions on that, and I don’t know how it will work out once the project structure starts to become more complicated, with testing and mobile development as part of it.

Still,

Creating TideMonkey Github report

MIT License

TideMonkey repo

Programming WatchKit with F#

Disclaimer: This is just a hack. I’m not in any position to make announcements about stuff, but Xamarin loves F# and I’m sure that better solutions than this are forthcoming. But this was fun to get running, so…

Xamarin just released it’s Preview of Watch Kit support and naturally, I had to see if it was possible to use F# to program the forthcoming Apple Watch. Yes, it is.

As always with Watch Kit Apps, the Xamarin solution consists of three projects:

  1. A Parent app that is a normal iOS app;
  2. An Extension that runs on a connected iPhone and executes the program logic; and
  3. A Watch App that runs on the Watch and is essentially a remote display for the Extension App

You can read much more about this at Xamarin’s Watch Kit Documentation site.

To create an F# Watch solution, first create an F#-based Parent App. Then, add the Extension project to that app, an F#-based Custom Keyboard Extension. Finally, add a Watch App from the C#/iOS/Unified/Apple Watch solution template.

The Watch App consists only of a storyboard and resources. It doesn’t actually have any C# (or F#) code in it.

Follow these instructions to [set project references and identifiers].

Switching the Extension from Custom Keyboard to Watch Kit

You will have to manually edit the info.plist of the Watch Extension:

  • In NSExtension, switch the NSExtensionPointIdentifier to com.apple.watchkit; and
  • Under NSExtensionAttributes, add a WKAppBundleIdentifier key to the identifier of your Watch App (e.g., com.xamarin.FWatch1.watchkitapp)

Screenshot 2015-01-21 15.02.07

Now you can get rid of the template F# code and replace it with something like this:

namespace WatchX

open System
open UIKit
open Foundation
open WatchKit

type InterfaceController(ip : IntPtr) =
    inherit WKInterfaceController(ip)

override this.Awake (context) =
    System.Console.WriteLine("Hello F#")
    this.myLabel.SetText("F# |> I ♡")

Again, this is covered in much more detail in Xamarin’s docs, but every scene in the Watch App’s storyboard is backed by a subtype of WKInterfaceController. Since it’s loaded from a Storyboard, it uses the constructor that takes an IntPtr. The Awake method is called when the controller is instantiated.

The Hacky Part

Xamarin has not yet released designer support for Watch Kit, so for now, you need to edit your Watch App’s Storyboard in XCode Interface Builder.

That’s not the hacky part.

Once you’ve designed your UI, you have to hand-edit the Storyboard XML, adding connections elements that define your outlets (properties) and actions (event-handlers). You have to set the destination attribute to refer to the id of the associated control:

Screenshot 2015-01-21 15.37.52

But really, that’s the only ugly part! ;-)

Back in your Extension app, you now have to use attributes to link up your F# code with elements within the Storyboard. The RegisterAttribute on your WKInterfaceController links to the customClass attribute of the controller element, and the name of your OutletAttribute properties must correspond to the property attribute of the outlet elements. Finally, the selector attribute of your action elements must have a corresponding ActionAttribute :

    namespace WatchX

    open System
    open UIKit
    open Foundation
    open WatchKit

    [<register ("InterfaceController")>]
    type InterfaceController(ip : IntPtr) = 
        inherit WKInterfaceController(ip)

        let mutable label : WKInterfaceLabel = null
        let mutable button : WKInterfaceButton = null

        let mutable clickCount = 0
       
        [<outlet>]
        member this.myLabel with get() = label
        member this.myLabel with set(v) = label < - v

        [<Outlet>]
        member this.myButton with get() = button
        member this.myButton with set(v) = button < - v

        [<Action("OnButtonPress")>]
        member this.OnButtonPush () =
            clickCount < - clickCount + 1
            sprintf "Pressed %d times" clickCount 
            |> this.myLabel.SetText 


        override this.Awake (context) = 
            System.Console.WriteLine("Hello F#")
            this.myLabel.SetText("F# |> I ♡")

And that’s really all there is to putting F# on your wrist!

Github project

Xamarin.Forms Programming in F#

Things are kind of busy what with Evolve being only 40 days away and iOS 8 coming down the pipe, but I thought I’d share the easy hack that allows you to program Xamarin.Forms with F#.

(Of course, Xamarin loves F# and official support and templates and documentation and all that sort of stuff is forthcoming. This is just something you can do for the moment to begin exploring Xamarin.Forms with F#.)

tl;dr: Use the beta PCL 78 F# Core and link to the facade assemblies for monotouch

OK, so assuming that was a bit too brief…

In Xamarin.Studio create a “New solution…” of type F#/iOS/iPhone/Empty Project…

Open the “References” folder and delete the existing reference to Fsharp.core.dll.

Right-click the solution and select “Add Packages…”

Screenshot 2014-08-27 15.42.39

 

In the NuGet dialog, select “Show pre-release packages” and type FSharp.Core into the search box. This should allow you to add the “FSharp.Core Mono delay signed” package.

Screenshot 2014-08-27 15.25.05Also, add the Xamarin.Forms package:

Screenshot 2014-08-27 15.46.26

And now the tricky part!  You have to add references to the System.ObjectModel.dll and System.Runtime.dlls from the monotouch facade assemblies by hand.

Right-click on the References folder, Select “Edit…”, and select “.NET Assembly”. Add references to System.ObjectModel.dll and System.Runtime.dll from, in my case:

/Library/Frameworks/Mono.framework/Versions/Current/lib/mono/4.5/Facades/

Your path may be a little different.

Write a Xamarin.Forms app in 36 lines of code :


namespace FSXF1

open System
open MonoTouch.UIKit
open MonoTouch.Foundation
open Xamarin.Forms

type App = class
 static member GetMainPage =
   let lbl = new Label()
   lbl.Text <- "Hello, F# Xam.Forms!"
   lbl.VerticalOptions <- LayoutOptions.CenterAndExpand
   lbl.HorizontalOptions <- LayoutOptions.CenterAndExpand

   let cp = new ContentPage()
   cp.Content <- lbl
   cp
end

[<Register("AppDelegate")>]
type AppDelegate() =
 inherit UIApplicationDelegate()

 member val Window = null with get, set

// This method is invoked when the application is ready to run.
 override this.FinishedLaunching(app, options) =
   this.Window <- new UIWindow(UIScreen.MainScreen.Bounds)
   Forms.Init()
   this.Window.RootViewController <- App.GetMainPage.CreateViewController()
   this.Window.MakeKeyAndVisible()
   true

module Main =
   [<EntryPoint>]
   let main args =
     UIApplication.Main(args, null, "AppDelegate")
     0

And you’re good to go!

Screenshot 2014-08-25 10.16.14

 

P.S. If it helps: https://github.com/lobrien/HelloXamarinFormsFSharp

F# For Scripting

It’s F# Week at Xamarin. Also, in the US, it’s only a 4-day work-week. F# saves 20% of your time. QED.

Anyway, I don’t have any actually interesting F# to share, but I recommend:

But what I thought I could quickly contribute is that:

  • F# is an awesome scripting language; and
  • Scripting may be the best way to learn F#

Scripting tasks often involve transforming a stream of text by repeatedly Filtering, Assigning, Reducing, Transforming, and Slicing it (“a sequence of FARTS“) and this is an area where the functional approach is pretty clearly easier to work with than the OOP approach of a network of cooperating objects.

And since scripting tasks are often private or semi-private low-complexity chores, they’re an excellent domain for regularly exercising your knowledge of a new language. It’s all well and good to carve out a couple weekends and work through a book but nothing beats regular exposure.

(While I’m on the subject, these are currently my favorite F# books. Initial exploration:

Deeper dives:

)

F# scripts are F# files with the .fsx extension. On OS X with mono, they can be run with fsharpi script.fsx or:

#if run_with_bin_sh
  exec fsharpi --exec $0 $*
#endif
printfn "%A" fsi.CommandLineArgs

To add references, use #r:

#if run_with_bin_sh
  exec fsharpi --exec $0 $*
#endif

#r "System.Core.dll"
#r "System.Xml"

open System
open System.Xml.Linq
open System.IO

//...etc...

I’ve been using F# for scripting for more than a year now and I can honestly say that it’s displaced Ruby as my scripting language of choice.

Give it a shot!

iOS 8, Scene Kit @ 60FPS, programmed in F#, using Xamarin.iOS

I have the best job in the world:

namespace SceneKitFSharp

open System
open MonoTouch.UIKit
open MonoTouch.Foundation
open MonoTouch.SceneKit
open MonoTouch.CoreAnimation

type MySceneKitController () =
    inherit UIViewController()

    override this.ViewDidLoad () =
        let scene = new SCNScene ()

        //Positions everyone!
        let boxNode = new SCNNode ()
        boxNode.Geometry <- new SCNBox(
            Width = 1.0F, 
            Height = 1.0F, 
            Length = 1.0F, 
            ChamferRadius = 0.02f
        )
        scene.RootNode.AddChildNode (boxNode)

        let material = new SCNMaterial ()
        material.Diffuse.Contents <- UIImage.FromFile ("textureX.png")
        material.Specular.Contents <- UIColor.Gray
        material.LocksAmbientWithDiffuse <- true
        boxNode.Geometry.FirstMaterial <- material

        //Lights!
        let lightNode = new SCNNode()
        lightNode.Light <- new SCNLight ()
        lightNode.Light.LightType <- SCNLightType.Omni
        lightNode.Position <- new SCNVector3 (0.0F, 10.0F, 10.0F)
        scene.RootNode.AddChildNode (lightNode)

        let ambientLightNode = new SCNNode ()
        ambientLightNode.Light <- new SCNLight ()
        ambientLightNode.Light.LightType <- SCNLightType.Ambient
        ambientLightNode.Light.Color <- UIColor.DarkGray
        scene.RootNode.AddChildNode (ambientLightNode)

        //Camera!
        let cameraNode = new SCNNode ()
        cameraNode.Camera <- new SCNCamera ()
        scene.RootNode.AddChildNode (cameraNode)
        cameraNode.Position <- new SCNVector3 (0.0F, 0.0F, 3.0F)


        // Action!
        let animation = new CABasicAnimation(
            KeyPath = "rotation"
        )
        let t = new SCNVector4 (1.0F, 1.0F, 0.0F, float32 (Math.PI * 2.0))
        animation.To <- NSValue.FromVector (t)

        animation.Duration <- float 5.0F
        animation.RepeatCount <- float32 Double.MaxValue //repeat forever
        boxNode.AddAnimation(animation,new NSString("rotation"))

        let scnView = new SCNView(UIScreen.MainScreen.Bounds)
        scnView.Scene <- scene
        scnView.AllowsCameraControl <- true
        scnView.ShowsStatistics <- true
        scnView.BackgroundColor <- UIColor.Black

        this.View <- scnView
       

[<Register ("AppDelegate")>]
type AppDelegate () =
    inherit UIApplicationDelegate ()

    // This method is invoked when the application is ready to run.
    override this.FinishedLaunching (app, options) =
        let window = new UIWindow (UIScreen.MainScreen.Bounds)
        window.RootViewController <- new MySceneKitController()
        window.MakeKeyAndVisible ()
        true

module Main =
    [<EntryPoint>]
    let main args =
        UIApplication.Main (args, null, "AppDelegate")
        0

IMG_0272

photo

50 PRINT “HAPPY BIRTHDAY”

I think BASIC’s greatest strength may be that it was something that many people — not just those with a particular background — could learn. There was no gatekeeper, either literally or figuratively: you didn’t have to push punchcards under a bank-teller window nor did you have to learn recursion before learning recursion. In the 80s, virtually every machine ran BASIC and learning how to login and start the interpreter was generally the hardest part of beginning to “program an X machine.”

People get drop-through imperative programming: either the line-by-line flexibility of BASIC or the blocks of FORTRAN and Flash (I didn’t understand Flash until I realized that it’s just FORTRAN with worse numerics and better graphics). You don’t have to be a born programmer to understand:

 10 PRINT "HELP! I AM CAUGHT IN A PROGRAM LOOP!"
 20 GOTO 10

I imagine that 95% of the people who got a passing grade in their BASIC programming class or typed in a few games from the back of COMPUTE! magazine never wrote themselves another program. But the 5% who did found that personal computers could help them in their job. And the 1-in-100 or 1-in-1000 who went beyond that found themselves in a community where only drive and talent mattered and credentials meant nothing.

I’m a college dropout and never took a CS course in my life. At 25 I was hired as Technical Editor for a magazine that specialized in Artificial Intelligence and for Computer Language, the best programming magazine of all time (as far as size or circulation goes, we were the “We Try Harder” Avis to Dr. Dobb’s Journal‘s Hertz).

Today, the design of programming languages is discussed at sites like Lambda the Ultimate and while I can muddle through even some of the more arcane papers, and while I understand the value of a dense, high signal-to-noise ratio on certain topics, it seems to me that there’s not nearly enough reflection on the market triumphs of popular languages. I’m not advocating a return to the line-numbered BASIC interpreters (single-threaded, as if that had to be mentioned!) of my youth, but I am saying that 50 years ago, Kemeny, Kurtz, and colleagues captured lightning in a bottle. So did Dan Bricklin, inventor of the computerized spreadsheet, another tool for manipulating data and calculations that empowered an audience vastly larger than that emerging from the bottleneck of “Computer Science courses at good universities.”

I’m not suggesting that marketshare is the only, or even dominant, factor in assessing a language’s quality. In the case of JavaScript, for instance, I see an example of the contingent nature of history, as discussed in Steven Jay Gould’s classic Wonderful Life. JavaScript is a market triumph, it behooves all professional programmers to master it, but I think it’s fair to say that it has some flaws as a programming language.

Nor am I saying that there’s not a lot of discussion of “beginner’s languages.” I volunteer at a local school and am tremendously impressed by Scratch, for instance. Because Scratch is accessible at such a young age, it may generate the same kind of nostalgia that some of us share for BASIC. But I don’t suspect that it will have the truly broad, industry-expanding impact of BASIC or Flash.

Today, there’s some talk of functional programming sweeping over the industry in the same way that object-orientation did in the early 1990s. I am not a functional programming True Believer, but I truly believe that functional programming has advantages. And it seems to me that languages such as F# on the CLR and Scala on the JVM have a “you can have it all” aspect (no-hassle availability of libraries, the ability to integrate with legacy code, object-functional hybrid type-systems) that at the very least make them appealing to some teams.

But, although perhaps not as broadly accessible as line numbers and GOTO, OOP has something of BASIC’s “learnability.” We can teach OOP to a lot of people, without a lot of preliminaries. And some will struggle through, and some will have a comfortable understanding, and some will have taken a step towards design and architecting large systems. With Functional Programming, it’s not as clear to me that there’s that same “muddle through” path. It’s hard for me to imagine a better introduction to functional ideas than the early chapters of Structure and Interpretation of Computer Programs, but I think of that as a text that weeds out, not one that expands the base. If you’re a natural-born programmer with a semester in front of you SICP is a great book. But if you “just” have potential or are a working developer with a “where does this help my day-to-day problems?” pragmatism, I don’t know what you should read.

Goto 10

BASIC was the first programming language for most of those in my generation. We sat in front of green- and amber-texted monitors or machines that spooled seemingly infinite reams of paper. We typed on chiclet keys and teletypes, punched papertape and cards and threaded magnetic reels. Compared to today’s machines we had indistinguishable-from-0 working memory or horsepower.

You have no idea how fun it was.

Reviewing Values for iOS UIViewContentMode with Xamarin and F#

Who can remember the scaling behavior of UIView.ContentMode? Not me!

So I wrote this quick little F# program to review them:

    namespace Simple
     
    open System
    open MonoTouch.UIKit
    open MonoTouch.Foundation
    open System.Drawing
     
    type ContentView ( color : UIColor ) as self = 
        inherit UIView ()
        do
            self.BackgroundColor < - color

    type ContentModeModel  () = 
         inherit UIPickerViewModel ()

         let T = typedefof<UIViewContentMode>

         let selectionChanged = Event<_>()

         member this.SelectionChanged = selectionChanged.Publish 

         override this.GetRowsInComponent(_, _) = Enum.GetNames(T).Length
           
         override this.GetTitle(_, row : int, _) = Enum.GetName(T, row)

         override this.GetComponentCount(_) = 1

         override this.Selected(_, row : int, _) = selectionChanged.Trigger(enum<UIViewContentMode>(row))
       
     
    type SimpleController ( ) =
        inherit UIViewController ()
     
        override this.ViewDidLoad () = 
            this.View < - new ContentView(UIColor.Blue)

            let imgView = new UIImageView(new RectangleF(20.0F, 80.0F, UIScreen.MainScreen.Bounds.Width - 40.0F, 100.0F))
            imgView.Image <- UIImage.FromFile("flower.png")
            imgView.ClipsToBounds <- true
            this.View.AddSubview(imgView)

            let picker = new UIPickerView(new RectangleF(20.0F, UIScreen.MainScreen.Bounds.Height - 180.0F, 250.0F, 140.0F))
            let model = new ContentModeModel()
            picker.Model <- model 

            model.SelectionChanged.Add <| fun newMode -> imgView.ContentMode < - newMode

            this.View.AddSubview(picker)
     
    [<Register ("AppDelegate")>]
    type AppDelegate () =
        inherit UIApplicationDelegate ()
     
        let window = new UIWindow (UIScreen.MainScreen.Bounds)
     
        // This method is invoked when the application is ready to run.
        override this.FinishedLaunching (app, options) =
            let viewController = new SimpleController()
            window.RootViewController < - viewController
            window.MakeKeyAndVisible ()
            true
     
    module Main =
        [<EntryPoint>]
        let main args =
            UIApplication.Main (args, null, "AppDelegate")
            0

No real interesting techniques, but another nice quick iOS app in Xamarin using F#.

contentview

Review of my Xamarin F# Event Code Leads To Improvements

Not at all surprisingly, it turns out that F# events need not be the crufty structures I showed in my previous post.

First, Xamarin‘s David Siegel suggested “Let the Event type be inferred, don’t define a delegate type, and send simple typed values rather than EventArgs:”


open System

type Control() =
let hello = Event<_>()

member this.Hello = hello.Publish
member this.Speak() = hello.Trigger "yo!"

let control = Control()

control.Hello.Add < | fun msg ->
printfn "Received '%s'" msg

control.Speak()

While Ryan Riley suggested a step further down the reactive line:

To remain consistent with your pipe forwards when using events, you can use the Observable module:
do myItem.FooEvent |> Observable.add (fun o args -> …)
or even
let disposable = myItem.FooEvent |> Observable.subscribe (fun o args -> …)
You can also expose an event as an IObservable rather than as an event if you like:
FooEvent.Publish :> IObservable


I also learned from @kemnet that List.choose id is the idiomatic way to transform a List<option> into a List of Some values.