Phil Wright : Component Factory

Thursday, July 21, 2005

microISV, Coding Evolution

Nothing duplicated

I am a strong believer in reusing code and thereby minimizing the amount of code I need to write. Every time I write some new functionality I double check to make sure I have not already done something very similar already. There are two very good reasons for this.

First of all I want to get maximum benefit from each hour spent in front of the compiler. Working on this project only in my spare time means I don't have the luxury of doing anything not crucial.

Second, and even more important, is the principle of object orientated programming. If I'm writing code that is the same, or very similar, to something elsewhere in the project then something has gone wrong. It's a clear indication that something is going amiss with my design.

That being the case I need to investigate the problem and fix the architecture. The fix should negate the need for the duplicated code.

From small steps...

A result of this approach is that a new project should feel like evolution on a small scale. You start off by writing the simple elements of the project. As you then build upwards you create more complex structures that reuse many of the existing components. You're constantly moving up the evolutionary ladder.

Each step upwards only involves adding a small and reasonable set of features and feels quite manageable in itself. But after a few weeks have passed you look back and notice that all the small steps have evolved your design into an elegant and sophisticated structure. Well, that's the hope anyway!

If you've been following my coding updates then you should have been able to see this taking place. Let's quickly follow how the project has evolved so far.

In the beginning...

The first control created was about as simple and boring as can be imagined. We created a simple Panel component that is mostly going to be used to fill the client area of a window and give it the appropriate appearance.

Below you can see the control in use and it has the Microsoft Office 2003 look and feel. This is the only rendering class I have coded at the moment and so all the example pictures have this look and feel.



Let there be light...

Actually a more appropriate phrase would be Let there be a border... because out second control is the Group component. This consists of adding a border drawing ability with the existing background capability.

This was quick and easy to create because all of the infrastructure from the existing Panel was reused and extended. Although not obvious from this picture the components are much more flexible than they appear. You can use alpha blending, rounded corners, tiled images and so forth.



The Holy Trinity

Component number three took a little longer to construct because it involves drawing and positioning text. This is the Header control and it reuses the background and border functionality from the previous controls and then extends it.

This is an important landmark because the Header represents completion of the holy trinity of rendering. Almost all controls use a combination of background, border and content for display. If this sounds hard to believe then check out the next section which shows a good example of this in practice.



Add another dimension

What is the difference between a Button control and our previously completed Header component? Not a lot. In fact the only difference is that a Header has only a single palette and a Button has several.

Let's define what I mean by a palette. A palette is the triple combination of background, border and content settings. And by settings I mean the colors, font and other drawing styles you can specify.

So when the button is drawn normally we use one palette. When the user moves the mouse over the button area we switch to drawing with a different palette. On pressing the mouse down on the button we use yet another palette.

So the button really is the same as the header but instead of having one palette we have several, one for each of the states it can be in. Now you can see how we are reusing the existing infrastructure to get maximum benefit for adding a minimum of new code.

Our final picture below has two button instances, the left in the hovering over state and the right in the normal state.



To Infinity and beyond...

So what is our next step up the evolutionary ladder? The next control is going to be called the HeaderGroup and, as the name implies, it will combine the Group and Header capabilities into a useful little control. This might not sound like much of an advance, but trust me, it will turn out to be quite a handy little control.

So the next time you're coding...just think how much you owe to Darwin.

Tuesday, July 19, 2005

.NET2, ColorMatrix Reloaded

The Matrix Connection

Despite the headline this blog entry has absolutely nothing to do with the Matrix set of films. In fact it is about using the ColorMatrix capability of the ImageAttributes class for drawing images.

Not only does that description not fit into the title but there is no chance you would have read the entry without the Reloaded part of the name. A marketing guy would call this technique a Teaser. The rest of us call this very sneaky.

If I was selling fish fingers, or any other food, then this would be called a breach of the trade descriptions act and the local council would be onto me. In fact they would already have closed me down. Luckily no one cares about accurate descriptions in the software industry and so we will continue without fear.

Drawing a Disabled Image

I am in the closing stages of writing a Button control and want to make it look good when it was disabled. There are two ways to handle this issue. The easiest solution for me is to get the developer to provide two images, one for when the control is disabled and another for when it is enabled.

Not only is this lazy but it demands extra work from the developer to use my control. The whole point of our library is to make the developers application look good with a minimum of effort from the developer himself. So the alternative solution, and the one I am taking, is to take the enabled image and then draw it in a disabled appearance.

In the past I have used the ControlPaint.DrawImageDisabled method provided by the framework but I am no longer happy with that solution. I want to provide more flexibility in the appearance and so let the developer choose a variety of different ways the image could be manipulated.

Enter The ColorMatrix

This is where the ColorMatrix comes into play because it can be used to modify the colors of the image when it is being drawn. So now my button control allows the developer to specify an enumeration of different ColorMatrix settings to be applied.

Here is a picture with three buttons. The name of the enumeration value is used as the button text and the image is drawn in the named style.



The first is called normal and has no color modification applied. In the second the matrix is used to convert from color to a black and white scale. Last of all the disabled appearance is achieved by using a gray scale but also making the colors 10% brighter than normal. This gives a more subtle look and feel.

GrayScale Matrix Code

new ColorMatrix(new float[][]{

new float[]{0.3f,0.3f,0.3f,0,0},
new float[]{0.59f,0.59f,0.59f,0,0},
new float[]{0.11f,0.11f,0.11f,0,0},
new float[]{0,0,0,1,0},
new float[]{0,0,0,0,1}

});

The first three lines of the matrix are used to convert the Red, Green and Blue colors of the pixel in that order. The fourth line is used to convert the alpha channel and the fifth line for adding/subtracting values.

So in this example the fourth and fifth lines use a value of 1 to show they are leaving the alpha channel alone and not applying any addition/subtraction.

The values in column 0, 1 and 2 of the first three lines are the same because in order to convert to a grayscale we need to ensure that the RGB values are the same for the R, G and B. Notice that the 0.3, 0.59 and 0.11 values add up to exactly 1.

These three relative factors are used because the eye has better acuity in the green range than in the red and the red is better than the blue. Hence we want to take more account of the green (0.59) than the red (0.3) than the blue (0.11).

Color Intensity

There is no limit to the color manipulation you can achieve and so I also added some extra enumeration values for making the image lighter or darker in appearance. These might prove useful in many different situations. Here they are in operation.



Breaking Point

As an experiment I tried converting just two of the colors to grayscale and leaving the third alone. In the example below you can see GrayScale R where the blue and green have been gray scaled but the red left alone. Below that are the other two versions for blue and green variations.



The reason they are not coming out perfectly is that the three circles are not filled with pure red, pure green and pure blue. Hence the conversion is not achieving the exact effect I was intending. I have decided to leave these enumeration options in the code although they will not be used very often.

Pain Points

By providing these different effects out of the box the developer has more options in presenting the button image. They might decide to have the button appear gray scaled normally but become full color when the mouse tracks over it. Alternatively they might want to use a darker version of the image normally and only use the normal image on hot tracking.

The important point is the developer provides just a single image and can then apply different effects without needing to create them using a separate package, such as Paint Shop Pro. To use a really stupid management style phrase, we are removing a Pain Point for the developer.

Friday, July 15, 2005

microISV, Text For Australians

Header Control Revisited

At last the simple heading control is finished. No doubt changes will need to be made in the future to mirror alterations in the overall architecture but the basic implementation is there and working. The last feature I added, and quite a useful one, is the Orientation property.

As you can see in the picture below, you can define the orientation so that text is drawn in one of four positions. The Top, Left and Right positions are easy to imagine being of use in various ways. But the Bottom orientation is a little harder to justify.



My first excuse for adding upside down text is a feeling of completeness. If you add the other three positions it just does not feel right to miss out the fourth one. The second, and more flimsy excuse, is that my wife is from Oz and so she needs that format to use my library.

(No doubt you will haved spotted the flaw in my argument; the chances of a programmers wife writing any code must be pretty slim. Although one of her Australian relations is bound to find this blog and send me an abusive email)

You probably didn't notice on first inspection but the heading control is actually showing multi-line text. This could be really useful in many applications and when you combine this capability with the Orientation and AutoSize properties it turns into a handy little control.

Think of it as a traditional Label control on steroids.


Creating a Button

After creating three simple controls (Panel, Group and Heading) we need to move onto something a little more difficult and certainly more interesting. The one control that everyone loves to create for themselves, the Button.

Browse any programmers code site such as Code Project or Code Guru and you will find a zillion different button implementations. I guess this is the starting place for any new user interface programmer in the same way your first console application is the canonical Hello World!.

One of great advantages of thinking about the design before coding is that I can reuse almost everything written so far. The separation of Palette, Renderer, View, Control and Controller into separate abstractions makes for great reuse possibilities.

So my Button control will use exactly the same specification for content as the Heading control, i.e. an image and two text strings. So creating the basic control outline was quick and easy.

It was also the first time we needed to add a Controller to the framework code as this is the first active control that needs to respond to mouse or keyboard input. The ButtonController implementation just takes the mouse input and decides which palette entries should be used for drawing.

Here you can see the button in three states.



The left image is the normal button state, the second image the mouse over and finally the far right image is where the mouse is pressing down the button. You cannot see the actual mouse pointer because I used a naff screen capture utility that does not capture it, but you get the idea.

Hidden Depths

You might think that the control was pretty much down by the look of it. Sadly that is not the case. Although a Button control sounds very simple it actually has a fair amount of functionality that needs adding that most people don't event think about.

So now I have to flesh it out by correct handling keyboard support for mnemonics. Provide correct feedback for when it has the focus or when it is the default button on a Form. Plus it has to implement the standard IButtonControl interface so it interacts correctly with the rest of the Windows.Forms implementation. And of course it needs to automatically update the DialogResult of the parent Form when the user clicks the button.

Luckily none of these is hard to implement but it does take a little time to knock out the code and test it works as anticipated in the common usage scenarios.

Well, that is my next few days taken care of.

Tuesday, July 12, 2005

.NET2, AutoSize

.NET Framework 2

Version 2 of the .NET Framework is a great improvement for Windows.Forms developers. Each time I investigate a new area I find some cool new feature that makes life so much easier than before.

Control.DisplayRect

My previous technical entry has already mentioned use of the DisplayRect property as a way of controlling the child space available for positioning children. This is a great feature and without this it would be a real pain to achieve the same effect.

Control.AutoSize

Now I have noticed another great addition that will save developers time. There is a new Control property called AutoSize that does exactly what it says. When defined it will automatically resize the control appropriately.

For instance, if you create a Button control instance then the control will size itself to fit the Text content. Now this might not sound very exciting, but in the past you had a real pain getting a control such as a Button to size properly.

For a start you would have to get the Font used by the Control and then measure the size of the Text for that Font. Then you need to add on a sensible spacing gap around the text and finally add the border allocation. Not rocket science but still a pain to have to write the code.

Header and Button

Knowing this great new property is available means I want my own controls to provide the same functionality. If a user can take advantage of AutoSize on a standard windows Button then they will, quite reasonably, expect my own controls to provide the same functionality.

As the image from a previous post show, I have completed the simple Header control for the library. I am now into the process of creating a Button control that reuses the same rendering process.

After a little investigation I worked out how to hook into the auto sizing process. It turns out to be really easy and I recommend that anyone else writing a custom control also adds the capability.

GetPreferredSize

All you need to do is override the virtual method called GetPreferredSize and return from it a Size instance the is the preferred size you would like your control to be. That's it. Just override that one method and your done.

This is so simple there is no excuse for not adding it to your own controls.

Saturday, July 09, 2005

microISV, Strapline Part Deux

Feedback

Thanks for the great feedback comments.

Do we need a strapline?

kris makes a good point by asking if a strapline is actually necessary? I assumed that just because most other companies have one that I should as well. Obviously that is not a good reason, but having thought about this more carefully I have come to the conclusion that actually it is a good idea. It's a good way to get across a simple fundamental message about the company.

When visiting a website I tend to notice the logo and associated strapline first of all. Then my eyes scan downwards to the actual content of the page, skinning over the headlines to see what the content is all about.

So in the worst case people just ignore the strapline, in which case it has caused no harm by being present. In the best case it gets across a simple message I want to convey. This is a no lose situation.

What is the message?

So I guess I need to ask myself what is the message I want to get across to the website visitor. Well I am very clear on what I would like to say. We produce a premium set of visual components that will save your business time and money.

But we need to be careful about putting ideas like saving money or time in the strapline. Just about every company is going to claim they save time and money with their product and so the message is too generic. It needs to be specific.

Looking at the suggestions and working from the ones I like, my new list of candidates comes out like this...

Component Factory
Making you look good.

Component Factory
We build components. You build solutions.

Component Factory
Passionate about your looks.

Component Factory
Creating components so you don't have to.

Component Factory
Tools that extend your potential.

My current favorite is the second one, because it indicates our position in the value chain. We create the components, the building blocks that the customers use to create a full solution.

If you have any more ideas or better variations then let me know!

Thursday, July 07, 2005

microISV, Need a Strapline

All companies have a strapline to go with their company logo and company name. The idea, I assume, is to sum up the philosophy of the company or maybe the type of product or service it offers.

Something short that embodies the whole concept of the company can make it quick and easy for new comers to the website to understand what it is they do. Here are a few examples from software companies that operate in the same market as our microISV.

Infragistics
Powering The Presentation Layer

Pure Components
Components...Pure And Simple

ComponentOne
More Tools. Endless Possibilities

Developer Express
Improving the Developer Experience

So, I need my own strapline for Component Factory. As a company we are going to produce user interface controls in order to make the customers applications look professional. They are intended to be a premium level product that speeds up project schedules by being quick and easy to use but also provide a high level of flexibility.

So far I have only come up with one candidate. Here we go...

Component Factory
Making You Look Good

Not sure if it sounds a bit cheesy. But it indicates straight away that we aiming to make your application look good and could also be taken to mean that the developer will look good for creating such a great appearance very quickly.

Think you can do better? I hope so, lets hear your ideas!

Tuesday, July 05, 2005

microISV, Coding Progress

New Controls

It's been almost two weeks since I last posted any pictures of coding progress. Progress was slowed because I spent a couple of days on a marketing course and then another couple of evenings making changes to my existing company website in order to implement some ideas that came from the course.

But now I am back into full coding mode again and so here is the state of play as of today. We now have three different controls in our little toolkit. If you look at the image below you can see examples of all three.

Professional Renderer



All of the above controls are drawn with the default settings using our single renderer currently in the toolkit. This is called the Professional renderer and is intended to mimic the look and feel of the Microsoft Office line of products.

Most users are accustomed to this appearance and so the majority of business applications want to replicate it in their own applications. By making their own programs look familiar to customers it is likely to help customers believe the corporate application is as professional as Microsoft programs.

The first control on the left is the Panel control and is intended to be used as the background filler for the client area of the application. In our case it is a simple light blue color.

The middle control is the Group control and it provides a border and background appearance for a control container. This is similar to what you might see in Microsoft Outlook, where the contents are a preview of an email message.

Finally our newest control is called Header and as the name suggest is intended to be useful for providing a heading for other content on the user's page. Our header control can have three pieces of information displayed, an image, a primary piece of text and a secondary piece of text. All three pieces are optional and can be aligned against different edges.

Text Rendering

We use the same technique for drawing the text strings as we used previously for drawing the border and background elements. So you can use solid as well as gradient color effects on the text itself. Here is an example with large text so it is easy to see the color effect in action.



I did not need to write lots of new code for the rendering, I could completely reuse the existing code for creating an appropriate Brush for painting the text area.

In a previous post I showed how I had added the ability to provide an image for drawing the border and background. This has also been reused and so here is an example where an image is used to paint the text.



It only took about 30 seconds to create the following header instance with some interested color gradient effects in the border, background and the text itself. Although a little over the top for actual use it shows the potential for creating some cool looking design very quickly.



The Next Step

Although the basics of the Header control are working I still need to flesh out the functionality before it is completed. I need to investigate the ability to auto size the control based on the content, add extra appearance settings so when it is disabled it has a disabled look and feel.

It also needs to handle the RightToLeft setting so international users get the reversed ordering they would expect. Small details like this tend to take up much of the development effort.

Oh well, back to the keyboard...