# Friday, April 16, 2010

Tonight, I worked some more on Ubox. Since having been introduced to demos, there has been one effect I’ve always wanted to try coding – the LED-sign style scroller. In theory, it’s easy enough – plot pixels. However, I tried to take it a step further.

My first attempt involved testing copying one array of integers to another, column by column, to simulate the effect of scrolling. While this worked, I quickly realized how inefficient it is. To store the 26 letters of the alphabet as arrays of integers, size 8x8 would require on a 32-bit machine, 4 x 64 x 26 = 6656 bytes, or around 6KB. Doesn’t sound like a lot of memory? It might not be these days, but it’s inefficient as hell. After doing some thinking, I realized that for the scroller, I only wanted two colors – a light red and a dark red. With this in mind, I realized I could do some primitive compression. If we have 8x8 scroller character data, we need to store 64 bits, or 8 bytes of information per character. That works out to two 32-bit integers on a Win32 machine. With this in mind, I cut the space requirement from 6656 bytes to 208 bytes.

To implement this, I built a separate helper program in C#. Enter the worlds worst monochrome graphics editor.

image

Yes, it’s done in WinForms. Yes, I know how to use WPF. Yes, the program is a total hack. But it works. Basically, the checkboxes represent what one would expect to be an “on” state. Output gives me the integer array representing the character data. For instance,

int stuff[53] =
{
0x66663C3C, 0x66667E66, 0x7E82827E, 0x7E82827E, 0x6063C78, 0x783C0606, 0x42427E3E, 0x3E7E4242, 0x3E023E7E, 0x7E3E021E, 0x3E023E7E, 0x202021E, 0x6067E3C, 0x7C7E4676, 0x7E666666, 0x6666667E,
0x18187E7E, 0x7E7E1818, 0x3730FCFC, 0x1E3E3237, 0x1E366606, 0x66361E0E, 0x6060606, 0x3C7E0606, 0xD6FEEEC6, 0xC6C6C6C6, 0xCFC7C3C3, 0xC3E3F3DB, 0x66667E1C, 0x3C7E6666, 0x6666663E, 0x606063E,
0x66667618, 0xD8FE7676, 0x46467E3E, 0x66361E3E, 0x606063C, 0x3C60603C, 0x18183C7E, 0x18181818, 0x66666666, 0x387E6666, 0xC3C3C300, 0x183C66C3, 0xC3C3C3C3, 0x66FEDBDB, 0x183CE7C3, 0xC3C3663C,
0x3C666666, 0x18181818, 0x30607C7E, 0x7E3E0C18, 0x0, 0x0
};

…represents my horribly-drawn 26-character-plus-space alphabet.

Next came the implementation. I keep track of the current “column” being displayed in the scroller, along with the ASCII string being displayed. The ASCII string is used to plot each character.

  1: for(int i = 0; i < 96; i++)
  2: {
  3:   // Drawing routine for pixel scroller.
  4: 
  5:   //  PSet(xLet + (x << scale), 50 + (y << scale), pixDt[2], pixDt[1], pixDt[0], screen);
  6: 
  7:   int currCol = (col + i) % len;
  8:   char letter = scroller[currCol / 8];
  9:   if(letter == 32)
 10:   {
 11:     for(int y = 0; y < 8; y++)
 12:     {
 13:       // col
 14:       PSet(xLet + (i << scale), 125 + (y << scale), 140, 0, 0, screen);
 15:     }
 16:   }
 17:   else
 18:   {
 19:     for(int y = 0; y < 4; y++)
 20:     {
 21:       int realLetter = letter - 0x41;
 22: 
 23:       // Idea: top half is in MSB of stuff[realLetter]
 24:       // bottom in LSB of stuff[realLetter + 1]
 25: 
 26:       int t1 = ((8 * y) + (currCol % 8));
 27:       int t2 = stuff[realLetter * 2] >> t1;
 28:       Uint8 g1 = (t2 & 0x1) == 0x1 ? 255 : 140;
 29:       Uint8 g2 = ((stuff[(realLetter * 2) + 1] >> ((8 * (y + 4)) 
 30:         + (currCol % 8))) & 0x1) == 0x1 ? 255 : 140;
 31:       // col
 32:       int x1 = xLet + (i << scale);
 33:       int y1 = (y << scale);
 34:       int x2 = xLet + (i << scale);
 35:       int y2 = ((y + 4) << scale);
 36: 
 37:       y1 = 125 + y1;// * cos((double)sAngle*3.14/180.0);
 38:       y2 = 125 + y2;// * cos((double)sAngle*3.14/180.0);
 39:       PSet(x1, y1, g1, 0, 0, screen);
 40:       PSet(x2, y2, g2, 0, 0, screen);
 41:     }
 42:   
 43:   }
 44: }
 45: 

That’s the entire source listing for the scroller. The horrible mess of bit-shifts and modulo translates the stored integer into a simple 0x1 or 0x0 for display.

The result looks like this:

Ubox3

Friday, April 16, 2010 1:36:20 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, April 14, 2010

Ubox – Enter the Hello World

Ubox1

Ubox-Preview

Music was totally ripped from the Razor 1911 Chipdisk #3. I plan on changing that. The bouncing head is Bob Barker from Robot Chicken. Totally not posting until I find a way to not have to deal with DLL hell. The source is 463 lines long, including whitespace, written in C++ (so it’s no speed demon). I think for a hello-world sort of demo it’s not bad at all. Just need to watch more demos and get inspiration for this.

Did I mention this is only my second completely unmanaged C++ application that isn’t trivial? (The first was my Physics project for grade 12 – a GameBoy Advance ROM. That was some serious fun to work on.)

Wednesday, April 14, 2010 4:23:19 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 

Today, after studying for a CS exam for four hours straight, I decided that it would be a good judgment call to write some code. After all, there’s only so much theory one can absorb until code calls. So, I decided to write my first (official) demo. I’m still working on it, and want to compose my own music to it (and make it suck a little less), so it’ll be released later.

I ran into a fun snag along the way, though. I used the SDL libraries to power the graphics of the demo. One library, SDL_Gfx, is not distributed precompiled – you have to compile it yourself. Fortunately, the author includes a Visual C++ Project file that builds just fine. Now, I’ve done some SDL work in the past and had built SDL_Gfx a while ago.

At this point, some readers might see where this is going. As I put some of the hacking finishing touches on the demo, I sent it out to a couple of friends. Of course, it didn’t run on either machine. One was Windows 7, one was Windows XP, and both failed with the same error: The application was unable to start correctly (0x0150002).

A little digging, and the problem pointed to a few solutions – reinstall Windows (yuck), install Visual C++ Express 2008 (double-yuck), or redistribute the debug DLL for Visual C++ 2008 (triple-yuck). This seemed odd to me; I had compiled the demo as a release, non-debug Windows EXE. Why on earth would it need the debug runtime?

Further digging in the event log brought us this error: "Activation context generation failed for "c:\…\release\SDLGFX.DLL". Dependent Assembly Microsoft.VC90.DebugCRT, processorArchitecture="x86", publicKeyToken="1fc8b3b9a1e18e3b", type="win32", version="9.0.21022.8" could not be found. Please use sxstrace.exe for detailed diagnosis."

After a couple of hours of fiddling with manifest files, swearing at SxS, and no luck with the various builds, I stared at the path above. SDLGFX.dll. Then it hit me.

I had built SDL_Gfx as a Debug library in Visual C++ 2008. Crap.

Some swearing and frantic coding later, it works, and runs on other machines. The moral of the story? Always check to make sure your library build type matches your solution type.

I just wish I could have that two hours of my life back.

Wednesday, April 14, 2010 4:12:11 AM (Eastern Daylight Time, UTC-04:00)  #    Disclaimer  |  Comments [0]  | 
# Tuesday, March 02, 2010

I’ve been on a cooking kick recently and have come up with a series of recipes that are tasty, cheap, and nutritious. Here’s one such dish.

  • Skinless, boneless chicken breast
  • Whole-wheat spaghetti noodles
  • Red chili pepper flakes
  • Garlic (either powder or fresh)
  • Salt

Here’s how to prep:

  1. Cook up the chicken breasts. Since I’ve got a Costco membership, I like to buy the bags of Kirkland frozen chicken breasts, as they yield 2kg worth. I’d recommend buying at least 400g worth of chicken breasts and cooking them all up at the same time. From frozen, bake in the oven for approx. 30 minutes at 400F.
  2. At the same time, cook up the spaghetti noodles. As with the chicken, I like to cook a lot of it up at the same time so it’s ready to go when I need to throw a meal together quickly. Whole wheat noodles boiled should take 8-10 minutes.
  3. After cooking the noodles, strain them. Once the excess water is removed, set aside and (optionally) let cool.
  4. After cooking the chicken breasts, take one or two and cut into thin pieces, width-wise.
  5. Get out the frying pan, put in some olive oil, and crank the heat to approximately medium (electric). When the oil is up to temperature, throw in some noodles, and the sliced up chicken.
  6. Sprinkle on some red chili pepper flakes, garlic, and salt. Cook 3-5 minutes.
  7. Plate, and serve.

I’ll post some pictures of this dish the next time I make it. Enjoy!

(Note: the directions to making this dish are a little vague, I know. It’s moreso a dish I threw together when I ran out of spaghetti sauce. It’s delicious though.)

Tuesday, March 02, 2010 7:10:34 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, November 26, 2009

For anyone who’s done any WPF control retemplating, it can sometimes be a daunting task. Some controls seem to retemplate with ease, while others can have a myriad of nested styles, with certain parts seeming to appear where you don’t expect them. Today, I ran into an interesting situation with the WPF Toolkit’s DataGrid – retemplating the column header sorting arrows.

As it turns out, the arrows for column sorting live in the control DataGridHeaderBorder. If we inspect the DataGrid.DataGridColumnHeader style in Blend…

Blend1

…notice there’s no placeholder for the arrows. Attempting to edit the default style for the Border won’t work either – there is no style to be found. There is no ControlTemplate to edit either, since DataGridHeaderBorder inherits from Border, which in turn inherits from FrameworkElement, and not Control. (Remember, Control defines the ControlTemplate property)

So where are the arrows defined then? Well, inspecting the source for the DataGridHeaderBorder…

/// <summary>
///     Called when this element should re-render.
/// </summary>
protected override void OnRender(DrawingContext dc)
{
if (UsingBorderImplementation)
{
    // Revert to the Border implementation
    base.OnRender(dc);
}
else
{
    // Choose the appropriate rendering based on the current theme
    switch (Theme)
    {
      // Omitted for brevity's sake...
      // A switch here calls RenderAeroNormalColor.
    }
}

private void RenderAeroNormalColor(DrawingContext dc)
{

   if (isSorted && (size.Width > 14.0) && (size.Height > 10.0))
   {
       // Draw the sort arrow
       TranslateTransform positionTransform = new TranslateTransform((size.Width - 8.0) * 0.5, 1.0);
       positionTransform.Freeze();
       dc.PushTransform(positionTransform);

       bool ascending = (sortDirection == ListSortDirection.Ascending);
       PathGeometry arrowGeometry = (PathGeometry)GetCachedFreezable(ascending ? (int)AeroFreezables.ArrowUpGeometry : (int)AeroFreezables.ArrowDownGeometry);


          // Actual drawing here, omitted for brevity's sake...
      }
}

If you snoop through this source (in the toolkit), you’ll notice the arrows are drawn in the OnRender() method of the DataGridHeaderBorder. In my humble opinion, I don’t think this is the most intuitive way to pull this effect off, but I’m sure there was a sound reason for it. In any case, if you’ve got your own sorting arrows that you wish to use, the easiest (and only way, I believe) to do this is to adjust their visibility by using the Triggers of the DataGridColumnHeader, namely the SortDirection property.

Special note: SortDirection is a nullable property – it is set to null when there is no sorting applied to the column. Keep this in mind when templating the control.

image For this demonstration, I’ve blown away the default DataGridHeaderBorder. I’ll use a regular Border, with a ContentPresenter within it (for the column header contents – don’t forget this), and two TextBlocks to indicate the sort direction. Remember, you aren’t limited to TextBlocks – you can use whatever you want to indicate sort direction. You can even use Storyboards that fire on the EnterAction property of the trigger to provide animations.

First, I created a style on the DataGridColumnHeader of a fresh DataGrid, and defined it in Window1.xaml. I blew away the default style and put in a Border containing a StackPanel, which contains the ContentPresenter and our two TextBlocks.

The TextBlocks are to be Collapsed by default, since the default state of a column is no sorting.

The reason I picked a StackPanel to contain the ContentPresenter and the sorting arrows is that I wanted to whip up a demo fairly quickly, and this is the fastest way to get the control to automatically resize itself to prevent waste of dead-space from the arrows. You can pull off the hiding of the space used by the arrows by using appropriate autosizing of grid columns, etc., a topic of which I’ll cover in a future article.

Next, we can apply our triggers to show the user what direction they are sorting. In the above screengrab, I’ve already added three Property triggers for  SortDirection: Ascending, Descending, and null. Null is used for when there is no sorting applied, and the other two are self-explanatory. So, depending on which value is currently set will define which arrows are visible.

With SortDirection = Ascending selected, I’ve set the Visibility property of the Up TextBlock to be visible, and for the SortDirection = Descending, the Dn TextBlock is visible. When null, no changes occur from the default style, which is to say both TextBlocks are Collapsed. The end result looks like this…

 

 image which goes to…  image

… and finally goes to…

image

Thursday, November 26, 2009 11:32:16 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  | 
# Thursday, November 19, 2009

Recently, I found a need to keep an item within a Scrollviewer from scrolling vertically, yet allow it to scroll horizontally. After a few fruitless attempts at banging my head against the wall on this issue, I found a solution that appeals to my sense of elegance. Not only that, but it’s a XAML-only approach. Sweet.

We make use of the RenderTransform property on a UIElement. Specifically, to allow the control to scroll horizontally but keep it fixed vertically, we’ll be using a TranslateTransform and tweaking its Y value. Thankfully, it derives from DependencyObject, so it’s eligible to participate in data binding, so that’s exactly what we’ll do.

<ScrollViewer x:Name="scrollViewer"
              HorizontalScrollBarVisibility="Visible">
    <Grid>
        <Rectangle Stroke="Blue"
                   StrokeThickness="4"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   Width="900"
                   Height="50">
            <Rectangle.RenderTransform>
                <TransformGroup>
                    <TranslateTransform Y="{Binding VerticalOffset, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ScrollViewer}}, Mode=Default}"
                                        X="{Binding HorizontalOffset, ElementName=scrollViewer, Mode=Default}" />
                </TransformGroup>
            </Rectangle.RenderTransform>
        </Rectangle>

        <Rectangle Stroke="Black"
                   HorizontalAlignment="Left"
                   VerticalAlignment="Top"
                   Width="100"
                   Height="900"
                   StrokeThickness="4" />
    </Grid>
</ScrollViewer>

imageIn the above sample, I’ve bound to the Vertical/HorizontalOffset of the Scrollviewer in two ways. The first is using my preferred method of finding a specific element, RelativeSource FindAncestor. That signals the WPF binding engine to search through the visual tree for the first parent control of type Scrollviewer. This is convenient for when you don’t want (or need) to give your control a specific name, but still need to bind to it. The other method is to use the ElementName binding, which works just as well. The result?

The result is exactly what you would expect. The blue bordered rectangle appears to stay in the same spot, yet everything else within the Scrollviewer scrolls as per normal. Why?

During a RenderTransform, as far as the WPF layout engine is concerned, the Rectangle has not moved, since RenderTransforms are not applied until after the layout (measure/arrange) has been completed, ergo during the render pass.

Remember, a LayoutTransform will change the controls layout, which will be taken into account during the measure/arrange pass! This is why I used a RenderTransform to pull this off. As an exercise, you might want to change the RenderTransform to a LayoutTransform just to see what will happen.

As a side-note, yes, I realize I’m running in the classic Windows theme. It’s only because I’m not running Windows 7 (yet) on my main development box. Perhaps I’ll switch that over soon…

Thursday, November 19, 2009 12:24:13 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  | 
# Wednesday, March 18, 2009
Normally I don't blog at work, but today is a very special exception. Announcements include Expression Web SuperPreview, a beta of which is now available at http://shrinkster.com/15ad.

Various announcements concerning ASP.NET MVC 1.0, Velocity, and the like.

Just announced as I write this post is the Microsoft Web Platform Installer. Scott Hanselman has a post of this at http://shrinkster.com/15ae.

If you actually keep track of my site, go to http://live.visitmix.com/ and watch the keynote!

UPDATE: Silverlight 3 beta 1 SDK! Here we go again, kids. http://www.microsoft.com/downloads/details.aspx?FamilyID=D09B6ECF-9A45-4D99-B752-2A330A937BC4&displaylang=en This should prove interesting. It looks like Microsoft answered my prayers for a way to run a Silverlight app as a standalone application, like Adobe AIR. Awesome! http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=11dc7151-dbd6-4e39-878f-5081863cbb5d is where the VS tools are.

UPDATE THE SECOND: The Silverlight 3 tools are all available for download at http://silverlight.net/getstarted/silverlight3/default.aspx.

Wednesday, March 18, 2009 11:48:39 AM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  | 
# Saturday, March 14, 2009

You know you want some swag with my face plastered onto it in full monochrome glory. Now you can get your fill of Elias Puurunen anytime you want - http://www.cafepress.com/EliasPuurunen. Buy a T-shirt, buy a mug, hell, buy one (or more) of everything! Show some love in the form of your hard-earned recession-bail-out-package dollars.

Saturday, March 14, 2009 11:25:50 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  | 
# Sunday, March 08, 2009

2 After a few months of being M.I.A., a podcast that I didn't exactly maintain, and a successful university term, I think I'm back... for a little while at least. A number of things have changed in my world; I'm certainly busier these days than ever before.

First off, I will be speaking at the Toronto Code Camp on April 25, 2009! Go check out the details at http://www.torontocodecamp.net/. I'll be speaking about some of my experiences as a Windows Presentation Foundation developer, with the session being named WPF and the Model-View-ViewModel Pattern. I hope to make this an interesting session, and I plan to bring up the small nuances/gotchas that one might run into whilest working with WPF. (As an aside, enough W's in that last sentence?) It's an all-day event, my session is only an hour long, and it's free for anyone to attend. Come on out and see it!

IMG_0054 Next, I'm making a triumphant return to the world of water-cooled PC's. I've got the gear sitting on my desk as I type this article; it's a matter of taking the plans I've crafted, going to the hardware store, and getting the beast integrated into my system again, all without leaking liquid all over the place. Pictures will be forthcoming of that event.

Somewhat related to technology as well is the custom hybrid dance pad I built for Dance Dance Revolution. Dissatisfied with the way most soft pads work, I decided to venture out and build my own. Unfortunately, this didn't work out as well as I had planned, but I took plenty of pictures of the disaster, and once I locate the SD card they're stored upon, those will be posted as well. A wood version of the pad is currently in the works, and I plan on talking about that sucker plenty.

Finally, I'm in the process of moving the old blog to my new webhosting provider; I'll be porting over the old posts at some point. For now, I'm back. For a little while at least.

P.S.: For what it's worth, I've now got a Twitter account, since that seems to be the latest craze. Follow me at http://twitter.com/EliasPuurunen.

Sunday, March 08, 2009 7:35:21 PM (Eastern Standard Time, UTC-05:00)  #    Disclaimer  |  Comments [0]  |