Gotta Digg

Never used Digg.com but I’ve had this simple tune in my head since the following a link to it from techAU’s blog last night. Not even sure whether SuperBowl is baseball or grid-iron – but I love the marketing power of the Internet that have been used to promote this. Even more so since the Gotta Digg song is only being used in the campaign – its not even the actual song she’s submitted for the competition.

WinForms Animation (part 2)

A small update to this previous post on doing very simply animations in WinForms. Having a base class to represent individual graphic elements, then using the built in Transforms (rotate, scale, translate) to individually paint each element works pretty well. However, there are a couple of issues with this approach.

The first issue becomes apparent when some level of interaction is required with the graphic elements. For example, the ability to select one using the mouse. In the previous example the individual elements never know their transformed location themselves, therefore they can’t perform their own hit-testing. Its a shame there isn’t some way to have the transforms applied in reverse – to convert a form co-ordinate into a local point. The simple solution to this that I opted for with PhotoPlay was to simply perform my own translations.

First step was to add a property called TransformedBounds to the base class that translates the element’s local bounds to world co-ordinates using some good old fashioned trig. (Angle), multiplication (Scale) and addition (Centre). Also an overridable implementation of a HitTest. The base implementation caters for polygons (e.g. rectangles, triangles, stars) but an override is required for more complex shapes – particularly those with curves.

    public class InteractiveDrawingElement : DrawingElement
    {
        private bool isHot;

        /// <summary>
        /// Gets or sets whether the element is “hot” – normally this is when the cursor is located over the element.
        /// </summary>
        public bool IsHot
        {
            get { return isHot; }
            set { isHot = value; }
        }

        /// <summary>
        /// Determines whether the supplied<paramref name=”hitPoint”/> is contained within the
        /// element.
        /// </summary>
        /// <param name=”hitPoint”>The point to be tested.</param>
        /// <returns><see langword=”true”/> if<paramref name=”hitPoint”/> is considered to be a “hit”
        /// on the drawing element,<see langword=”false”/> otherwise.</returns>
        public virtual bool HitTest(Point hitPoint)
        {
            return DrawingSupport.PolygonContains(TransformedVertices, hitPoint);
        }
    }

The second issue is allowing for parts of the element rendering to ignore aspects of the transformation. The obvious example of this is not wanting to scale things like anchors/handles. This can be handled via an OnRawPaint method that I call before transformation occurs but it means that any portion of the transform that you do want (e.g. rotation) must now be manually coded. The second example I had was rendering a shadow on a photo. Initially I just painted a dark semi-transparent rectangle behind the photo frame. But rotating the frame also caused the shadow to rotate, meaning that if an image is rotate 180 degrees its shadow is now offset to the top right instead of the bottom left. That doesn’t make a lot of sense since shadows should also be offset for all objects in a consistent direction regardless of their rotation. This required a dirty hack to fix and I didn’t bother catering for it in the base class.

The updated source code for the WinForms Transitions is here. A ClickOnce online only example is here.

Ok – so enough WinForms and rants (the monitor arrived on the weekend ) – back to WPF.