About Me

My photo
I'm a colonist who has declared war on machines and intend to conquer them some day. You'll often find me deep in the trenches fighting off bugs and ugly defects in code. When I'm not tappity-tapping at my WMD (also, known as keyboard), you'll find me chatting with friends, reading comics or playing a PC game.

Monday, February 15, 2010

Snow flakes particle system in WPF

Hi all! While playing around with a rudimentary particle system that I created, I thought it might be fun to create a screen saver that will do a cool Compiz Fusion style snow fall. Of course, this was just a fun exercise. The screen saver is not configurable at all, except through code.

Sunday, February 7, 2010

A 3D Valentines day Greeting card.

I'd like to showcase a 3D Greeting card concept created in WPF. Feel free to customize and send this card to others too. The attached readme file in the download package has some information on customizing the card.

System and Software Requirements:
A processor better than a PIV.
Windows XP SP2 (with .NET Framework 3.0 or higher installed), Windows Vista or Windows 7.
A graphics card is recommended but not required.

Sunday, January 24, 2010

Its a programmer thing

I'm just trying my hand out at web comics and though I'm far from Penny Arcade or xkcd, I'd really like to give my readers something to smile about. :)

Tuesday, November 24, 2009

LWUIT and WPF Gradients Mash-up #2

"On the last episode of Angelo's Stuff..."
We saw how to create a multi-coloured linear gradient. We also learnt the concept and purpose of gradient stops. This time around, we're going to dive into radial gradients.

What's so hard about radial gradients?
First off, there are a couple of things that radically differentiate linear and radial gradients.
  1. Linear radients are memory efficient. Only a small strip of an image needs to be made and that same image is tiled either horizontally or vertically across the area to be painted. Radial gradients are not tegular. We need an image that is as large as the area to be painted. A lot of memory is going to be used for a fancy effect. The good news is that the memory will be used up at run-time. So, the downloadable application isn't bloated.
  2. Radial gradients have a lot of customization options. Since we're using up a large image, we might as well get our memory's worth.
Let's paint the town red!

The GradientStop class.
See previous post.

The RadialGradient class.
public class RadialGradient
{
private Vector vGradientStops;
private int radiusX, radiusY;
private int marginTop, marginLeft;

public final static int FILL = 0xffff;
public final static int CENTER = 0xffff;

public RadialGradient( Vector gradientStops,
int radiusX, int radiusY,
int marginLeft, int marginTop )
{
vGradientStops = new Vector();
if(gradientStops != null)
{
//Ensure the gradient stops are ordered by offset in the member Vector.
for(int i = 0; i < gradientStops.size(); ++i)
{
GradientStop newGradientStop =
(GradientStop) gradientStops.elementAt(i);
int insertPos = 0;
for(insertPos = 0; insertPos < vGradientStops.size(); ++insertPos)
{
GradientStop existingGradientStop =
(GradientStop) vGradientStops.elementAt(insertPos);
if(newGradientStop.getOffset() < existingGradientStop.getOffset())
{
break;
}
}

vGradientStops.insertElementAt(newGradientStop, insertPos);
}
}

this.radiusX = radiusX;
this.radiusY = radiusY;
this.marginTop = marginTop;
this.marginLeft = marginLeft;
}

//Getters.
public Vector getGradientStops()
{ return vGradientStops; }
public int getRadiusX()
{ return radiusX; }
public int getRadiusY()
{ return radiusY; }
public int getMarginLeft()
{ return marginLeft; }
public int getMarginTop()
{ return marginTop; }
}

The constructor of this class takes the following parameters:
  1. A Vector of GradientStop. This allows us to use multiple colours within a single gradient.
  2. An X radius. This is the width of the radial gradient. Specify RadialGradient.FILL in order to have the radial gradient fill the entire width of the painted area.
  3. A Y radius. This is the height of the radial gradient. Specify RadialGradient.FILL in order to have the radial gradient fill the entire height of the painted area.
  4. A left margin. This is the distance of the center of the gradient from the left-most point of the area to be painted. Specify RadialGradient.CENTER to have the radial gradient show up in the horizontal center of the painted area.
  5. A top margin. This is the distance of the center of the gradient from the top-most point of the area to be painted. Specify RadialGradient.CENTER to have the radial gradient show up in the vertical center of the painted area.
What are these margins for?
The margins are basically used to space the radial gradient in the area to be painted. Assume that we have a radial gradient with an X radius and Y radius of 20 each. Now let's say that we want to paint this radial gradient at the top left of the painted area. Then all we need to do is specify left and top margins of 10 (half the respective radii). The illustration below should clarify things.

The Painter.
We're going to cache an image that is as large as the area to be painted. So, why restrict ourselves to a single radial gradient? Let's call our custom Painter - MultiRadialGradientPainter. The user of our Painter should be able to overlay multiple radial gradients over each other.
public class MultiRadialGradientPainter implements Painter
{
private byte opacity;
private Image cache;
private Vector vRadialGradients;
private int backFillColor;

public MultiRadialGradientPainter( Vector radialGradients,
byte opacity, int backFillColor )
{
vRadialGradients = radialGradients;
this.opacity = opacity;
this.backFillColor = backFillColor;
}

//Special case overload for single Radial Gradients only.
public MultiRadialGradientPainter( RadialGradient radialGradient,
byte opacity, int backFillColor )
{
vRadialGradients = new Vector();
vRadialGradients.addElement(radialGradient);

this.opacity = opacity;
this.backFillColor = backFillColor;
}

public void paint(Graphics g, Rectangle rect)
{
final Dimension d = rect.getSize();
final int x = rect.getX();
final int y = rect.getY();
final int width = d.getWidth();
final int height = d.getHeight();

final int size = Math.max(width, height);
if(cache == null || size != cache.getWidth())
{
cache = Image.createImage(size, size);
Graphics dc = cache.getGraphics();

//Set the backFillColor before drawing the gradients.
if(backFillColor >= 0)
{
dc.setColor(backFillColor);
dc.fillRect(0, 0, width, height);
}

for(int i = 0; i < vRadialGradients.size(); ++i)
{
final RadialGradient radialGradient =
(RadialGradient)vRadialGradients.elementAt(i);
int radiusX = radialGradient.getRadiusX();
int radiusY = radialGradient.getRadiusY();
int marginLeft = radialGradient.getMarginLeft();
int marginTop = radialGradient.getMarginTop();

if(radiusX >= RadialGradient.FILL)
radiusX = size;
if(radiusY >= RadialGradient.FILL)
radiusY = size;

if(marginTop >= RadialGradient.CENTER)
marginTop = height / 2;
if(marginLeft >= RadialGradient.CENTER)
marginLeft = width / 2;

final Vector vGradientStops = radialGradient.getGradientStops();
for(int j = vGradientStops.size() - 2; j > -1; --j)
{
GradientStop thisGradientStop =
((GradientStop)vGradientStops.elementAt(j));
GradientStop nextGradientStop =
((GradientStop)vGradientStops.elementAt(j + 1));

drawRadialGradient(dc,
thisGradientStop.getColor(),
nextGradientStop.getColor(),
(int)(radiusX * (thisGradientStop.getOffset() / 100.0)),
(int)(radiusX * (nextGradientStop.getOffset() / 100.0)),
(int)(radiusY * (thisGradientStop.getOffset() / 100.0)),
(int)(radiusY * (nextGradientStop.getOffset() / 100.0)),
marginLeft, marginTop
);
}
}

if(opacity < 255)
{
cache = cache.modifyAlpha(opacity);
}
}

g.drawImage(cache, x, y);
}

//This routine does the job of drawing a radial gradient.
private void drawRadialGradient(Graphics dc, int srcColor, int destColor,
int startRadiusX, int endRadiusX,
int startRadiusY, int endRadiusY,
int marginLeft, int marginTop)
{
final int srcR = srcColor >> 16;
final int srcG = srcColor >> 8 & 0xff;
final int srcB = srcColor & 0xff;

final int destR = destColor >> 16;
final int destG = destColor >> 8 & 0xff;
final int destB = destColor & 0xff;

final int dx = (endRadiusX - startRadiusX);
final int dy = (endRadiusY - startRadiusY);
final int biggerDiff = (dx > dy) ? dx : dy;

for(int i = biggerDiff; i > 0; --i)
{
final int interpolatedR =
(int)(srcR + ((destR - srcR) * ((float)i / biggerDiff)));
final int interpolatedG =
(int)(srcG + ((destG - srcG) * ((float)i / biggerDiff)));
final int interpolatedB =
(int)(srcB + ((destB - srcB) * ((float)i / biggerDiff)));

final int interpolatedColor =
interpolatedB | (interpolatedG << 8) | (interpolatedR << 16);

dc.setColor(interpolatedColor);

final int currentRadiusX = startRadiusX + (i * dx / biggerDiff);
final int currentRadiusY = startRadiusY + (i * dy / biggerDiff);

dc.fillArc(
marginLeft - (currentRadiusX / 2),
marginTop - (currentRadiusY / 2),
currentRadiusX, currentRadiusY, 0, 360);
}
}
}
The constructor of MultiRadialGradientPainter takes the following arguments:
  1. A Vector of RadialGradient. This allows us to have multiple radial gradients drawn by the painter.
  2. Opacity. A byte value that controls the transparency of the entire painted image.
  3. A back fill color. This colour will be used to fill the remainder of the space in the image where there is no gradient.
How about an example?
We have a simple LWUIT Form with a Label at the top (BorderLayout.NORTH).






















The screenshot on the left shows the Form without the Label. The Form has two radial gradients - one on the top and the other in the center. The screenshot on the right shows the barebones Form with the Label. The Label has a linear gradient.

This is what the code for setting these gradients looks like:
{
Vector vGradientStops = new Vector();
vGradientStops.addElement(new GradientStop(0xffffff, (byte)0));
vGradientStops.addElement(new GradientStop(0x434343, (byte)50));
vGradientStops.addElement(new GradientStop(0xffffff, (byte)60));

theLabel.getStyle().setBgPainter(
new LinearGradientPainter(vGradientStops, (byte)127, false));
}
{
Vector vGradientStops = new Vector();
vGradientStops.addElement(new GradientStop(0x704700, (byte)0));
vGradientStops.addElement(new GradientStop(0x251801, (byte)100));

Vector vRadialGradients = new Vector();
vRadialGradients.addElement(
new RadialGradient(vGradientStops,
RadialGradient.FILL, RadialGradient.FILL,
RadialGradient.CENTER, RadialGradient.CENTER));

Vector vSmallGradientStops = new Vector();
vSmallGradientStops.addElement(new GradientStop(0xffa300, (byte)0));
vSmallGradientStops.addElement(new GradientStop(0xffa300, (byte)50));
vSmallGradientStops.addElement(new GradientStop(0x251801, (byte)100));

vRadialGradients.addElement(
new RadialGradient(vSmallGradientStops,
RadialGradient.FILL, 50,
RadialGradient.CENTER, 0));

theForm.getStyle().setBgPainter(
new MultiRadialGradientPainter(vRadialGradients, (byte)255, 0x251801));

}
Note that the linear gradient is at 50% opacity. When combining the two together, we get the effect as seen below.
Pretty neat, huh?

Is that all?
Well, yes. That's it. A word of caution: Use radial gradients sparingly. Remember that they require memory allocated for an image that is as large as the area to be painted. If we were to start using radial gradients for all our components then we would run into Out Of Memory exceptions. Also, expect the unexpected. If we do run into an OOM exception, we need to gracefully handle it and fall back on a less fancy UI.

Whew! That was a pretty long-winded post but I hope the MultiRadialGradientPainter proves useful to LWUIT designer/developers out there. If you find an issue with the code feel free to inform me and I'll be happy to look into it. Happy coding!

Sunday, November 15, 2009

LWUIT and WPF Gradients Mash-up #1

Shai Almog's blog is the one-stop-shop for all things LWUIT. I recently read his entry on GradientPainters and it floored me! I thought I could enhance it a bit by adding GradientStops to the LinearGradientPainter.

What is a GradientStop?
If you come from a WPF background, then you know exactly what a GradientStop is. The fillLinearGradient() routine in LWUIT allows us to smoothly transition between two colours. So, we could go from White to Black and end up with this.

However, if we want to smoothly transition between multiple colours then that's where GradientStops can help us out. Let's say we want to vertically transition from White to Red and then from Red to Black. We start with White at the top and transition to red halfway through. Then we go from red at the half position, all the way to black at the bottom. Your mind's eye should have a picture like the one below.

A GradientStop has an offset and colour. The offset is the percentage of the position at which the colour is the strongest. For example, in our multiple colour gradient example above, we would need three GradientStops.
  1. GradientStop with offset 0 and colour White (0xffffff in LWUIT terms).
  2. GradientStop with offset 50 and colour Red (0xff0000).
  3. GradientStop with offset 100 and colour Black (0x000000).
Where's the code?
First, the implementation of the GradientStop class.

public class GradientStop
{
   private int color;
   private byte offset;

   public GradientStop()
   {
       color = 0x000000;   //Default Black at offset 0.
       offset = 0;
   }

   public GradientStop(int colorVal, byte offsetVal)
   {
       color = colorVal;
       offset = offsetVal;
   }

   public int getColor()
   {
       return color;
   }

   public int getOffset()
   {
       return offset;
   }

   public void setColor(int value)
   {
       color = value;
   }

   public void setOffset(byte value)
   {
       offset = value;
   }
}

Now, comes the implementation of the enhanced LinearGradientPainter.

public class LinearGradientPainter implements Painter
{
   private boolean horizontal;
   private byte opacity;
   private Image cache;
   private Vector vGradientStops;

   public LinearGradientPainter(   Vector gradientStops,
                                   byte opacity, boolean horizontal)
   {
       vGradientStops = new Vector();

       if(gradientStops != null)
       {
           //Ensure the gradient stops are ordered by offset in the Vector.
           for(int i = 0; i < gradientStops.size(); ++i)
           {
               GradientStop newGradientStop =
                       (GradientStop) gradientStops.elementAt(i);
               int insertPos = 0;
               for(insertPos = 0; insertPos < vGradientStops.size(); ++insertPos)
               {
                   GradientStop existingGradientStop =
                           (GradientStop) vGradientStops.elementAt(insertPos);
                   if(newGradientStop.getOffset() < existingGradientStop.getOffset())
                   {
                       break;
                   }
               }

               vGradientStops.insertElementAt(newGradientStop, insertPos);
           }
       }

       this.horizontal = horizontal;
       this.opacity = opacity;
   }

   public void paint(Graphics g, Rectangle rect)
   {
       final Dimension d   = rect.getSize();
       final int x         = rect.getX();
       final int y         = rect.getY();
       final int height    = d.getHeight();
       final int width     = d.getWidth();

       //Horizontal painting of gradient.
       if (horizontal)
       {
           if (cache == null || width != cache.getWidth())
           {
               cache = Image.createImage(width, 1);               
               Graphics dc = cache.getGraphics();

               for(int i = 0; i < vGradientStops.size() - 1; ++i)
               {
                   GradientStop thisGradientStop =
                           ((GradientStop)vGradientStops.elementAt(i));
                   GradientStop nextGradientStop =
                           ((GradientStop)vGradientStops.elementAt(i + 1));

                   dc.fillLinearGradient(thisGradientStop.getColor(),
                          nextGradientStop.getColor() ,
                          (int)(width * (thisGradientStop.getOffset() / 100.0)),
                          0,
                          (int)(width * (nextGradientStop.getOffset() / 100.0)),
                          1, horizontal);
               }

               if(opacity < 255)
               {
                   cache = cache.modifyAlpha(opacity);
               }
           }
           for (int iter = 0; iter < height; ++iter)
           {
               g.drawImage(cache, x, y + iter);
           }           
       }
       //Vertical painting of gradient.
       else
       {
           if (cache == null || height != cache.getHeight())
           {
               cache = Image.createImage(1, height);               
               Graphics dc = cache.getGraphics();

               for(int i = 0; i < vGradientStops.size() - 1; ++i)
               {
                   GradientStop thisGradientStop =
                           ((GradientStop)vGradientStops.elementAt(i));
                   GradientStop nextGradientStop =
                           ((GradientStop)vGradientStops.elementAt(i + 1));

                   dc.fillLinearGradient(thisGradientStop.getColor(),
                           nextGradientStop.getColor(),
                           0,
                           (int)(height * (thisGradientStop.getOffset() / 100.0)),
                           1,
                           (int)(height * (nextGradientStop.getOffset() / 100.0)),
                           horizontal);
               }

               if(opacity < 255)
               {
                   cache = cache.modifyAlpha(opacity);
               }
           }
          
           for (int iter = 0; iter < width; ++iter)
           {
               g.drawImage(cache, x + iter, y);
           }           
       }
   }
}

How do I use it?
Well usage is pretty simple. Here's an example for our previous multi-gradient case.

Vector vGradientStops = new Vector();
vGradientStops.addElement(new GradientStop(0xffffff, (byte)0));     
vGradientStops.addElement(new GradientStop(0xff0000, (byte)50));     
vGradientStops.addElement(new GradientStop(0x000000, (byte)100));

myComponent.getStyle().setBgPainter(
             new LinearGradientPainter(vGradientStops, (byte)255, false));    
     

Where do I go from here?
Let your imagination run wild!
What about the RadialGradientPainter?
I haven't forgotten about that. I thought I'd cover just one GradientPainter in this post so as not to bog the reader down. A multi-colour RadialGradientPainter will be covered in a future post.

Have fun!

Tuesday, September 22, 2009

Take Control of your Scroll

I recently ran into a specific issue when developing for a Windows Mobile environment. I had a lot of controls inside a Windows Form and by setting the Form's AutoScroll property to true, I could automatically scroll the contents of my form. This was quick and easy but then I found that the scrolling happened one pixel at a time which was just too slow. It would not really matter in most cases but in this case, I had to support the TouchFlo scrolling gesture. Thus began a 2-day hunt for an appropriate solution.

Attempt #1:
The first thing I looked for was some sort of property or method which could increase the scroll step. Nothing.

Attempt #2:
The next thing to try was take complete control of the scrolling. I put in my own scrollbar and handled the Scroll event of the scrollbar. This was a reasonable approach but then I realized that the Touch Flo scroll gesture did not work for me. I slapped my forehead and proceeded to the next attempt.

Attempt #3 (Final Solution):
The only other real solution was to take control of the Windows pumping messages. It turns out that you can override the WndProc function for Windows Forms. When it comes to the .NET Compact Framework, though, you can’t do that because its just not supported. I googled for an alternative and found this. I really must thank Mike Underhill for bailing me out here.
Third time’s a charm, they say and it seemed true in my case. This is what I ended up with.


private const int WM_VSCROLL = 0x115;
private const int GWL_WNDPROC = -4;
private const int SB_LINEUP = 0;
private const int SB_LINEDOWN = 1;

delegate IntPtr WndProcDelegate(IntPtr hWnd, uint msg,
IntPtr wParam, IntPtr lParam);

//Win32 APIs that I need.
[DllImport("coredll.dll", EntryPoint = "GetWindowLong")]
private static extern IntPtr GetWindowLong(IntPtr hWnd, int nIndex);

[DllImport("coredll.dll")]
static extern int SetWindowLong(IntPtr hWnd, int nIndex, IntPtr newWndProc);

[DllImport("coredll.dll")]
static extern IntPtr CallWindowProc(IntPtr lpPrevWndFunc, IntPtr hWnd,
uint Msg, IntPtr wParam, IntPtr lParam);

private static IntPtr oldWndProc = IntPtr.Zero;
private static WndProcDelegate newWndProc;
private const long lowOrderMask = 0xF;

public IntPtr WndProc(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam)
{
if (msg == WM_VSCROLL)
{
long val = ((long)wParam & lowOrderMask);

if (val == SB_LINEDOWN)
{
//Haven’t really found out why the Y position
//was going negative but this seemed an easy fix. :p
AutoScrollPosition =
new Point(0, - AutoScrollPosition.Y + step);
}
else if (val == SB_LINEUP)
{
AutoScrollPosition =
new Point(0, - AutoScrollPosition.Y - step);
}


return CallWindowProc(oldWndProc, hWnd, msg, wParam, lParam);
}
}

//Constructor
public Form1()
{
InitializeComponent();

newWndProc = new WndProcDelegate(WndProc);
oldWndProc = GetWindowLong(pnlContainer.Handle, GWL_WNDPROC);
SetWindowLong(pnlContainer.Handle, GWL_WNDPROC, Marshal.GetFunctionPointerForDelegate(newWndProc));
}


Hope this helps someone who ever comes across this problem.

Tuesday, July 28, 2009

My take on a Glass Button in WPF.

The following video tutorial shows how to create a nifty glass button in WPF using Microsoft Expression Blend 2. This is the first time I've actually made a screencast and it didn't turn out too bad. I'm sure it could be better. So, feel free to comment on anything that you like or don't like.