Thursday, May 26, 2011

There and back again: A Cursor's tale

I've been working on UI code recently and have run into this quite a bit:
Cursor = Cursors.Wait;
SomeLongRunningTask();
Cursor = Cursors.Default;
Pretty straight forward code. I see this type of thing a lot, not just in the C# code I'm working on now, but I've seen this in the past. In other languages. On other platforms. It's a common practice. The problem is it only works in some cases.

This will have problems if any method in the "long running task" does the same thing. The cursor will be set back to default prematurely. Of course, this is easily solved by saving the old value prior to setting the new one.
var oldCursor = Cursor;
Cursor = Cursors.Wait;
SomeLongRunningTask();
Cursor = oldCursor;
This is an improvement but will still fail if an exception is raised. This can be fixed with a try/finally.
var oldCursor = Cursor;
Cursor = Cursors.Wait;
try
{
    SomeLongRunningTask();
}
finally            
{
    Cursor = oldCursor;
}
Ok. So now we have some code that works reasonably well. The issue now is one of code maintainability and clarity. Every method that needs to change the cursor needs to add nine lines before it can do any work of its own. It's nine lines where bugs could hide. It's nine lines obscuring the real purpose of the method. There's got to be a better way.

Way back in my Delphi days, I had a small class which handled this chore for me. The constructor took a parameter containing the new cursor. The current cursor was saved in a class field, the cursor was changed and the constructor finished. The destructor simply set the cursor back to the saved value. In that environment, interfaces were reference counted and destroyed when the reference went to zero. The compiler took care of all the bookkeeping automatically. So I could create an instance of this class, store it in a local variable and, when the variable went out of scope, the object was destroyed, resetting the cursor. It worked really well. One line to change the cursor to whatever I wanted and it automatically reset to the original value when done. Pretty sweet.

Unfortunately, C# does not have any deterministic way of handling object lifetimes. This is one of my biggest frustrations with the language. The closest thing we have is the hack that is the using statement. Since this is the best we have, I have put together a class, shown below, similar to the one I had before. The constructor takes the new cursor value and control whose cursor should be changed, saves the current one and, in the Dispose method, resets it back. Now we can have three simple lines with one code block rather than the nine lines with two blocks. It's a big improvement although still not the single line like I'd prefer.

In use, it looks like this:
using ChangeCursor(this, Cursors.Wait)
{
    SomeLongRunningTask();
}
Arguably, this is a bit cleaner than even the first code snippet we started with.

Since this takes a FrameworkElement, it's WPF specific. It'd be easy enough to change the type to work with WinForms, if needed. The same technique could be used to handle other things where a state needs to be set to one value and then reset when some unit of work is done. For example, if using TreeViews with BeginUpdate/EndUpdate pairs.

Hope this helps someone.
using System;
using System.Windows;
using System.Windows.Input;

namespace CursorResourceProtection
{
    public class ChangeCursor : IDisposable
    {
        private FrameworkElement Context { get; set; }
        private bool Disposed { get; set; }
        private Cursor OriginalCursor { get; set; }

        public ChangeCursor(FrameworkElement context, Cursor newCursor)
        {
            Disposed = false;
            Context = context;
            OriginalCursor = context.Cursor;
            context.Cursor = newCursor;
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            if(Disposed)
                return;

            Context.Cursor = OriginalCursor;
            Disposed = true;
        }

        ~ChangeCursor()
        {
            Dispose(false);
        }
    }
}

Wednesday, May 11, 2011

Non-int array indexes from Delphi in C#

In Delphi, array indexes can be any type that resolves to an integer, not just integers. So for example, enum and bool types can be array indexes. This can be handy in many situations to reduce a if-then or switch construct to a simple assignment. A simple, contrived example:


MyEnum = (item1, item2, item3);
...
function enumToString(value: MyEnum): string
begin
switch(value)
case item1: result = "Item one";
case item2: result = "Item two";
case item3: result = "Item three";
end;
end;
...
SomeLabel.Caption = enumToString(value);
...

becomes something like this:


MyEnum = (item1, item2, item3);
enumToString[MyEnum]: string = ("Item one", "Item two", "Item three");
...
SomeLabel.Caption = enumToString[value];
...
Not only does it reduce code, it also reduces possible bugs. Consider what happens when a value is added to MyEnum. The first example will simply return an empty string creating a possible silent failure that hopefully will be caught when tests are run. The second will generate a compiler error, forcing the programmer to intentionally decide what to do.

In C#, array indexes must be one of the four integer types: int, uint, long or ulong. I really miss the ability to use bools and enums. While lamenting this lack as I looked at some code today similar to the original switch statement, I realized I could use a generic dictionary. The new code looks like this:

MyEnum = (item1, item2, item3);
enumToString = new Dictionary = {{item1, "Item one"}, {item2, "Item two"}, {item3, "Item three")};
...
SomeLabel.Contents = enumToString[value];
...
On one hand, it is a bit more wordy than the Delphi array; on the other, it's clearer how things are associated in the initializer. The biggest drawback is it doesn't have the compiler error when things are added to the enum. This is mitigated a bit by the runtime exception generated by a missing key; it's not quite as silent as just returning nothing in the original code. However, it still depends on good test coverage to find it.

Friday, May 6, 2011

Arduino notebook: 16x2 LCD display (Part 2)

How to change the default behavior

Prologue

My last article in this series talked about why I chose Sparkfun's Serial Enabled LCD display kit and how to build it. One of the reasons it caught my eye was because it uses an Arduino as the controller for the display. I figured it was pretty busy doing nothing most of the time and thought it could be used for other purposes in addition to driving the display. Upon further investigation, it turns out I was right.

Nicole, a friend of mine, recently e-mailed me about a photography project she was interested in doing but didn't want to spend the money for a professional rig to do some of the things involved. She asked if I had any ideas. I'd already given some thought to the problem, the investigation of which led me to the Arduino platform in the first place. This project was one I had stewing on the back burner for quite a while and it was now time to turn up the heat on it.

One of the requirements was to be stand-alone. It had to allow for some user configuration at the time of use in battery mode, without any other devices attached. This ruled out the obvious easy solution of setting the parameters via USB through a computer. Also, it involved controlling a stepper motor. I immediately thought of the LCD kit. I knew I would at least use it for the display, and hopefully some toggle switches. I had a distant hope I could also use it for the motor control. Since this was going to be a pretty permanent build, I immediately ordered another LCD to use specifically for this project.

After getting a new display on the way, I pulled out my first kit to take a look at it. Sure enough, it had a handful of empty holes on the PCB labeled with both digital and analog pin assignments. Cool. It had enough extra pins to accomodate everything I needed to do. So, I started work on the rest of the project while I waited for the LCD to arrive. (The other details of this project I'll write about in future articles here and on my photography blog Hooked On Light.)

First thing after getting the new kit, I assembled it. It went much faster this time with no of the frustrations I experienced on the first one. It actually worked the first time I applied power.

One of the biggest things I did differently was to use ribbon cable between the display and controller boards. In some ways this made things easier and in other ways it was harder. I think on the next project I'll probably put the header pins that come with the kit in one board and get a socket to solder onto the other board. That will give me a cleaner build like the first one, but with the ability to separate the boards for easier access like I have with the ribbon cable on the second one.

The web site to order the kit indicates the firmware can be reprogrammed with an FTDI Basic Breakout board. I had ordered one with the first kit, but hadn't had a chance to use it prior to this project. Knowing I needed to use this, I also purchased some 90 degree header pins from my local electronics parts supplier and soldered them into the holes on one end of the board designed for the purpose. This allowed the FTDI board to plug onto the controller board, providing a plug for a USB cable to be plugged in.

Now I started looking for instructions on how to actually reprogram the thing. The order page indicated you needed to change a setting in the Arduino IDE and referenced the github page for further instructions. Well, the github page had no other instructions on programming the thing. All it talked about was how to use the board through the serial interface. The software for the firmware was also hosted there. Besides the one sentence on the order page, I couldn't find any other instructions either on those two sites or anywhere else via web searches on how to reprogram this kit.

Reprograming the kit

I figured, no guts, no glory and decided to experiment some. I downloaded the source code from github, loaded it in the Arduino IDE and made a simple change to the splash screen text. Since the splash screen is the first thing you see, I thought this would be an easy way to verify if my changes worked or not. In the IDE, as instructed on the order page, I changed the target machine to Arduino Duemilanove or Nano w/ ATmega328 and hit the upload button.

It compiled.

It uploaded.

And when it reset after the upload, there was my new splash screen text.

Amazing. That was all there was to reprogram the kit's default software. The reason I couldn't find any other instructions was, there weren't any other instructions needed.

Epilogue

After this success, it was simply a matter of changing things to do what I needed it to do for this project. Essentially, I ripped out everything the existing software does and replaced it with what I needed. There are a few lines to initialize the LCD and one function to write characters to the screen that are the same, but everything else is completely new.

Now that I've found how easy this is to repurpose, I think I'll probably use it for other projects in the future too. It's an easy way to get an entire Arduino system up and running in a clean package with a simple user interface and minimal external support circuitry needed.