Phillip Trelford's Array

POKE 36879,255

Generative Art

Last night I ran a free hands on Generative Art session to a full class room at Skills Matter for the F#unctional Londoners meetup group. We host a hands on programming sessions every month, next month we’ll return to the Machine Learning theme with Matt Moloney from the Tsunami IDE team.


Samples: http://trelford.com/GenerativeArt.zip

I recently picked up Matt Pearson’s Generative Art book published by Manning, his examples use the Processing programming language which is loosely based on Java. For the hands on creative part we used F# and the SmallSharp library which has a similar feel but is limited to 2D.

SmallSharp

SmallSharp is a small .Net library for drawing graphics, similar to Small Basic but aimed more at the "Sharp" languages C# and F#

Small Basic the good parts:

  • minimal IDE: you get intellisense, buttons for opening and saving files and a big run button (F5)
  • simple library: type GraphicsWindow and dot to start drawing shapes, no need worry about Single Threaded Apartments, data binding or XAML
SmallBasic

Small Basic’s library is just about usable from C# and F# but relies on strings and implicit conversions to a variant type, where as SmallSharp’s API takes explicit typed arguments.

In F# with SmallSharp we can write:

GraphicsWindow.BrushColor <- red
for i in 0..5..200 do
    GraphicsWindow.DrawLine(i,0,200-i,200)
    GraphicsWindow.DrawLine(0,i,200,200-i)

 

Which draws concentric lines:

Pattern

Bubbles

I found a nice piece on Deviant Art entitled Bubbles:

colorful_bubbles_by_basil4life-d6i06vv

The task was to generate a similar work, starting with the following code:

Win.Background <- black
let rand = System.Random()
let colors = [red; green; blue; yellow]
for i = 1 to 200 do
    Win.Opacity <- rand.NextDouble() ** 3.0
    Win.FillColor <- colors.[rand.Next(colors.Length)]
    let x = rand.NextDouble() * Win.Width
    let y = rand.NextDouble() * Win.Height
    let r = 10.0 + rand.NextDouble() * 30.0
    Win.DrawEllipse(x-r,y-r,r*2.0,r*2.0)

Here’s a monochrome from David Kowalski:

Monochrome

and an interesting Spiral effect from Rob Lyndon:

Spiral Galaxy

FunScript

Following Atwood's Law:

any application that can be written in JavaScript, will eventually be written in JavaScript.

I created the same effect using the HTML5 Canvas, with the F# code being compiled to JavaScript by the FunScript library, which also gives typed access to JavaScript libraries.

[<ReflectedDefinition>]
module Program

open FunScript
open FunScript.TypeScript

type ts = Api<"../Typings/lib.d.ts">

let circle (ctx:ts.CanvasRenderingContext2D) (x,y,d,c) =
   let pi = ts.Math.PI
   ctx.beginPath()
   ctx.arc(x, y, d, 0.0, pi * 2.0)
   ctx.fillStyle <- c
   ctx.fill()   

let inline str x = x.ToString()
let rgba (r,g,b) a = "rgba("+str r+","+str g+","+str b+","+str a+")";
let next n = ts.Math.random() * n
let from n = ts.Math.floor(next (float n)) |> int

let main() =
   let canvas = unbox<ts.HTMLCanvasElement>(ts.document.getElementById("canvas"))
   canvas.width <- 1000.
   canvas.height <- 500.
   let ctx = canvas.getContext("2d")
   // Set background
   ctx.fillStyle <- "rgb(0,0,0)"
   ctx.fillRect (0., 0., canvas.width, canvas.height);
   /// Circle colors
   let colors = [
      255,0,0
      0,255,0
      0,0,255
      255,255,0
      ]
   // Draw circles
   for i = 1 to 200 do
      let x = next canvas.width
      let y = next canvas.height
      let r = 10. + next 40.
      let a = next 1.
      let c = rgba (colors.[from colors.Length]) a
      circle ctx (x, y, r, c)

Circles


Turing Drawings

We finished up on drawing roulette with Turing drawings, made by random Turing machines:

DrawingRoulette

I created an F# version a few weeks back which you can run in the Cloud Tsunami IDE.

Have fun!

Random Walker

This week our automated tools uncovered a fatal exception before it reached the client. Nick and Anton, 2 of the full-time testers on our team have written a testing tool they call Random Walker that simulates interactions with the user interface as clicks and gestures. It has helped uncover numerous issues, particularly NullReferenceExceptions, more often than not emanating from third-party libraries. It typically finds issues that are not easily found by manual testing or our extensive suite of unit and integration tests. Up-time is very important to us and our large client base who interact with our software throughout the day. 

Stack Trace

System.InvalidOperationException: GridViewColumnCollection is read-only now.
 at System.Windows.Controls.GridViewColumnCollection.VerifyAccess()
 at System.Windows.Controls.GridViewColumnCollection.RemoveItem(Int32 index)

Documentation

The exception is thrown after calling RemoveItem method of GridViewColumnCollection, although the MSDN documentation does not specify an exception is expected.

Disassembly

Using a disassembler we can see VerifyAccess will throw if the IsImmutable property is true:

private void VerifyAccess()
{
    if (this.IsImmutable)
    {
        throw new InvalidOperationException(
                      SR.Get("ListView_GridViewColumnCollectionIsReadOnly"));
    }
    base.CheckReentrancy();
}

 

The next question is when does this property get set to true. Using Telerik’s JustDecompile you can right click the property and select Find Usages, which shows its set from methods BlockWrite and UnblockWrite.

BlockWrite is called by the GridViewHeaderRowPresenter.StartHeaderDrag private method.

UnblockWrite is called by GridVIewHeaderRowPresenter.FinishHeaderDrag.

StartHeaderDrag is called from the MouseMove handler.

FinishHeadDrag is called from OnMouseLeftButtonUp, OnLostMouseCapture and OnColumnsPresenterKeyDown.

Problem

There appears to be an undocumented assumption that the columns can not be updated either during or on completion of a drag operation. However our front end lets you add or remove columns from a table via a separate menu, so it is possible for an update operation to come from outside the drag gesture.

Workaround

One workaround is to pre-empt the call to VerifyAccess by checking the IsImmutable property as it is possible to invoke private methods via refection:

bool IsImmutable()
{
    var flags = BindingFlags.Instance || BindingFlags.NonPublic;
    var property = columns.GetType().GetProperty("IsImmutable");
    return (bool)property.GetValue(columns, new object[] {});
}

 

Closing Thoughts

The Random Walker UI testing tool has really helped flush out those hard to find issues, if up-time is important to your customers, you may want to consider using one. Bugs exist even in mature frameworks like WPF, and you may need to set aside some time to working around them. Encapsulation seems good in theory, but I’m thankful that we can disassemble the source of third-party libraries and dynamically invoke private members when necessary.

Silverlight 5 Native Popup Windows

A popup is a window without a standard border that pops up above other controls to display contextual information like a tooltip, context menu or validation error. Silverlight’s browser heritage means it’s built-in popups may appear clipped inside their parent window.

Silverlight Validation Warning Clipped

When running on the desktop, as an out-of-browser full-trust application, it would be nice to have popups that appear outside of their parent window, as they do in WPF and WinForms,

Borderless

Silverlight 5’s native window support makes it possible to create popups that can break free of their parent window in out-of-browser applications. The main requirement for creating a native popup window is to be able to create a borderless window. A Silverlight Window can be made borderless simply by setting it’s WindowStyle property to None:

new Window
{
    Title = "Popup",
    WindowStyle = WindowStyle.None,
    TopMost = true,
    Visibility = Visibility.Collapsed
};

Note: set the Window’s width & height after you’ve set the style, otherwise it will appear with additional area to accommodate it’s no longer visible chrome.

Position

The absolute position of the popup can be set via the popup window’s Top and Left properties. To place the popup relative to a point in a parent window simply offset by the parent window’s Top and Left properties.

Example: Showing a Context Menu popup window on a right mouse button click:

private void MouseRightButtonUp(object sender, MouseButtonEventArgs e)
{
    var parent = Window.GetWindow((DependencyObject) sender);
    var position = e.GetPosition(null);
    var popup =
        new Window
        {
            WindowStyle = WindowStyle.None,
            TopMost = true,
            Top = parent.Top + position.Y,
            Left = parent.Left + position.X,
        };
}

Chrome

If the parent window has chrome then the absolute position should be offset by this too:

int chromeWidth = 0;
int chromeHeight = 0;
var style =
    window == Application.Current.MainWindow
    ? Deployment.Current.OutOfBrowserSettings.WindowSettings.WindowStyle
    : window.WindowStyle;
if (style == WindowStyle.SingleBorderWindow)
{
    chromeWidth = 10;
    chromeHeight = 32;
}

Note: getting the WindowStyle property of the main window throws a NotImplementedException exception. To workaround this the WindowStyle property of WindowSettings can be used instead if the parent window is the main window.

Target

WPF’s Popup control provides a PlacementTarget property which specifies:

the element relative to which the Popup is positioned when it opens

This can be useful for positioning tool tips or validation errors

Position

The TransformToVisual method can be used to get the position of an element in a window:

var window = Window.GetWindow(PlacementTarget);
var transform = PlacementTarget.TransformToVisual(window.Content);
var position = transform.Transform(new Point(0, 0));

The position of the popup can be offset using a HorizontalOffset and VerticalOffset.

Placement

The Placement property specifies the mode of the popup:

public enum PlacementMode
{
    Absolute,
    Relative,
    Top, 
    Left, 
    Bottom, 
    Right
}

Orientating the popup based on the placement mode:

private Point GetPlacementPosition()
{
    switch (Placement)
    {
        case PlacementMode.Absolute:
            return new Point(HorizontalOffset, VerticalOffset);
        case PlacementMode.Relative:
            return GetRelativePosition(0, 0);
        case PlacementMode.Top:
            return GetRelativePosition(0, -this.Height);
        case PlacementMode.Bottom:
            return GetRelativePosition(0, PlacementTarget.ActualHeight);
        case PlacementMode.Left:
            return GetRelativePosition(-this.Width, 0);
        case PlacementMode.Right:
            return GetRelativePosition(PlacementTarget.ActualWidth, 0);
        default:
            throw new InvalidOperationException();
    }
}

Note: the PlacementTarget’s ActualWidth and ActualHeight properties are useful here.

Monitors

Just as a Silverlight in-browser popup can be clipped inside a window, an out-of-browser window can be clipped inside the display monitor. Using P/Invoke it is easy to find monitor information from the MonitorFromPoint and GetMonitorInfo Win32 functions.

private void PlaceWindowWithinDisplay(Point point)
{
    var monitor = DisplayMonitors.GetMonitorInfoFromPoint(point);
    if (point.Y < monitor.WorkArea.Top)
        point.Y = monitor.WorkArea.Top;
    if (point.Y + this.Height > monitor.WorkArea.Bottom)
        point.Y = monitor.WorkArea.Bottom - this.Height;
    if (point.X < monitor.WorkArea.Left)
        point.X = monitor.WorkArea.Left;
    if (point.X + this.Width > monitor.WorkArea.Right)
        point.X = monitor.WorkArea.Right - this.Width;
    _window.Top = point.Y;
    _window.Left = point.X;
}

TaskBar

Popup windows should not typically be visible in the TaskBar. To remove a window from the task bar it’s extended style needs to be set to WS_EX_NOACTIVATE:

internal static void RemoveFromTaskBar(IntPtr hwnd)
{
    SetWindowLong(hwnd, GWL_EXSTYLE, (int)WS_EX_NOACTIVATE);
}

Again this can be achieved easily with P/Invoke, full details are available in this post:

Focus

WPF’s Popup provides a useful StaysOpen property which defaults to true and indicates:

whether the Popup control closes when the control is no longer in focus

Again this is easy to emulate by handling the GotFocus event on the popup’s parent window.

var window = Window.GetWindow(PlacementTarget);
window.Content.GotFocus += TargetWindowGotFocus;

Source

A full implementation of native Popup windows for Silverlight is available in the CodePlex Open Source project:

It also includes a Context Menu that works as a Popup:

ContextMenu_SL5_Native