Archive for April, 2006

Here is a description of the control logic that has now been implemented. I think it covers all the situations developers would need but maybe you can point out possible improvements.

One of the comments to the first Krypton Navigator post pointed out a set of possible scenarios for using the navigator and a summary of features it should have in order to support them fully. As I have now implemented a first cut of the control logic I want to outline its operation.

If you think I have missed something or have ideas for improvements then I would love to hear them. Better to get the logic right now when it is painless than several months down the line.

Dynamic Page Creation

The Navigator has a property called KryptonPages that exposes a collection of KryptonPage instances. As with any standard collection you can append, insert, remove and clear the contents and use the standard collection editor to update the contents at design time. Any change to the collection is reflected in the user interface immediately in an appropriate manner.

Enabled & Disabled

You can enable for disable an individual KryptonPage by using the standard Enabled property that it exposes. The Navigator will then display it in an appropriate manner and alter user interaction as well. For example, a traditional tab appearance would show the tab header for the page in a disabled appearance and prevent the user from selecting the page by clicking the header.

Visibility

Unlike most tab controls you can also use the Visible property of the KryptonPage to hide the page. This prevents the need to remove the page from the KryptonPages collection and then add it back again later on. For example, a traditional tab appearance would completely remove display of a tab header for the page until it is made visible again. Obviously you cannot select a page that is currently hidden.

Change Events

Four events are used in the process of changing the selected page. The first two of these are called Deselecting and Selecting and can be cancelled in order to prevent the selection change. These are then followed by the Deselected and Selected events. The sequence of events would be as follows.

Deselecting sent to page about to lose selection.
Selecting sent to page about to receive selection.
Deselected sent to page that is losing selection.
Selected sent to page that is receiving selection.

The first two events allow both sides of the change to decide if they want to prevent the change from occurring. Maybe the current page wants to prevent a change until an error condition has been corrected. Maybe the target page wants to prevent itself from getting the selection until an operation has completed.

If neither side cancels the event then the switch is committed to occurring and they both get an additional event (the Deselected or Selected) to notify that the change is happening.

Finally one more event is fired at the end of the process. The SelectedPageChanged is fired whenever the SelectedPage property has a new value and this value is actually changed at the end of the process. If you only need to know when the selection changes then this is the event to hook into.

I think that covers all the scenarios developers could need. But if you know of something extra just drop me a line or a comment!

I have recently started working on the first extension to the Toolkit called the Krypton Navigator. Your probably wondering what the control will do, well wonder no more.

In any component suite there are usually several controls to choose from when you need to allow the user to select between different pages. The traditional TabControl achieves it using a collection of TabPages and showing tab headers for selection. The Outlook style control allows selection using a set of headings at the bottom of the control with an overflow area. A Wizard control has a selection of pages but uses buttons for moving forwards and backwards through the list.

All these controls are doing the same thing, allowing the user to move between a set of pages. So why not have just a single control that provides different modes rather than having a range of different controls. This is the purpose of the Krypton Navigator, to provide a range of different user interfaces for allowing the user to navigate around a set of Krypton Page instances.

This has some big advantages for developers. First of all you can expose this extra flexibility to the user of the application. Let them have an option to choose how they prefer to navigate around. They might prefer an outlook style instead of a tab control or vica versa.

Instead of having to delete a control and adding back a different control in order to change the style of navigation you would just need to change the mode setting on the Navgiator. Much easier to manage.

Another advantage is that as new methods of navigating come in and out of fashion a new mode can just be added to the Navigator. You automatically have access to this new mode in the next software release and do not need to learn how to use a completely new control or replace a control in your app.

So thats the concept and I have now started work in earnest. I will begin by adding the easiest and simplest modes first and build up to the more complex ones over time.

If you have seen the logo image on the home page for the Krypton Toolkit you will have noticed the poor effort my Photoshop skills can manage. Instead I have ordered some custom images and here they are.

Rather than spend a minimum of $200 per image by going to a graphic designer I decided to try a different idea. Instead I would find a company that makes icons in the style I like and get them to produce some extra custom icons. This is much cheaper and the four images I have initially commissioned are only $100, that’s the total for all four of them. Plus they are delivered in vector graphic format as well as the usual bitmap, png etc.

So here is the initial design for the Krypton Toolkit…

…the design for the Krypton Navigator…

…the design for a ‘palettes’ image…

…and finally the ‘controls’ image…

After much deliberation I have replaced use of the TextRenderer and gone back to the GDI+ text drawing. It is a simple of case of deciding which has the worst side effects.

On the plus side for the TextRenderer was the more accurate measuring and drawing of text so that controls would be sized very accurately. On the negative side we have the inability to draw text with anti aliasing in the vertical orientation. To begin with I thought this was only going to be a minor annoyance and so worth the price but on reflection that is not the case.

Instead I have rewritten the text drawing, for the third time, to use standard GDI+ drawing. So now we have the use of gradient colors and images for the text and a consistent appearance in all orientations. Dealing with the inaccurate sizing is a pain but within bearable limits.

It is frustrating spending so much time going over the same ground until you reach the right decision but at least I know I have explored all the options!

The great thing about trying to improve performance is the ease with which you can pick off the low hanging fruit to make a meaningful difference.

This was the first time I had run the library through a performance tool so I was hoping that there would be one or two simple changes I could make to boost the library. Not that anyone had complained about the speed of the library.

Sadly I do not have the Team System version of Visual Studio aimed at developers which comes with some nice tools including performance analysis. Being part of the ISV Empower program means I miss out of those goodies as I only get the professional edition.

So instead I had a look around for something cheap but functional. I decided on the ANTS Profiler because it is easy to use and gives enough detail to get going.

After a little investigation it became obvious there was an inefficiency that could be removed to make a big impact. Most of the toolkit controls can have transparency in either the border or background. To allow for this the controls always draw the parent container before the control itself. This ensures that any part of the control that is transparent will show the correct background.

Now if the control does not happen to have any transparent areas then drawing the background is very wasteful. In fact it can be horribly wasteful. You might have a button that sits inside a panel that is in a header group that is on a split container panel. Drawing the button involves asking the parent panel to draw, which in turn then asks for the header group to draw and so forth up the chain.

So I have added some logic that decides if the control has any transparent element and will only ask for the parent background to be drawn when it is required. For my small test application this reduced the execution time by half. Considering this test app was small and so had relatively few layers of controls it means a real world application is likely to benefit even more.

By default the two built in palettes provided with the toolkit have no transparent areas on any of the controls, so they both get maximum benefit from the change. The custom palettes provided in the Palettes installation directory all have rounded edges and so will not benefit to the same extent.

This is a trick worth bearing in mind if you want to improve the drawing performance of the library, make sure your custom palette does not make too much use of transparency on those controls you use most often.