Next VSLab release upcoming

by cisterni 19. January 2009 22:51

Ok, we are close to a new release of VSLab. It will contain two major changes that are very very important. The first one is, as far as I know, the first implementation of Lightweight Controls for Windows Forms, made available for programming viewlets with ease but also available to all .NET applications. Wonder why are Lightweight Controls so important? Let's start with an example in C#:

    public partial class Form1 : Form    {

        public Form1()        {

            InitializeComponent();

            var lc = new LightweightContainer();

            var lb = new LightweightButton();

            var rb = new RoundButton();

            var rb2 = new RoundButton();

            lc.Dock = DockStyle.Fill;

            lb.Position = new Point(0, 0);

            lb.Text = "Hello World";

            lc.BackColor = Color.AliceBlue;

            lc.Add(lb);

            rb.Position = new Point(0, 100);

            rb.Size = new Size(50, 50);

            rb.Text = "Hello with very long text";

            lc.Add(rb);

            rb2.Position = new Point(0, 110);

            rb2.Size = new Size(50, 50);

            rb2.Text = "Hello 2";

            lc.Add(rb2);

            this.Controls.Add(lc);

        }

    }

This is a simple code meant for creating three buttons into a canvas. The LightweightContainer class is a sort of panel capable of hosting lightweight controls (classes derived from LightweightControl). The library features a number of predefined controls such as buttons (in Vista style) and scrollbars. In the example the lb variable holds an instance of a LightweightButton. The lightweight control container is docked within the form. The other two buttons are instances of RoundButton class which is a simple example of how to write a lightweight control:

    public class RoundButton : LightweightControl    {

        public string Text = "";

         public override void OnMouseMove(MouseEventArgs e)        {

            base.OnMouseMove(e);

            BackColor = Color.Red;

            Invalidate();

        }

        public override void OnClick(EventArgs e)        {

            base.OnClick(e);

            Position = new Point(Position.X, Position.Y + 10);

            Invalidate();

        }

         public override void OnPaint(PaintEventArgs e)        {

            var g = e.Graphics;

            using (var b = new SolidBrush(Color.FromArgb(40, BackColor)))            {

                g.FillEllipse(b, e.ClipRectangle);

                g.DrawEllipse(Pens.Black, e.ClipRectangle);

                var sf = new StringFormat();

                sf.Alignment = StringAlignment.Center;

                sf.LineAlignment = StringAlignment.Center;

                g.DrawString(Text, Font, Brushes.Black, new RectangleF(e.ClipRectangle.X, e.ClipRectangle.Y, e.ClipRectangle.Width, e.ClipRectangle.Height), sf);

            }

        }

    }

 The RoundButton is written as a standard UserControl except for the fact that it inherits from LightweightControl (and that not all the features of UserControl are available). The output is shown in the following picture: 

Here is a more complete screenshot of one of our regression tests running inside VSLab:

Lightweight controls are important for viewlets because it is not possible using the standard controls, therefore having user control abstractions makes viewlet development a lot easier. One of the example is the addition of a button over the Chart and the 3D Chart viewlets as shown in this screenshot:

The other important update in this new release is the implementation of double buffering for Viewlets (the Chart viewlet sample does not flicker anymore once enabled) which has been challenging to implement because of the internals of VSLab. The overall code has been cleaned up and reviewed in order to offer a more consistent programming API.

Now we are getting back to the original ideas of featuring new viewlets for data visualization and system shell replacement. In the meantime we are using VSLab in projects involving biomedical engineers.

Currently rated 5.0 by 1 people

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

Tags: ,

General | Shell | Viewlets

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:

#light

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)

 

  do

    t.Interval <- int(framerate * 1000.0)

    t.Tick.Add(fun _ ->

    balls |> ResizeArray.iter (fun b ->

      b.Update(framerate)

      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.Invalidate()

    )

    t.Start()

    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>)

    balls.Add(b)

    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()

v.Show()

v.Close()

Currently rated 5.0 by 2 people

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

Tags:

General | Viewlets

VSLab Regression tests and doc

by cisterni 28. September 2008 18:30

I've just added a project for regression tests in VSLab. It is also interesting because it shows very simple viewlets doing simple things and it can also be a good way to learn Viewlet development. So far there are two viewlets checking mouse move and resize events. Here is the code:

#light

open System.Drawing

open VSLab

type ShowStringViewlet() =  inherit Viewlet()

 

  [<DefaultValue>]

  val mutable displayString : string

 

  override self.OnPaint(e) =     let g = e.Graphics

    g.DrawString(self.displayString, self.Font, Brushes.Black, 0.0f, 0.0f)

 

type
MouseMotionViewlet() as x =  inherit ShowStringViewlet()

 

  do x.displayString <- "Move the mouse inside the area"

 

  override self.OnMouseMove(e) =     self.displayString <- sprintf "x: %d, y: %d" (e.X) (e.Y)

    self.Invalidate(new Rectangle(0, 0, 200, 50))

let mmv = new MouseMotionViewlet()

mmv.Show()

mmv.Close()

 

type
ResizeViewlet() as x =  inherit ShowStringViewlet()

 

  do x.displayString <- "Resize the viewlet"

 

  override x.OnSizeChanged (e) =

    x.displayString <- sprintf "Size is (%d, %d)" (x.Width) (x.Height)

let rv = new ResizeViewlet()

rv.Show()

rv.Close()

 

 I hope this can be useful.

Be the first to rate this post

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

Tags: , ,

General | Viewlets

Powered by BlogEngine.NET 1.4.0.0
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.

Resources

Recent comments

Comment RSS

Disclaimer

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

© Copyright 2008