VSLab update and measure units sample

by cisterni 30. October 2008 23:29

Ok, it is some time since the last update of VSLab, but today I decided to update the installer and commit several changes I did to improve stability and support for events. I finally managed to go through the whole Viewlet definition and fully document supported and unsupported events inherited from UserControl. I also managed to fix several bugs in this respect.

 This is term period and in the Graphical interfaces courses I'm teaching using F# (interactively). Today to discuss animations I've implemented a simple application with balls moving around and quickly converted into a viewlet! The nice thing about this application is the use of unit measures in a graphical application to estimate velocity (<px/s>). Once you run the viewlet you can create a new ball by simply clicking in the client area and drag the initial velocity vector. Here is a screenshot:


and here it is the code:


open System.Drawing

open System.Windows.Forms [<Measure>] type px

[<Measure>] type s

open VSLab

let ballsz = new SizeF(25.0f, 25.0f)

type Ball(ipx: float<px>, ipy:float<px>, ivx:float<px/s>, ivy:float<px/s>) =

  let mutable vx = ivx

  let mutable vy = ivy

  let mutable px = ipx

  let mutable py = ipy

  let sz = ballsz

  member x.Update(interval:float<s>) =

    px <- px + vx * interval

    py <- py + vy * interval

  member x.Size

    with get() = sz

  member x.Position     with get() = (px, py)


  member x.CenterPosition

    with get() = ((px + 1.0<px> * (float (sz.Width / 2.0f))), (py + 1.0<px> * (float (sz.Height / 2.0f))))


  member x.Velocity

    with get() = (vx, vy)

    and set (v:float<px/s>*float<px/s>) =

      vx <- fst v

      vy <- snd v

type SampleViewlet() as x =

  inherit Viewlet()

  let balls = new ResizeArray<Ball>()

  let framerate = 0.02<s>

  let t = new Timer()

  let mutable newball:Option<Ball> = None

  let mutable mousepos = (0, 0)



    t.Interval <- int(framerate * 1000.0)

    t.Tick.Add(fun _ ->

    balls |> ResizeArray.iter (fun b ->


      let px, py = b.Position

      let pxi = (int px)

      let pyi = (int py)      let mutable vx, vy = b.Velocity


      if (pxi < 0 || pxi > x.ClientSize.Width - (int b.Size.Width)) then

        vx <- vx * -1.0

      if (pyi < 0 || pyi > x.ClientSize.Height - (int b.Size.Height)) then

        vy <- vy * -1.0


      b.Velocity <- (vx, vy)






    x.Text <- "Animate!"

  override x.OnMouseDown e =

    mousepos <- (e.X, e.Y)

    let px = 1.0<px>*((float e.X) - ((float ballsz.Width) / 2.0))

    let py = 1.0<px>*((float e.Y) - ((float ballsz.Height) / 2.0))

    let b = new Ball(px, py, 0.0<px/s>, 0.0<px/s>)


    newball <- Some(b)

  override x.OnMouseMove e =

    if newball.IsSome then

      mousepos <- (e.X, e.Y)

  override x.OnMouseUp e =

    if newball.IsSome then

      let px, py = newball.Value.Position

      let vx = (float (fst mousepos - (int px)))*1.0<px/s>

      let vy = (float (snd mousepos - (int py)))*1.0<px/s>

      newball.Value.Velocity <- (vx, vy)

      newball <- None

  override x.OnPaint e =    let g = e.Graphics

    g.SmoothingMode <- Drawing2D.SmoothingMode.AntiAlias

    balls |> ResizeArray.iter (fun b ->

    let px, py = b.Position

    g.FillEllipse(Brushes.Blue, (single px), (single py), ballsz.Width, ballsz.Height))

    if newball.IsSome then

      let px, py = newball.Value.CenterPosition

      let ipx = (int px)

      let ipy = (int py)

      let mx, my = mousepos

      use p = new Pen(Color.Black)

      p.EndCap <- Drawing2D.LineCap.ArrowAnchor

      g.DrawLine(p, ipx, ipy, mx, my)


  override x.OnViewletVisibilityChange e =

  t.Enabled <- e

let v = new SampleViewlet()



Currently rated 2.3 by 15 people

  • Currently 2.266667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5


General | Viewlets

Powered by BlogEngine.NET
Theme by Mads Kristensen

VSLab blog

VSLab is a Visual Studio extension designed to support Visual Studio interaction from F# interactive. It is a Microsoft product developed at University of Pisa, by a team lead by Antonio Cisternino.


Recent comments

Comment RSS


The opinions expressed herein are my own personal opinions and do not represent my employer's view in  anyway.

© Copyright 2008