I was working on BASeBlock’s splash screen a bit, and thought it would be neat to have a little animation to expand and contract the list of loaded assemblies. I suddenly found myself wanting something similar to JQuery.
It didn’t seem inexorably difficult; so I got to work. Soon I had a simple little class that could move and size a object.
But that wasn’t enough. it wasn’t flexible enough- what if I wanted to animate, say, the background color, too? So I created a new project- BCQuery. The purpose is to provide a simple control animation framework; I came to realize that even restricting it to just controls could be limiting, so it really accepts any object at all.
The design is based around a simple threading model. Obviously, all UI actions (such as moving or interacting with Windows Forms controls) need to occur on the main application thread. Thankfully, Control’s expose a “Invoke” and “BeginInvoke” method that can be used to run code on that thread while closing over local variables, which is immensely useful.
This runner thread is only active while things are animating. When an animation is added and there is no thread running, it starts it; otherwise, when the last animation completes, the Thread removes itself. The interesting part is that it only uses one extra thread- All animations are performed concurrently here, with extra operations being queued up for execution in that thread before the iteration runs. One of the main concerns here is with the use of a foreach to iterate through and update each animation; since the animation can easily complete and there is no way to directly remove the instance from the collection without the next iteration of the foreach throwing an InvalidOperationException because the collection was changed. Code that needs or wants to remove or otherwise modify that collection can now do so by simply queuing up a piece of code to run the next time through the main animation loop.
I rather like how the project has come so far; I have it so I now need only two lines of code in a form to set up a basic “expando” whereby one control expands and the expander control moves. Given the amount of effort in dealing with what is essentially a finite state machine otherwise, this is extremely helpful IMO. Currently I have “easers” that can work with Size, Point, float, and int property’s, but it isn’t too much trouble to add more; the Point and Size versions use a corresponding easer of the appropriate type; for example, there is a PointFEaser, which uses two FloatEaser’s to ease the X and Y coordinates. This could be useful if I create custom float easers later on to support say… easing. (Though that is far from easy.
It works a treat, and will definitely be the subject of a future blog post.
It’s worth mention that this sort of library would be valueless for, say, WPF. This functionality is far better provided by WPF Storyboards via the Windows XAML rather than using something like this. But you can’t always use WPF, or don’t want to make something “heavy” that uses WPF, but might want some interesting animations like those you might need a simple storyboard for without writing too much code; and that’s what this library will be for.
EDIT: It didn’t exactly come to me quickly, but it did only take one debug run (I accidentally swapped two parameters because I named them poorly) before I had it working; considering it uses reflection to change members and properties on the fly, it works quite well. Definitely a class library to be expected with new releases of most of my projects, and of course available standalone.
Have something to say about this post? Comment!